From 65383f2a8967e8d71589100e5d43bb2328c030e7 Mon Sep 17 00:00:00 2001 From: hustcer Date: Fri, 6 Feb 2026 19:25:20 +0800 Subject: [PATCH 1/6] deps: Upgrade @actions/core,@actions/tool-cache,undici,lefthook & semver --- package.json | 16 +- pnpm-lock.yaml | 603 +++++++++++++++++++++++++------------------------ 2 files changed, 321 insertions(+), 298 deletions(-) diff --git a/package.json b/package.json index 6c77a39..657349c 100644 --- a/package.json +++ b/package.json @@ -22,22 +22,22 @@ }, "homepage": "https://github.com/hustcer/setup-nu#readme", "dependencies": { - "@actions/core": "^2.0.2", - "@actions/tool-cache": "^3.0.0", + "@actions/core": "^3.0.0", + "@actions/tool-cache": "^4.0.0", "@octokit/rest": "^22.0.1", "globby": "^16.1.0", "shelljs": "^0.10.0", - "undici": "^7.19.0" + "undici": "^7.20.0" }, "devDependencies": { - "@biomejs/biome": "^2.3.11", - "@types/node": "^25.0.10", + "@biomejs/biome": "^2.3.14", + "@types/node": "^25.2.1", "@types/semver": "^7.7.1", "@types/shelljs": "^0.10.0", "@vercel/ncc": "^0.38.4", - "cspell": "^9.6.0", - "lefthook": "^2.0.15", - "semver": "^7.7.3", + "cspell": "^9.6.4", + "lefthook": "^2.1.0", + "semver": "^7.7.4", "typescript": "^5.9.3" }, "engines": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b6781f2..ada7419 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,11 +12,11 @@ importers: .: dependencies: '@actions/core': - specifier: ^2.0.2 - version: 2.0.2 - '@actions/tool-cache': specifier: ^3.0.0 version: 3.0.0 + '@actions/tool-cache': + specifier: ^4.0.0 + version: 4.0.0 '@octokit/rest': specifier: ^22.0.1 version: 22.0.1 @@ -27,15 +27,15 @@ importers: specifier: ^0.10.0 version: 0.10.0 undici: - specifier: ^7.19.0 - version: 7.19.0 + specifier: ^7.20.0 + version: 7.20.0 devDependencies: '@biomejs/biome': - specifier: ^2.3.11 - version: 2.3.11 + specifier: ^2.3.14 + version: 2.3.14 '@types/node': - specifier: ^25.0.10 - version: 25.0.10 + specifier: ^25.2.1 + version: 25.2.1 '@types/semver': specifier: ^7.7.1 version: 7.7.1 @@ -46,112 +46,124 @@ importers: specifier: ^0.38.4 version: 0.38.4 cspell: - specifier: ^9.6.0 - version: 9.6.0 + specifier: ^9.6.4 + version: 9.6.4 lefthook: - specifier: ^2.0.15 - version: 2.0.15 + specifier: ^2.1.0 + version: 2.1.0 semver: - specifier: ^7.7.3 - version: 7.7.3 + specifier: ^7.7.4 + version: 7.7.4 typescript: specifier: ^5.9.3 version: 5.9.3 packages: - '@actions/core@2.0.2': - resolution: {integrity: sha512-Ast1V7yHbGAhplAsuVlnb/5J8Mtr/Zl6byPPL+Qjq3lmfIgWF1ak1iYfF/079cRERiuTALTXkSuEUdZeDCfGtA==} + '@actions/core@3.0.0': + resolution: {integrity: sha512-zYt6cz+ivnTmiT/ksRVriMBOiuoUpDCJJlZ5KPl2/FRdvwU3f7MPh9qftvbkXJThragzUZieit2nyHUyw53Seg==} - '@actions/exec@2.0.0': - resolution: {integrity: sha512-k8ngrX2voJ/RIN6r9xB82NVqKpnMRtxDoiO+g3olkIUpQNqjArXrCQceduQZCQj3P3xm32pChRLqRrtXTlqhIw==} + '@actions/exec@3.0.0': + resolution: {integrity: sha512-6xH/puSoNBXb72VPlZVm7vQ+svQpFyA96qdDBvhB8eNZOE8LtPf9L4oAsfzK/crCL8YZ+19fKYVnM63Sl+Xzlw==} - '@actions/http-client@3.0.1': - resolution: {integrity: sha512-SbGS8c/vySbNO3kjFgSW77n83C4MQx/Yoe+b1hAdpuvfHxnkHzDq2pWljUpAA56Si1Gae/7zjeZsV0CYjmLo/w==} + '@actions/http-client@4.0.0': + resolution: {integrity: sha512-QuwPsgVMsD6qaPD57GLZi9sqzAZCtiJT8kVBCDpLtxhL5MydQ4gS+DrejtZZPdIYyB1e95uCK9Luyds7ybHI3g==} - '@actions/io@2.0.0': - resolution: {integrity: sha512-Jv33IN09XLO+0HS79aaODsvIRyduiF7NY/F6LYeK5oeUmrsz7aFdRphQjFoESF4jS7lMauDOttKALcpapVDIAg==} + '@actions/io@3.0.2': + resolution: {integrity: sha512-nRBchcMM+QK1pdjO7/idu86rbJI5YHUKCvKs0KxnSYbVe3F51UfGxuZX4Qy/fWlp6l7gWFwIkrOzN+oUK03kfw==} - '@actions/tool-cache@3.0.0': - resolution: {integrity: sha512-JBx8gEWuu8Lqaqx/hEnL6QdKvF06suBR4y+dBDi9vJbHx1r+p6QtmBKhQYhiKjDUYIoDX1bUrbyAYPChoPK+XA==} + '@actions/tool-cache@4.0.0': + resolution: {integrity: sha512-L8P9HbXvpvqjZDveb/fdsa55IVC0trfPgQ4ZwGo6r5af6YDVdM9vMGPZ7rgY2fAT9gGj4PSYd6bYlg3p3jD78A==} - '@biomejs/biome@2.3.11': - resolution: {integrity: sha512-/zt+6qazBWguPG6+eWmiELqO+9jRsMZ/DBU3lfuU2ngtIQYzymocHhKiZRyrbra4aCOoyTg/BmY+6WH5mv9xmQ==} + '@biomejs/biome@2.3.14': + resolution: {integrity: sha512-QMT6QviX0WqXJCaiqVMiBUCr5WRQ1iFSjvOLoTk6auKukJMvnMzWucXpwZB0e8F00/1/BsS9DzcKgWH+CLqVuA==} engines: {node: '>=14.21.3'} hasBin: true - '@biomejs/cli-darwin-arm64@2.3.11': - resolution: {integrity: sha512-/uXXkBcPKVQY7rc9Ys2CrlirBJYbpESEDme7RKiBD6MmqR2w3j0+ZZXRIL2xiaNPsIMMNhP1YnA+jRRxoOAFrA==} + '@biomejs/cli-darwin-arm64@2.3.14': + resolution: {integrity: sha512-UJGPpvWJMkLxSRtpCAKfKh41Q4JJXisvxZL8ChN1eNW3m/WlPFJ6EFDCE7YfUb4XS8ZFi3C1dFpxUJ0Ety5n+A==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [darwin] - '@biomejs/cli-darwin-x64@2.3.11': - resolution: {integrity: sha512-fh7nnvbweDPm2xEmFjfmq7zSUiox88plgdHF9OIW4i99WnXrAC3o2P3ag9judoUMv8FCSUnlwJCM1B64nO5Fbg==} + '@biomejs/cli-darwin-x64@2.3.14': + resolution: {integrity: sha512-PNkLNQG6RLo8lG7QoWe/hhnMxJIt1tEimoXpGQjwS/dkdNiKBLPv4RpeQl8o3s1OKI3ZOR5XPiYtmbGGHAOnLA==} engines: {node: '>=14.21.3'} cpu: [x64] os: [darwin] - '@biomejs/cli-linux-arm64-musl@2.3.11': - resolution: {integrity: sha512-XPSQ+XIPZMLaZ6zveQdwNjbX+QdROEd1zPgMwD47zvHV+tCGB88VH+aynyGxAHdzL+Tm/+DtKST5SECs4iwCLg==} + '@biomejs/cli-linux-arm64-musl@2.3.14': + resolution: {integrity: sha512-LInRbXhYujtL3sH2TMCH/UBwJZsoGwfQjBrMfl84CD4hL/41C/EU5mldqf1yoFpsI0iPWuU83U+nB2TUUypWeg==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] + libc: [musl] - '@biomejs/cli-linux-arm64@2.3.11': - resolution: {integrity: sha512-l4xkGa9E7Uc0/05qU2lMYfN1H+fzzkHgaJoy98wO+b/7Gl78srbCRRgwYSW+BTLixTBrM6Ede5NSBwt7rd/i6g==} + '@biomejs/cli-linux-arm64@2.3.14': + resolution: {integrity: sha512-KT67FKfzIw6DNnUNdYlBg+eU24Go3n75GWK6NwU4+yJmDYFe9i/MjiI+U/iEzKvo0g7G7MZqoyrhIYuND2w8QQ==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] + libc: [glibc] - '@biomejs/cli-linux-x64-musl@2.3.11': - resolution: {integrity: sha512-vU7a8wLs5C9yJ4CB8a44r12aXYb8yYgBn+WeyzbMjaCMklzCv1oXr8x+VEyWodgJt9bDmhiaW/I0RHbn7rsNmw==} + '@biomejs/cli-linux-x64-musl@2.3.14': + resolution: {integrity: sha512-KQU7EkbBBuHPW3/rAcoiVmhlPtDSGOGRPv9js7qJVpYTzjQmVR+C9Rfcz+ti8YCH+zT1J52tuBybtP4IodjxZQ==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] + libc: [musl] - '@biomejs/cli-linux-x64@2.3.11': - resolution: {integrity: sha512-/1s9V/H3cSe0r0Mv/Z8JryF5x9ywRxywomqZVLHAoa/uN0eY7F8gEngWKNS5vbbN/BsfpCG5yeBT5ENh50Frxg==} + '@biomejs/cli-linux-x64@2.3.14': + resolution: {integrity: sha512-ZsZzQsl9U+wxFrGGS4f6UxREUlgHwmEfu1IrXlgNFrNnd5Th6lIJr8KmSzu/+meSa9f4rzFrbEW9LBBA6ScoMA==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] + libc: [glibc] - '@biomejs/cli-win32-arm64@2.3.11': - resolution: {integrity: sha512-PZQ6ElCOnkYapSsysiTy0+fYX+agXPlWugh6+eQ6uPKI3vKAqNp6TnMhoM3oY2NltSB89hz59o8xIfOdyhi9Iw==} + '@biomejs/cli-win32-arm64@2.3.14': + resolution: {integrity: sha512-+IKYkj/pUBbnRf1G1+RlyA3LWiDgra1xpS7H2g4BuOzzRbRB+hmlw0yFsLprHhbbt7jUzbzAbAjK/Pn0FDnh1A==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [win32] - '@biomejs/cli-win32-x64@2.3.11': - resolution: {integrity: sha512-43VrG813EW+b5+YbDbz31uUsheX+qFKCpXeY9kfdAx+ww3naKxeVkTD9zLIWxUPfJquANMHrmW3wbe/037G0Qg==} + '@biomejs/cli-win32-x64@2.3.14': + resolution: {integrity: sha512-oizCjdyQ3WJEswpb3Chdngeat56rIdSYK12JI3iI11Mt5T5EXcZ7WLuowzEaFPNJ3zmOQFliMN8QY1Pi+qsfdQ==} engines: {node: '>=14.21.3'} cpu: [x64] os: [win32] - '@cspell/cspell-bundled-dicts@9.6.0': - resolution: {integrity: sha512-gLNe9bB+5gMsTEhR9YPE0Wt122HR2EV+Q1j9W+MbwbeBJmpTWrgAP1ZdpvHOg+6LF6x/bD/EC9HfWdd/om8wXA==} + '@cspell/cspell-bundled-dicts@9.6.4': + resolution: {integrity: sha512-OIiPQuB7XQ6rnUv4KaCwHr9vNwbh6VZ4GfgQjcThT0oz0hkL6E5Ar3tq54K9jyqE9ylcHqpRuXUgnKgio6Hlig==} engines: {node: '>=20'} - '@cspell/cspell-json-reporter@9.6.0': - resolution: {integrity: sha512-5sY1lgAXS5xEOsjT5rREMADj7pHIt56XOL7xR80nNl0TwlpZbeBHhoB2aH5sirVTeodJFN5iraXNbVOYPPupPw==} + '@cspell/cspell-json-reporter@9.6.4': + resolution: {integrity: sha512-rGYSDnDWACrUyovfN8M/LM8CCFSKjYd2kehbNS7YMPk0Jk+rLk6sgt5WYu3ty45otXCkiO07bjUo/81wBLet7A==} engines: {node: '>=20'} - '@cspell/cspell-pipe@9.6.0': - resolution: {integrity: sha512-YNuY8NNXfE+8Qzknm2ps6QbrZLZu6rSZTZr3dYW3K6TK7+IFVlJ6e2Z9iKJTqp6aZ4AGU/r9QYGmNX4Oq4gZ0A==} + '@cspell/cspell-performance-monitor@9.6.4': + resolution: {integrity: sha512-exuqxV1IVfZkasg57ZjUbaHeZDd6Mdbsbe5FBT3+XaVnRij+wpY2oEW9+kIOL5MOQE3bgQKgu37iMtA1NlCrGA==} + engines: {node: '>=20.18'} + + '@cspell/cspell-pipe@9.6.4': + resolution: {integrity: sha512-vVxajTG9Ko01oHk8HPsMLajcLrd9AfkOk6vdgFI4FD7ZPq1CY0hfTmfmJ8bzZ4/QkqXglTvePdSgHQVJeltwWw==} engines: {node: '>=20'} - '@cspell/cspell-resolver@9.6.0': - resolution: {integrity: sha512-Gb2UWNmRpTOQGpYL4Q/LMw+b50KcRZcf/wJg6w0Yl3IT+F/uDNhNh1f5rHuTyGsbMsMxHJhsb2AoP+73GlbIfw==} + '@cspell/cspell-resolver@9.6.4': + resolution: {integrity: sha512-3xsgZEqqH9Uj8ZYLBnWbnsHz8wphgaeuWKcNDqgwoMjvwTMQLGoXjHht8Jx5yxd2e080lB7fJax8TaBdCzmFFA==} engines: {node: '>=20'} - '@cspell/cspell-service-bus@9.6.0': - resolution: {integrity: sha512-DCuKKkySTEB8MPLTdoPMdmakYcx7XCsHz1YEMbzOcLqJCxXsRlRZg4qE9kRBee/2QY7eYA2kaYNgn/TDMooa4g==} + '@cspell/cspell-service-bus@9.6.4': + resolution: {integrity: sha512-oGNEzP1gJ43rLklJQjOk5PsfX0mZkLjV19djGptb9xZQeC2qAUxnaAbZtWt5CE8ni2iiTaRmgNRbUqAhRCnjew==} engines: {node: '>=20'} - '@cspell/cspell-types@9.6.0': - resolution: {integrity: sha512-JTqrD47tV+rWc1y2W8T0NTfWLQMlSWX4OF64/Jf3WbsOD+4UXVIfjRlzPry7+1Zekm6pa38+23jkDBytYpu8yw==} + '@cspell/cspell-types@9.6.4': + resolution: {integrity: sha512-lf6d+BdMkJIFCxx2FpajLpqVGGyaGUNFU6jhEM6QUPeGuoA5et2kJXrL0NSY2uWLOVyYYc/FPjzlbe8trA9tBQ==} engines: {node: '>=20'} + '@cspell/cspell-worker@9.6.4': + resolution: {integrity: sha512-anacKDOZzDfPzuDeFOXGI2tFBYiRRCSnIZP/AOyJ9zTvEQcqq5p/ak18nJ5OQyDr2NG7ovJiCDT5YNiH2Vdg/g==} + engines: {node: '>=20.18'} + '@cspell/dict-ada@4.1.1': resolution: {integrity: sha512-E+0YW9RhZod/9Qy2gxfNZiHJjCYFlCdI69br1eviQQWB8yOTJX0JHXLs79kOYhSW0kINPVUdvddEBe6Lu6CjGQ==} @@ -197,14 +209,14 @@ packages: '@cspell/dict-elixir@4.0.8': resolution: {integrity: sha512-CyfphrbMyl4Ms55Vzuj+mNmd693HjBFr9hvU+B2YbFEZprE5AG+EXLYTMRWrXbpds4AuZcvN3deM2XVB80BN/Q==} - '@cspell/dict-en-common-misspellings@2.1.11': - resolution: {integrity: sha512-2jcY494If1udvzd7MT2z/QH/RACUo/I02vIY4ttNdZhgYvUmRKhg8OBdrbzYo0lJOcc7XUb8rhIFQRHzxOSVeA==} + '@cspell/dict-en-common-misspellings@2.1.12': + resolution: {integrity: sha512-14Eu6QGqyksqOd4fYPuRb58lK1Va7FQK9XxFsRKnZU8LhL3N+kj7YKDW+7aIaAN/0WGEqslGP6lGbQzNti8Akw==} - '@cspell/dict-en-gb-mit@3.1.16': - resolution: {integrity: sha512-4PPdapCJslytxAVJu35Mv97qDyGmAQxtDE790T2bWNhcqN6gvRVAc/eTRaXkUIf21q1xCxxNNqpH4VfMup69rQ==} + '@cspell/dict-en-gb-mit@3.1.17': + resolution: {integrity: sha512-MLx+3XN9rj+EGwLIFmh0gpEDNalCyQqjcszp+WkedCHcvTCzQgWXQMZK6cPuhO/OKYyW9GOwsx4t0wjU5tRVNg==} - '@cspell/dict-en_us@4.4.27': - resolution: {integrity: sha512-0y4vH2i5cFmi8sxkc4OlD2IlnqDznOtKczm4h6jA288g5VVrm3bhkYK6vcB8b0CoRKtYWKet4VEmHBP1yI+Qfw==} + '@cspell/dict-en_us@4.4.28': + resolution: {integrity: sha512-/rzhbZaZDsDWmXbc9Fmmr4/ngmaNcG2b+TGT+ZjGqpOXVQYI75yZ9+XduyI43xJ5O38QcX3QIbJY5GWaJqxPEg==} '@cspell/dict-filetypes@3.0.15': resolution: {integrity: sha512-uDMeqYlLlK476w/muEFQGBy9BdQWS0mQ7BJiy/iQv5XUWZxE2O54ZQd9nW8GyQMzAgoyg5SG4hf9l039Qt66oA==} @@ -218,14 +230,14 @@ packages: '@cspell/dict-fsharp@1.1.1': resolution: {integrity: sha512-imhs0u87wEA4/cYjgzS0tAyaJpwG7vwtC8UyMFbwpmtw+/bgss+osNfyqhYRyS/ehVCWL17Ewx2UPkexjKyaBA==} - '@cspell/dict-fullstack@3.2.7': - resolution: {integrity: sha512-IxEk2YAwAJKYCUEgEeOg3QvTL4XLlyArJElFuMQevU1dPgHgzWElFevN5lsTFnvMFA1riYsVinqJJX0BanCFEg==} + '@cspell/dict-fullstack@3.2.8': + resolution: {integrity: sha512-J6EeoeThvx/DFrcA2rJiCA6vfqwJMbkG0IcXhlsmRZmasIpanmxgt90OEaUazbZahFiuJT8wrhgQ1QgD1MsqBw==} '@cspell/dict-gaming-terms@1.1.2': resolution: {integrity: sha512-9XnOvaoTBscq0xuD6KTEIkk9hhdfBkkvJAIsvw3JMcnp1214OCGW8+kako5RqQ2vTZR3Tnf3pc57o7VgkM0q1Q==} - '@cspell/dict-git@3.0.7': - resolution: {integrity: sha512-odOwVKgfxCQfiSb+nblQZc4ErXmnWEnv8XwkaI4sNJ7cNmojnvogYVeMqkXPjvfrgEcizEEA4URRD2Ms5PDk1w==} + '@cspell/dict-git@3.1.0': + resolution: {integrity: sha512-KEt9zGkxqGy2q1nwH4CbyqTSv5nadpn8BAlDnzlRcnL0Xb3LX9xTgSGShKvzb0bw35lHoYyLWN2ZKAqbC4pgGQ==} '@cspell/dict-golang@6.0.26': resolution: {integrity: sha512-YKA7Xm5KeOd14v5SQ4ll6afe9VSy3a2DWM7L9uBq4u3lXToRBQ1W5PRa+/Q9udd+DTURyVVnQ+7b9cnOlNxaRg==} @@ -254,8 +266,8 @@ packages: '@cspell/dict-kotlin@1.1.1': resolution: {integrity: sha512-J3NzzfgmxRvEeOe3qUXnSJQCd38i/dpF9/t3quuWh6gXM+krsAXP75dY1CzDmS8mrJAlBdVBeAW5eAZTD8g86Q==} - '@cspell/dict-latex@4.0.4': - resolution: {integrity: sha512-YdTQhnTINEEm/LZgTzr9Voz4mzdOXH7YX+bSFs3hnkUHCUUtX/mhKgf1CFvZ0YNM2afjhQcmLaR9bDQVyYBvpA==} + '@cspell/dict-latex@5.0.0': + resolution: {integrity: sha512-HUrIqUVohM6P0+5b7BsdAdb0STIv0aaFBvguI7pLcreljlcX3FSPUxea7ticzNlCNeVrEaiEn/ws9m6rYUeuNw==} '@cspell/dict-lorem-ipsum@4.0.5': resolution: {integrity: sha512-9a4TJYRcPWPBKkQAJ/whCu4uCAEgv/O2xAaZEI0n4y1/l18Yyx8pBKoIX5QuVXjjmKEkK7hi5SxyIsH7pFEK9Q==} @@ -277,11 +289,11 @@ packages: '@cspell/dict-monkeyc@1.0.12': resolution: {integrity: sha512-MN7Vs11TdP5mbdNFQP5x2Ac8zOBm97ARg6zM5Sb53YQt/eMvXOMvrep7+/+8NJXs0jkp70bBzjqU4APcqBFNAw==} - '@cspell/dict-node@5.0.8': - resolution: {integrity: sha512-AirZcN2i84ynev3p2/1NCPEhnNsHKMz9zciTngGoqpdItUb2bDt1nJBjwlsrFI78GZRph/VaqTVFwYikmncpXg==} + '@cspell/dict-node@5.0.9': + resolution: {integrity: sha512-hO+ga+uYZ/WA4OtiMEyKt5rDUlUyu3nXMf8KVEeqq2msYvAPdldKBGH7lGONg6R/rPhv53Rb+0Y1SLdoK1+7wQ==} - '@cspell/dict-npm@5.2.29': - resolution: {integrity: sha512-ZAef8JpYmbuHFT1zekj/YyImLPvZevjECw663EmG5GPePyNo4AfH8Dd2fFhaOyQ3P5I5LrkAhGwypnOfUxcssw==} + '@cspell/dict-npm@5.2.32': + resolution: {integrity: sha512-H0XD0eg4d96vevle8VUKVoPhsgsw003ByJ47XzipyiMKoQTZ2IAUW+VTkQq8wU1floarNjmThQJOoKL9J4UYuw==} '@cspell/dict-php@4.1.1': resolution: {integrity: sha512-EXelI+4AftmdIGtA8HL8kr4WlUE11OqCSVlnIgZekmTkEGSZdYnkFdiJ5IANSALtlQ1mghKjz+OFqVs6yowgWA==} @@ -301,8 +313,8 @@ packages: '@cspell/dict-ruby@5.1.0': resolution: {integrity: sha512-9PJQB3cfkBULrMLp5kSAcFPpzf8oz9vFN+QYZABhQwWkGbuzCIXSorHrmWSASlx4yejt3brjaWS57zZ/YL5ZQQ==} - '@cspell/dict-rust@4.1.1': - resolution: {integrity: sha512-fXiXnZH0wOaEVTKFRNaz6TsUGhuB8dAT0ubYkDNzRQCaV5JGSOebGb1v2x5ZrOSVp+moxWM/vdBfiNU6KOEaFQ==} + '@cspell/dict-rust@4.1.2': + resolution: {integrity: sha512-O1FHrumYcO+HZti3dHfBPUdnDFkI+nbYK3pxYmiM1sr+G0ebOd6qchmswS0Wsc6ZdEVNiPYJY/gZQR6jfW3uOg==} '@cspell/dict-scala@5.0.9': resolution: {integrity: sha512-AjVcVAELgllybr1zk93CJ5wSUNu/Zb5kIubymR/GAYkMyBdYFCZ3Zbwn4Zz8GJlFFAbazABGOu0JPVbeY59vGg==} @@ -334,25 +346,25 @@ packages: '@cspell/dict-zig@1.0.0': resolution: {integrity: sha512-XibBIxBlVosU06+M6uHWkFeT0/pW5WajDRYdXG2CgHnq85b0TI/Ks0FuBJykmsgi2CAD3Qtx8UHFEtl/DSFnAQ==} - '@cspell/dynamic-import@9.6.0': - resolution: {integrity: sha512-Lkn82wyGj2ltxeYfH2bEjshdes1fx3ouYUZxeW5i6SBBvEVJoSmr43AygI8A317UMIQxVj59qVBorrtGYcRI1w==} + '@cspell/dynamic-import@9.6.4': + resolution: {integrity: sha512-1VnL9ahT3s17DLWl4MeO1pYg7zcVT3X9cKynI2/U86zNK5xMGS5icvjp7X65tsCAVNcWOtkqVFfrxi7kWxn67g==} engines: {node: '>=20'} - '@cspell/filetypes@9.6.0': - resolution: {integrity: sha512-CaWyk5j20H6sr+HCArtUY95jUQb7A/6W0GC4B4umnqoWvgqwR72duowLFa+w1K2C7tZg3GoV4Wf2cUn9jjt5FA==} + '@cspell/filetypes@9.6.4': + resolution: {integrity: sha512-a1aZ/8vGnhTknxTukjzo3m8CISyHW2MWnbedywg5SDEl5RMJitmzX90QZiQdSvEcqzqmtoAgSEZNBT2LX2gIKg==} engines: {node: '>=20'} - '@cspell/strong-weak-map@9.6.0': - resolution: {integrity: sha512-9g8LCLv/2RrprGeGnFAaBETWq7ESnBcoMbvgNu+vZE58iF+pbFvP0qGgKvVeKEEpc2LZhNuHLsUH37MUS6DOQg==} - engines: {node: '>=20'} + '@cspell/rpc@9.6.4': + resolution: {integrity: sha512-vGI1788Rx5Yml9N1/pD4zGd8Vrchi2Y01ADf9NiiOaNVVdf4PU1GCssLCsiIzhYQneErpQ8pJi/mS2F/QMZbRA==} + engines: {node: '>=20.18'} - '@cspell/url@9.6.0': - resolution: {integrity: sha512-257WOxh9vOYHAVgBNXRCdLEd+ldzlVbzcc9u+6DYoCDCNGe0OvOWOGsAfnUbMc9xEw48XgBlDYgOlPbjWGLOTg==} + '@cspell/strong-weak-map@9.6.4': + resolution: {integrity: sha512-AQrUbA0JUOEQgwItnfUQ6Ydk0hWY/uV3VhLwZWyrnT9eiQynmTnRTHtOCkkSl9+M4P0N4Raa2eGFRLcPAFksaw==} engines: {node: '>=20'} - '@fastify/busboy@2.1.1': - resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} - engines: {node: '>=14'} + '@cspell/url@9.6.4': + resolution: {integrity: sha512-h6VMlb7bDyGJfwLtipxxtHlT+ojzUXZz14AqZ/NEzY3LfOhfJTGpRcWLYFsgG/L0Ma4qjsYbPJt/Sj1C14j0VA==} + engines: {node: '>=20'} '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} @@ -422,8 +434,8 @@ packages: resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} engines: {node: '>=18'} - '@types/node@25.0.10': - resolution: {integrity: sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg==} + '@types/node@25.2.1': + resolution: {integrity: sha512-CPrnr8voK8vC6eEtyRzvMpgp3VyVRhgclonE7qYi6P9sXwYb59ucfrnmFBTaP0yUi8Gk4yZg/LlTJULGxvTNsg==} '@types/semver@7.7.1': resolution: {integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==} @@ -465,8 +477,8 @@ packages: resolution: {integrity: sha512-LWAxzHqdHsAZlPlEyJ2Poz6AIs384mPeqLVCru2p0BrP9G/kVGuhNyZYClLO6cXlnuJjzC8xtsJIuMjKqLXoAw==} engines: {node: '>=8'} - commander@14.0.2: - resolution: {integrity: sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==} + commander@14.0.3: + resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==} engines: {node: '>=20'} comment-json@4.5.1: @@ -480,50 +492,50 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} - cspell-config-lib@9.6.0: - resolution: {integrity: sha512-5ztvheawkmFXNHGN82iOOntU3T5mmlQBP/plgoKdBZ6+lSYrOJLkOyqxYyi7MrUBDtWrXPzFllkBrPNRDlbX/A==} + cspell-config-lib@9.6.4: + resolution: {integrity: sha512-MecJNR9bIlcPBhyZFsXP6Q2n8qQ2IR9N9HiIz0yh0gBNVydp3LR5JITP5Ji8m7hexmZzVeoXms/dVN74XbS95g==} engines: {node: '>=20'} - cspell-dictionary@9.6.0: - resolution: {integrity: sha512-wW0m1kLrbK6bRY/GrLUGKUUJ1Z4ZUgIb8LD4zNaECcvGviv9V7VcR3mEwUip3ZjoHa3ClzEoWgQ9gXrtac80Wg==} + cspell-dictionary@9.6.4: + resolution: {integrity: sha512-Ik9ZQVqV/fJfMt5X6IkC7yHGVH46/qjcqCNWwrMSwvROLM3SemNxxZoLvh0wi0GXz9WF1lHcxLJVdeKUk6QB8g==} engines: {node: '>=20'} - cspell-gitignore@9.6.0: - resolution: {integrity: sha512-8GfmJuRBBvibyPHnNE2wYJAiQ/ceDYLD1X1sUQaCyj6hPMR7ChJiVhFPtS11hMqkjZ46OBMYTMGWqO792L9fEQ==} + cspell-gitignore@9.6.4: + resolution: {integrity: sha512-a8asE9BsjJgJ506WUGh5VHrTdVEE8hWELjCJB2atPrW6iY5e4aCIugy0gkRC1ZH9/TseadlmMLrFzHUkJUjzsg==} engines: {node: '>=20'} hasBin: true - cspell-glob@9.6.0: - resolution: {integrity: sha512-KmEbKN0qdEamsEYbkFu7zjLYfw3hMmn9kmeh94IHr2kq6vWq5vNP5l1BuqmrUeFZlbNd07vj08IKAZHYsoGheQ==} + cspell-glob@9.6.4: + resolution: {integrity: sha512-253VrjbR8QU15h8GtpDQLX5Ti9uNSuNod2T7f8YEElQOb9I/kUXoCj3Cq4P390IC99klqSHIDxHsxd77ex19lA==} engines: {node: '>=20'} - cspell-grammar@9.6.0: - resolution: {integrity: sha512-jZVIM5/3eB9rWURDq+VXdYip+DmPuFzO+bqaRtzqT8w6YoOIGYbiIxdwvyyA9xdH7SmW8uqHJP5x4pzZju1lNQ==} + cspell-grammar@9.6.4: + resolution: {integrity: sha512-rvZyTB45/XSRWx7eAsrvTTAZvBTREr/2G2JWVMdqrptFyq1XReAKHhw/x1HJkNgWC9LKAK3bVQJpjLsNG37U9A==} engines: {node: '>=20'} hasBin: true - cspell-io@9.6.0: - resolution: {integrity: sha512-wZuZzKOYIb698kVEINYjGaNFQu+AFZ945TORM3hapmPjez+vsHwl8m/pPpCHeGMpQtHMEDkX84AbQ7R55MRIwg==} + cspell-io@9.6.4: + resolution: {integrity: sha512-bmvJ4yn5QK2FZWTkZA4sx2qJqIi8BrUUUV7W209drSwkYjhJtXqP0RyF6Qx4Xuu2D1s0UilEtO5Jd+E9UJkQ6w==} engines: {node: '>=20'} - cspell-lib@9.6.0: - resolution: {integrity: sha512-m9rIv8hkQ3Dio4s80HQbM9cdxENcd6pS8j2AHWL50OSjJf3Xhw6/wMrIAGbwLHP15K6QZVU2eJ/abCzIJwjA4w==} + cspell-lib@9.6.4: + resolution: {integrity: sha512-fUodKcIHTwvokuowB25XyFzBxlk73yj1QRw2por3BxDz9fAim1zAIohAPAnGuzj3LowYnTMjHLYE7RFDUSxy5A==} engines: {node: '>=20'} - cspell-trie-lib@9.6.0: - resolution: {integrity: sha512-L7GSff5F9cF60QT78WsebVlb3sppi6jbvTHwsw7WF1jUN/ioAo7OzBYtYB7xkYeejcdVEpqfvf/ZOXPDp8x2Wg==} + cspell-trie-lib@9.6.4: + resolution: {integrity: sha512-JKwyRtyybbaTrixwI1OgU5Hvva2Z5zHVWl92WBa9U7KijAyiD/Ehp3T3DCYuBwGks7egw7MgWPySkXXnpme6mw==} engines: {node: '>=20'} peerDependencies: - '@cspell/cspell-types': 9.6.0 + '@cspell/cspell-types': 9.6.4 - cspell@9.6.0: - resolution: {integrity: sha512-Mpf0oT2KAHTIb3YPAXWhW64/4CZKW5Lka4j1YxCLK3jM3nenmIsY/ocrJvqCMF4+1eejRF0N55sT3XmrijI5YQ==} - engines: {node: '>=20'} + cspell@9.6.4: + resolution: {integrity: sha512-rZJmgcyBGKX3KcJ3KC9JYVHeKhDEVbmCheSp8eRGMYw6MCG9o7FHqQjGA/u4lEu4A0psr7ACP/5ym/QHyntRbA==} + engines: {node: '>=20.18'} hasBin: true - env-paths@3.0.0: - resolution: {integrity: sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + env-paths@4.0.0: + resolution: {integrity: sha512-pxP8eL2SwwaTRi/KHYwLYXinDs7gL3jxFcBYmEdYfZmZXbaVDvdppd0XBU8qVz03rDfKZMXg1omHCbsJjZrMsw==} + engines: {node: '>=20'} esprima@4.0.1: resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} @@ -622,6 +634,10 @@ packages: resolution: {integrity: sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==} engines: {node: '>=12'} + is-safe-filename@0.1.1: + resolution: {integrity: sha512-4SrR7AdnY11LHfDKTZY1u6Ga3RuxZdl3YKWWShO5iyuG5h8QS4GD2tOb04peBJ5I7pXbR+CGBNEhTcwK+FzN3g==} + engines: {node: '>=20'} + is-stream@2.0.1: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} @@ -629,58 +645,58 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - lefthook-darwin-arm64@2.0.15: - resolution: {integrity: sha512-ygAqG/NzOgY9bEiqeQtiOmCRTtp9AmOd3eyrpEaSrRB9V9f3RHRgWDrWbde9BiHSsCzcbeY9/X2NuKZ69eUsNA==} + lefthook-darwin-arm64@2.1.0: + resolution: {integrity: sha512-u2hjHLQXWSFfzO7ln2n/uEydSzfC9sc5cDC7tvKSuOdhvBwaJ0AQ7ZeuqqCQ4YfVIJfYOom1SVE9CBd10FVyig==} cpu: [arm64] os: [darwin] - lefthook-darwin-x64@2.0.15: - resolution: {integrity: sha512-3wA30CzdSL5MFKD6dk7v8BMq7ScWQivpLbmIn3Pv67AaBavN57N/hcdGqOFnDDFI5WazVwDY7UqDfMIk5HZjEA==} + lefthook-darwin-x64@2.1.0: + resolution: {integrity: sha512-zz5rcyrtOZpxon7uE+c0KC/o2ypJeLZql5CL0Y9oaTuECbmhfokm8glsGnyWstW/++PuMpZYYr/qsCJA5elxkQ==} cpu: [x64] os: [darwin] - lefthook-freebsd-arm64@2.0.15: - resolution: {integrity: sha512-FbYBBLVbX8BjdO+icN1t/pC3TOW3FAvTKv/zggBKNihv6jHNn/3s/0j2xIS0k0Pw9oOE7MVmEni3qp2j5vqHrQ==} + lefthook-freebsd-arm64@2.1.0: + resolution: {integrity: sha512-+mXNCNuFHNGYLrDqYWDeHH7kWCLCJFPpspx5PAAm+PD37PRMZJrTqDbaNK9qCghC1tdmT4/Lvilf/ewXHPlaKw==} cpu: [arm64] os: [freebsd] - lefthook-freebsd-x64@2.0.15: - resolution: {integrity: sha512-udHMjh1E8TfC0Z7Y249XZMATJOyj1Jxlj9JoEinkoBvAsePFKDEQg5teuXuTGhjsHYpqVekfSvLNNfHKUUbbjw==} + lefthook-freebsd-x64@2.1.0: + resolution: {integrity: sha512-+AU2HD7szuDsUdHue/E3OnF84B2ae/h7CGKpuIUHJntgoJ4kxf89oDvq2/xl8kDCn9cT76UUjgeZUgFYLRj+6Q==} cpu: [x64] os: [freebsd] - lefthook-linux-arm64@2.0.15: - resolution: {integrity: sha512-1HAPmdYhfcOlubv63sTnWtW2rFuC+kT1MvC3JvdrS5V6zrOImbBSnYZMJX/Dd3w4pm0x2ZJb9T+uef8a0jUQkg==} + lefthook-linux-arm64@2.1.0: + resolution: {integrity: sha512-KM70eV1tsEib1/tk+3TFxIdH84EaYlIg5KTQWAg+LB1N23nTQ7lL4Dnh1je6f6KW4tf21nmoMUqsh0xvMkQk8Q==} cpu: [arm64] os: [linux] - lefthook-linux-x64@2.0.15: - resolution: {integrity: sha512-Pho87mlNFH47zc4fPKzQSp8q9sWfIFW/KMMZfx/HZNmX25aUUTOqMyRwaXxtdAo/hNJ9FX4JeuZWq9Y3iyM5VA==} + lefthook-linux-x64@2.1.0: + resolution: {integrity: sha512-6Bxmv+l7LiYq9W0IE6v2lmlRtBp6pisnlzhcouMGvH3rDwEGw11NAyRJZA3IPGEMAkIuhnlnVTUwAUzKomfJLg==} cpu: [x64] os: [linux] - lefthook-openbsd-arm64@2.0.15: - resolution: {integrity: sha512-pet03Edlj1QeFUgxcIK1xu8CeZA+ejYplvPgdfe//69+vQFGSDaEx3H2mVx8RqzWfmMbijM2/WfkZXR2EVw3bw==} + lefthook-openbsd-arm64@2.1.0: + resolution: {integrity: sha512-ppJNK0bBSPLC8gqksRw5zI/0uLeMA5cK+hmZ4ofcuGNmdrN1dfl2Tx84fdeef0NcQY0ii9Y3j3icIKngIoid/g==} cpu: [arm64] os: [openbsd] - lefthook-openbsd-x64@2.0.15: - resolution: {integrity: sha512-i+a364CcSAeIO5wQzLMHsthHt/v6n3XwhKmRq/VBzPOUv9KutNeF55yCE/6lvuvzwxpdEfBjh6cXPERC0yp98w==} + lefthook-openbsd-x64@2.1.0: + resolution: {integrity: sha512-8k9lQsMYqQGu4spaQ8RNSOJidxIcOyfaoF2FPZhthtBfRV3cgVFGrsQ0hbIi5pvQRGUlCqYuCN79qauXHmnL3Q==} cpu: [x64] os: [openbsd] - lefthook-windows-arm64@2.0.15: - resolution: {integrity: sha512-69u5GdVOT4QIxc2TK5ce0cTXLzwB55Pk9ZnnJNFf1XsyZTGcg9bUWYYTyD12CIIXbVTa0RVXIIrbU9UgP8O1AQ==} + lefthook-windows-arm64@2.1.0: + resolution: {integrity: sha512-0WN+grrxt9zP9NGRcztoPXcz25tteem91rfLWgQFab+50csJ47zldlsB7/eOS/eHG5mUg5g5NPR4XefnXtjOcQ==} cpu: [arm64] os: [win32] - lefthook-windows-x64@2.0.15: - resolution: {integrity: sha512-/zYEndCUgj8XK+4wvLYLRk3AcfKU6zWf2GHx+tcZ4K2bLaQdej4m+OqmQsVpUlF8N2tN9hfwlj1D50uz75LUuQ==} + lefthook-windows-x64@2.1.0: + resolution: {integrity: sha512-XbO/5nAZQLpUn0tPpgCYfFBFJHnymSglQ73jD6wymNrR1j8I5EcXGlP6YcLhnZ83yzsdLC+gup+N6IqUeiyRdw==} cpu: [x64] os: [win32] - lefthook@2.0.15: - resolution: {integrity: sha512-sl5rePO6UUOLKp6Ci+MMKOc86zicBaPUCvSw2Cq4gCAgTmxpxhIjhz7LOu2ObYerVRPpTq3gvzPTjI71UotjnA==} + lefthook@2.1.0: + resolution: {integrity: sha512-+vS+yywGQW6CN1J1hbGkez//6ixGHIQqfxDN/d3JDm531w9GfGt2lAWTDfZTw/CEl80XsN0raFcnEraR3ldw9g==} hasBin: true merge-stream@2.0.0: @@ -744,12 +760,8 @@ packages: run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - - semver@7.7.3: - resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} + semver@7.7.4: + resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} engines: {node: '>=10'} hasBin: true @@ -800,12 +812,12 @@ packages: undici-types@7.16.0: resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} - undici@5.29.0: - resolution: {integrity: sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==} - engines: {node: '>=14.0'} + undici@6.23.0: + resolution: {integrity: sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==} + engines: {node: '>=18.17'} - undici@7.19.0: - resolution: {integrity: sha512-Heho1hJD81YChi+uS2RkSjcVO+EQLmLSyUlHyp7Y/wFbxQaGb4WXVKD073JytrjXJVkSZVzoE2MCSOKugFGtOQ==} + undici@7.20.0: + resolution: {integrity: sha512-MJZrkjyd7DeC+uPZh+5/YaMDxFiiEEaDgbUSVMXayofAkDWF1088CDo+2RPg7B1BuS1qf1vgNE7xqwPxE0DuSQ==} engines: {node: '>=20.18.1'} unicorn-magic@0.4.0: @@ -837,66 +849,66 @@ packages: snapshots: - '@actions/core@2.0.2': + '@actions/core@3.0.0': dependencies: - '@actions/exec': 2.0.0 - '@actions/http-client': 3.0.1 + '@actions/exec': 3.0.0 + '@actions/http-client': 4.0.0 - '@actions/exec@2.0.0': + '@actions/exec@3.0.0': dependencies: - '@actions/io': 2.0.0 + '@actions/io': 3.0.2 - '@actions/http-client@3.0.1': + '@actions/http-client@4.0.0': dependencies: tunnel: 0.0.6 - undici: 5.29.0 + undici: 6.23.0 - '@actions/io@2.0.0': {} + '@actions/io@3.0.2': {} - '@actions/tool-cache@3.0.0': + '@actions/tool-cache@4.0.0': dependencies: - '@actions/core': 2.0.2 - '@actions/exec': 2.0.0 - '@actions/http-client': 3.0.1 - '@actions/io': 2.0.0 - semver: 6.3.1 + '@actions/core': 3.0.0 + '@actions/exec': 3.0.0 + '@actions/http-client': 4.0.0 + '@actions/io': 3.0.2 + semver: 7.7.4 - '@biomejs/biome@2.3.11': + '@biomejs/biome@2.3.14': optionalDependencies: - '@biomejs/cli-darwin-arm64': 2.3.11 - '@biomejs/cli-darwin-x64': 2.3.11 - '@biomejs/cli-linux-arm64': 2.3.11 - '@biomejs/cli-linux-arm64-musl': 2.3.11 - '@biomejs/cli-linux-x64': 2.3.11 - '@biomejs/cli-linux-x64-musl': 2.3.11 - '@biomejs/cli-win32-arm64': 2.3.11 - '@biomejs/cli-win32-x64': 2.3.11 - - '@biomejs/cli-darwin-arm64@2.3.11': + '@biomejs/cli-darwin-arm64': 2.3.14 + '@biomejs/cli-darwin-x64': 2.3.14 + '@biomejs/cli-linux-arm64': 2.3.14 + '@biomejs/cli-linux-arm64-musl': 2.3.14 + '@biomejs/cli-linux-x64': 2.3.14 + '@biomejs/cli-linux-x64-musl': 2.3.14 + '@biomejs/cli-win32-arm64': 2.3.14 + '@biomejs/cli-win32-x64': 2.3.14 + + '@biomejs/cli-darwin-arm64@2.3.14': optional: true - '@biomejs/cli-darwin-x64@2.3.11': + '@biomejs/cli-darwin-x64@2.3.14': optional: true - '@biomejs/cli-linux-arm64-musl@2.3.11': + '@biomejs/cli-linux-arm64-musl@2.3.14': optional: true - '@biomejs/cli-linux-arm64@2.3.11': + '@biomejs/cli-linux-arm64@2.3.14': optional: true - '@biomejs/cli-linux-x64-musl@2.3.11': + '@biomejs/cli-linux-x64-musl@2.3.14': optional: true - '@biomejs/cli-linux-x64@2.3.11': + '@biomejs/cli-linux-x64@2.3.14': optional: true - '@biomejs/cli-win32-arm64@2.3.11': + '@biomejs/cli-win32-arm64@2.3.14': optional: true - '@biomejs/cli-win32-x64@2.3.11': + '@biomejs/cli-win32-x64@2.3.14': optional: true - '@cspell/cspell-bundled-dicts@9.6.0': + '@cspell/cspell-bundled-dicts@9.6.4': dependencies: '@cspell/dict-ada': 4.1.1 '@cspell/dict-al': 1.1.1 @@ -913,16 +925,16 @@ snapshots: '@cspell/dict-docker': 1.1.17 '@cspell/dict-dotnet': 5.0.11 '@cspell/dict-elixir': 4.0.8 - '@cspell/dict-en-common-misspellings': 2.1.11 - '@cspell/dict-en-gb-mit': 3.1.16 - '@cspell/dict-en_us': 4.4.27 + '@cspell/dict-en-common-misspellings': 2.1.12 + '@cspell/dict-en-gb-mit': 3.1.17 + '@cspell/dict-en_us': 4.4.28 '@cspell/dict-filetypes': 3.0.15 '@cspell/dict-flutter': 1.1.1 '@cspell/dict-fonts': 4.0.5 '@cspell/dict-fsharp': 1.1.1 - '@cspell/dict-fullstack': 3.2.7 + '@cspell/dict-fullstack': 3.2.8 '@cspell/dict-gaming-terms': 1.1.2 - '@cspell/dict-git': 3.0.7 + '@cspell/dict-git': 3.1.0 '@cspell/dict-golang': 6.0.26 '@cspell/dict-google': 1.0.9 '@cspell/dict-haskell': 4.0.6 @@ -932,21 +944,21 @@ snapshots: '@cspell/dict-julia': 1.1.1 '@cspell/dict-k8s': 1.0.12 '@cspell/dict-kotlin': 1.1.1 - '@cspell/dict-latex': 4.0.4 + '@cspell/dict-latex': 5.0.0 '@cspell/dict-lorem-ipsum': 4.0.5 '@cspell/dict-lua': 4.0.8 '@cspell/dict-makefile': 1.0.5 '@cspell/dict-markdown': 2.0.14(@cspell/dict-css@4.0.19)(@cspell/dict-html-symbol-entities@4.0.5)(@cspell/dict-html@4.0.14)(@cspell/dict-typescript@3.2.3) '@cspell/dict-monkeyc': 1.0.12 - '@cspell/dict-node': 5.0.8 - '@cspell/dict-npm': 5.2.29 + '@cspell/dict-node': 5.0.9 + '@cspell/dict-npm': 5.2.32 '@cspell/dict-php': 4.1.1 '@cspell/dict-powershell': 5.0.15 '@cspell/dict-public-licenses': 2.0.15 '@cspell/dict-python': 4.2.25 '@cspell/dict-r': 2.1.1 '@cspell/dict-ruby': 5.1.0 - '@cspell/dict-rust': 4.1.1 + '@cspell/dict-rust': 4.1.2 '@cspell/dict-scala': 5.0.9 '@cspell/dict-shell': 1.1.2 '@cspell/dict-software-terms': 5.1.20 @@ -958,19 +970,25 @@ snapshots: '@cspell/dict-vue': 3.0.5 '@cspell/dict-zig': 1.0.0 - '@cspell/cspell-json-reporter@9.6.0': + '@cspell/cspell-json-reporter@9.6.4': dependencies: - '@cspell/cspell-types': 9.6.0 + '@cspell/cspell-types': 9.6.4 + + '@cspell/cspell-performance-monitor@9.6.4': {} - '@cspell/cspell-pipe@9.6.0': {} + '@cspell/cspell-pipe@9.6.4': {} - '@cspell/cspell-resolver@9.6.0': + '@cspell/cspell-resolver@9.6.4': dependencies: global-directory: 4.0.1 - '@cspell/cspell-service-bus@9.6.0': {} + '@cspell/cspell-service-bus@9.6.4': {} - '@cspell/cspell-types@9.6.0': {} + '@cspell/cspell-types@9.6.4': {} + + '@cspell/cspell-worker@9.6.4': + dependencies: + cspell-lib: 9.6.4 '@cspell/dict-ada@4.1.1': {} @@ -1004,11 +1022,11 @@ snapshots: '@cspell/dict-elixir@4.0.8': {} - '@cspell/dict-en-common-misspellings@2.1.11': {} + '@cspell/dict-en-common-misspellings@2.1.12': {} - '@cspell/dict-en-gb-mit@3.1.16': {} + '@cspell/dict-en-gb-mit@3.1.17': {} - '@cspell/dict-en_us@4.4.27': {} + '@cspell/dict-en_us@4.4.28': {} '@cspell/dict-filetypes@3.0.15': {} @@ -1018,11 +1036,11 @@ snapshots: '@cspell/dict-fsharp@1.1.1': {} - '@cspell/dict-fullstack@3.2.7': {} + '@cspell/dict-fullstack@3.2.8': {} '@cspell/dict-gaming-terms@1.1.2': {} - '@cspell/dict-git@3.0.7': {} + '@cspell/dict-git@3.1.0': {} '@cspell/dict-golang@6.0.26': {} @@ -1042,7 +1060,7 @@ snapshots: '@cspell/dict-kotlin@1.1.1': {} - '@cspell/dict-latex@4.0.4': {} + '@cspell/dict-latex@5.0.0': {} '@cspell/dict-lorem-ipsum@4.0.5': {} @@ -1059,9 +1077,9 @@ snapshots: '@cspell/dict-monkeyc@1.0.12': {} - '@cspell/dict-node@5.0.8': {} + '@cspell/dict-node@5.0.9': {} - '@cspell/dict-npm@5.2.29': {} + '@cspell/dict-npm@5.2.32': {} '@cspell/dict-php@4.1.1': {} @@ -1077,7 +1095,7 @@ snapshots: '@cspell/dict-ruby@5.1.0': {} - '@cspell/dict-rust@4.1.1': {} + '@cspell/dict-rust@4.1.2': {} '@cspell/dict-scala@5.0.9': {} @@ -1099,18 +1117,18 @@ snapshots: '@cspell/dict-zig@1.0.0': {} - '@cspell/dynamic-import@9.6.0': + '@cspell/dynamic-import@9.6.4': dependencies: - '@cspell/url': 9.6.0 + '@cspell/url': 9.6.4 import-meta-resolve: 4.2.0 - '@cspell/filetypes@9.6.0': {} + '@cspell/filetypes@9.6.4': {} - '@cspell/strong-weak-map@9.6.0': {} + '@cspell/rpc@9.6.4': {} - '@cspell/url@9.6.0': {} + '@cspell/strong-weak-map@9.6.4': {} - '@fastify/busboy@2.1.1': {} + '@cspell/url@9.6.4': {} '@nodelib/fs.scandir@2.1.5': dependencies: @@ -1188,7 +1206,7 @@ snapshots: '@sindresorhus/merge-streams@4.0.0': {} - '@types/node@25.0.10': + '@types/node@25.2.1': dependencies: undici-types: 7.16.0 @@ -1196,7 +1214,7 @@ snapshots: '@types/shelljs@0.10.0': dependencies: - '@types/node': 25.0.10 + '@types/node': 25.2.1 fast-glob: 3.3.3 '@vercel/ncc@0.38.4': {} @@ -1224,7 +1242,7 @@ snapshots: parent-module: 2.0.0 resolve-from: 5.0.0 - commander@14.0.2: {} + commander@14.0.3: {} comment-json@4.5.1: dependencies: @@ -1240,59 +1258,62 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 - cspell-config-lib@9.6.0: + cspell-config-lib@9.6.4: dependencies: - '@cspell/cspell-types': 9.6.0 + '@cspell/cspell-types': 9.6.4 comment-json: 4.5.1 smol-toml: 1.6.0 yaml: 2.8.2 - cspell-dictionary@9.6.0: + cspell-dictionary@9.6.4: dependencies: - '@cspell/cspell-pipe': 9.6.0 - '@cspell/cspell-types': 9.6.0 - cspell-trie-lib: 9.6.0(@cspell/cspell-types@9.6.0) + '@cspell/cspell-performance-monitor': 9.6.4 + '@cspell/cspell-pipe': 9.6.4 + '@cspell/cspell-types': 9.6.4 + cspell-trie-lib: 9.6.4(@cspell/cspell-types@9.6.4) fast-equals: 6.0.0 - cspell-gitignore@9.6.0: + cspell-gitignore@9.6.4: dependencies: - '@cspell/url': 9.6.0 - cspell-glob: 9.6.0 - cspell-io: 9.6.0 + '@cspell/url': 9.6.4 + cspell-glob: 9.6.4 + cspell-io: 9.6.4 - cspell-glob@9.6.0: + cspell-glob@9.6.4: dependencies: - '@cspell/url': 9.6.0 + '@cspell/url': 9.6.4 picomatch: 4.0.3 - cspell-grammar@9.6.0: + cspell-grammar@9.6.4: dependencies: - '@cspell/cspell-pipe': 9.6.0 - '@cspell/cspell-types': 9.6.0 + '@cspell/cspell-pipe': 9.6.4 + '@cspell/cspell-types': 9.6.4 - cspell-io@9.6.0: + cspell-io@9.6.4: dependencies: - '@cspell/cspell-service-bus': 9.6.0 - '@cspell/url': 9.6.0 + '@cspell/cspell-service-bus': 9.6.4 + '@cspell/url': 9.6.4 - cspell-lib@9.6.0: + cspell-lib@9.6.4: dependencies: - '@cspell/cspell-bundled-dicts': 9.6.0 - '@cspell/cspell-pipe': 9.6.0 - '@cspell/cspell-resolver': 9.6.0 - '@cspell/cspell-types': 9.6.0 - '@cspell/dynamic-import': 9.6.0 - '@cspell/filetypes': 9.6.0 - '@cspell/strong-weak-map': 9.6.0 - '@cspell/url': 9.6.0 + '@cspell/cspell-bundled-dicts': 9.6.4 + '@cspell/cspell-performance-monitor': 9.6.4 + '@cspell/cspell-pipe': 9.6.4 + '@cspell/cspell-resolver': 9.6.4 + '@cspell/cspell-types': 9.6.4 + '@cspell/dynamic-import': 9.6.4 + '@cspell/filetypes': 9.6.4 + '@cspell/rpc': 9.6.4 + '@cspell/strong-weak-map': 9.6.4 + '@cspell/url': 9.6.4 clear-module: 4.1.2 - cspell-config-lib: 9.6.0 - cspell-dictionary: 9.6.0 - cspell-glob: 9.6.0 - cspell-grammar: 9.6.0 - cspell-io: 9.6.0 - cspell-trie-lib: 9.6.0(@cspell/cspell-types@9.6.0) - env-paths: 3.0.0 + cspell-config-lib: 9.6.4 + cspell-dictionary: 9.6.4 + cspell-glob: 9.6.4 + cspell-grammar: 9.6.4 + cspell-io: 9.6.4 + cspell-trie-lib: 9.6.4(@cspell/cspell-types@9.6.4) + env-paths: 4.0.0 gensequence: 8.0.8 import-fresh: 3.3.1 resolve-from: 5.0.0 @@ -1300,33 +1321,37 @@ snapshots: vscode-uri: 3.1.0 xdg-basedir: 5.1.0 - cspell-trie-lib@9.6.0(@cspell/cspell-types@9.6.0): + cspell-trie-lib@9.6.4(@cspell/cspell-types@9.6.4): dependencies: - '@cspell/cspell-types': 9.6.0 + '@cspell/cspell-types': 9.6.4 - cspell@9.6.0: + cspell@9.6.4: dependencies: - '@cspell/cspell-json-reporter': 9.6.0 - '@cspell/cspell-pipe': 9.6.0 - '@cspell/cspell-types': 9.6.0 - '@cspell/dynamic-import': 9.6.0 - '@cspell/url': 9.6.0 + '@cspell/cspell-json-reporter': 9.6.4 + '@cspell/cspell-performance-monitor': 9.6.4 + '@cspell/cspell-pipe': 9.6.4 + '@cspell/cspell-types': 9.6.4 + '@cspell/cspell-worker': 9.6.4 + '@cspell/dynamic-import': 9.6.4 + '@cspell/url': 9.6.4 ansi-regex: 6.2.2 chalk: 5.6.2 chalk-template: 1.1.2 - commander: 14.0.2 - cspell-config-lib: 9.6.0 - cspell-dictionary: 9.6.0 - cspell-gitignore: 9.6.0 - cspell-glob: 9.6.0 - cspell-io: 9.6.0 - cspell-lib: 9.6.0 + commander: 14.0.3 + cspell-config-lib: 9.6.4 + cspell-dictionary: 9.6.4 + cspell-gitignore: 9.6.4 + cspell-glob: 9.6.4 + cspell-io: 9.6.4 + cspell-lib: 9.6.4 fast-json-stable-stringify: 2.1.0 flatted: 3.3.3 - semver: 7.7.3 + semver: 7.7.4 tinyglobby: 0.2.15 - env-paths@3.0.0: {} + env-paths@4.0.0: + dependencies: + is-safe-filename: 0.1.1 esprima@4.0.1: {} @@ -1414,52 +1439,54 @@ snapshots: is-path-inside@4.0.0: {} + is-safe-filename@0.1.1: {} + is-stream@2.0.1: {} isexe@2.0.0: {} - lefthook-darwin-arm64@2.0.15: + lefthook-darwin-arm64@2.1.0: optional: true - lefthook-darwin-x64@2.0.15: + lefthook-darwin-x64@2.1.0: optional: true - lefthook-freebsd-arm64@2.0.15: + lefthook-freebsd-arm64@2.1.0: optional: true - lefthook-freebsd-x64@2.0.15: + lefthook-freebsd-x64@2.1.0: optional: true - lefthook-linux-arm64@2.0.15: + lefthook-linux-arm64@2.1.0: optional: true - lefthook-linux-x64@2.0.15: + lefthook-linux-x64@2.1.0: optional: true - lefthook-openbsd-arm64@2.0.15: + lefthook-openbsd-arm64@2.1.0: optional: true - lefthook-openbsd-x64@2.0.15: + lefthook-openbsd-x64@2.1.0: optional: true - lefthook-windows-arm64@2.0.15: + lefthook-windows-arm64@2.1.0: optional: true - lefthook-windows-x64@2.0.15: + lefthook-windows-x64@2.1.0: optional: true - lefthook@2.0.15: + lefthook@2.1.0: optionalDependencies: - lefthook-darwin-arm64: 2.0.15 - lefthook-darwin-x64: 2.0.15 - lefthook-freebsd-arm64: 2.0.15 - lefthook-freebsd-x64: 2.0.15 - lefthook-linux-arm64: 2.0.15 - lefthook-linux-x64: 2.0.15 - lefthook-openbsd-arm64: 2.0.15 - lefthook-openbsd-x64: 2.0.15 - lefthook-windows-arm64: 2.0.15 - lefthook-windows-x64: 2.0.15 + lefthook-darwin-arm64: 2.1.0 + lefthook-darwin-x64: 2.1.0 + lefthook-freebsd-arm64: 2.1.0 + lefthook-freebsd-x64: 2.1.0 + lefthook-linux-arm64: 2.1.0 + lefthook-linux-x64: 2.1.0 + lefthook-openbsd-arm64: 2.1.0 + lefthook-openbsd-x64: 2.1.0 + lefthook-windows-arm64: 2.1.0 + lefthook-windows-x64: 2.1.0 merge-stream@2.0.0: {} @@ -1506,9 +1533,7 @@ snapshots: dependencies: queue-microtask: 1.2.3 - semver@6.3.1: {} - - semver@7.7.3: {} + semver@7.7.4: {} shebang-command@2.0.0: dependencies: @@ -1544,11 +1569,9 @@ snapshots: undici-types@7.16.0: {} - undici@5.29.0: - dependencies: - '@fastify/busboy': 2.1.1 + undici@6.23.0: {} - undici@7.19.0: {} + undici@7.20.0: {} unicorn-magic@0.4.0: {} From 8328f01c4a981f8785344d980e51fecf1cc54224 Mon Sep 17 00:00:00 2001 From: hustcer Date: Fri, 6 Feb 2026 19:32:58 +0800 Subject: [PATCH 2/6] deps: Upgrade @actions/core,@actions/tool-cache,undici,lefthook & semver --- dist/index.js | 147175 ++++++++++++++++++++++--------------------- dist/package.json | 3 + package.json | 1 + src/index.ts | 4 +- src/setup.ts | 4 +- tsconfig.json | 6 +- 6 files changed, 73981 insertions(+), 73212 deletions(-) create mode 100644 dist/package.json diff --git a/dist/index.js b/dist/index.js index fc36f17..145b071 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1,14268 +1,10701 @@ -/******/ (() => { // webpackBootstrap -/******/ var __webpack_modules__ = ({ +import { createRequire as __WEBPACK_EXTERNAL_createRequire } from "module"; +/******/ var __webpack_modules__ = ({ -/***/ 8943: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { +/***/ 6420: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; - }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; - }; -})(); -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.issueCommand = issueCommand; -exports.issue = issue; -const os = __importStar(__nccwpck_require__(857)); -const utils_1 = __nccwpck_require__(5219); + +const stringify = __nccwpck_require__(5373); +const compile = __nccwpck_require__(7521); +const expand = __nccwpck_require__(1826); +const parse = __nccwpck_require__(2259); + /** - * Issues a command to the GitHub Actions runner - * - * @param command - The command name to issue - * @param properties - Additional properties for the command (key-value pairs) - * @param message - The message to include with the command - * @remarks - * This function outputs a specially formatted string to stdout that the Actions - * runner interprets as a command. These commands can control workflow behavior, - * set outputs, create annotations, mask values, and more. - * - * Command Format: - * ::name key=value,key=value::message - * - * @example - * ```typescript - * // Issue a warning annotation - * issueCommand('warning', {}, 'This is a warning message'); - * // Output: ::warning::This is a warning message - * - * // Set an environment variable - * issueCommand('set-env', { name: 'MY_VAR' }, 'some value'); - * // Output: ::set-env name=MY_VAR::some value + * Expand the given pattern or create a regex-compatible string. * - * // Add a secret mask - * issueCommand('add-mask', {}, 'secretValue123'); - * // Output: ::add-mask::secretValue123 + * ```js + * const braces = require('braces'); + * console.log(braces('{a,b,c}', { compile: true })); //=> ['(a|b|c)'] + * console.log(braces('{a,b,c}')); //=> ['a', 'b', 'c'] * ``` - * - * @internal - * This is an internal utility function that powers the public API functions - * such as setSecret, warning, error, and exportVariable. + * @param {String} `str` + * @param {Object} `options` + * @return {String} + * @api public */ -function issueCommand(command, properties, message) { - const cmd = new Command(command, properties, message); - process.stdout.write(cmd.toString() + os.EOL); -} -function issue(name, message = '') { - issueCommand(name, {}, message); -} -const CMD_STRING = '::'; -class Command { - constructor(command, properties, message) { - if (!command) { - command = 'missing.command'; - } - this.command = command; - this.properties = properties; - this.message = message; - } - toString() { - let cmdStr = CMD_STRING + this.command; - if (this.properties && Object.keys(this.properties).length > 0) { - cmdStr += ' '; - let first = true; - for (const key in this.properties) { - if (this.properties.hasOwnProperty(key)) { - const val = this.properties[key]; - if (val) { - if (first) { - first = false; - } - else { - cmdStr += ','; - } - cmdStr += `${key}=${escapeProperty(val)}`; - } - } - } - } - cmdStr += `${CMD_STRING}${escapeData(this.message)}`; - return cmdStr; - } -} -function escapeData(s) { - return (0, utils_1.toCommandValue)(s) - .replace(/%/g, '%25') - .replace(/\r/g, '%0D') - .replace(/\n/g, '%0A'); -} -function escapeProperty(s) { - return (0, utils_1.toCommandValue)(s) - .replace(/%/g, '%25') - .replace(/\r/g, '%0D') - .replace(/\n/g, '%0A') - .replace(/:/g, '%3A') - .replace(/,/g, '%2C'); -} -//# sourceMappingURL=command.js.map - -/***/ }), - -/***/ 9239: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { -"use strict"; +const braces = (input, options = {}) => { + let output = []; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; + if (Array.isArray(input)) { + for (const pattern of input) { + const result = braces.create(pattern, options); + if (Array.isArray(result)) { + output.push(...result); + } else { + output.push(result); + } } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; - }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; - }; -})(); -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); + } else { + output = [].concat(braces.create(input, options)); + } + + if (options && options.expand === true && options.nodupes === true) { + output = [...new Set(output)]; + } + return output; }; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.platform = exports.toPlatformPath = exports.toWin32Path = exports.toPosixPath = exports.markdownSummary = exports.summary = exports.ExitCode = void 0; -exports.exportVariable = exportVariable; -exports.setSecret = setSecret; -exports.addPath = addPath; -exports.getInput = getInput; -exports.getMultilineInput = getMultilineInput; -exports.getBooleanInput = getBooleanInput; -exports.setOutput = setOutput; -exports.setCommandEcho = setCommandEcho; -exports.setFailed = setFailed; -exports.isDebug = isDebug; -exports.debug = debug; -exports.error = error; -exports.warning = warning; -exports.notice = notice; -exports.info = info; -exports.startGroup = startGroup; -exports.endGroup = endGroup; -exports.group = group; -exports.saveState = saveState; -exports.getState = getState; -exports.getIDToken = getIDToken; -const command_1 = __nccwpck_require__(8943); -const file_command_1 = __nccwpck_require__(2666); -const utils_1 = __nccwpck_require__(5219); -const os = __importStar(__nccwpck_require__(857)); -const path = __importStar(__nccwpck_require__(6928)); -const oidc_utils_1 = __nccwpck_require__(6437); -/** - * The code to exit an action - */ -var ExitCode; -(function (ExitCode) { - /** - * A code indicating that the action was successful - */ - ExitCode[ExitCode["Success"] = 0] = "Success"; - /** - * A code indicating that the action was a failure - */ - ExitCode[ExitCode["Failure"] = 1] = "Failure"; -})(ExitCode || (exports.ExitCode = ExitCode = {})); -//----------------------------------------------------------------------- -// Variables -//----------------------------------------------------------------------- -/** - * Sets env variable for this action and future actions in the job - * @param name the name of the variable to set - * @param val the value of the variable. Non-string values will be converted to a string via JSON.stringify - */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -function exportVariable(name, val) { - const convertedVal = (0, utils_1.toCommandValue)(val); - process.env[name] = convertedVal; - const filePath = process.env['GITHUB_ENV'] || ''; - if (filePath) { - return (0, file_command_1.issueFileCommand)('ENV', (0, file_command_1.prepareKeyValueMessage)(name, val)); - } - (0, command_1.issueCommand)('set-env', { name }, convertedVal); -} + /** - * Registers a secret which will get masked from logs - * - * @param secret - Value of the secret to be masked - * @remarks - * This function instructs the Actions runner to mask the specified value in any - * logs produced during the workflow run. Once registered, the secret value will - * be replaced with asterisks (***) whenever it appears in console output, logs, - * or error messages. - * - * This is useful for protecting sensitive information such as: - * - API keys - * - Access tokens - * - Authentication credentials - * - URL parameters containing signatures (SAS tokens) - * - * Note that masking only affects future logs; any previous appearances of the - * secret in logs before calling this function will remain unmasked. - * - * @example - * ```typescript - * // Register an API token as a secret - * const apiToken = "abc123xyz456"; - * setSecret(apiToken); + * Parse the given `str` with the given `options`. * - * // Now any logs containing this value will show *** instead - * console.log(`Using token: ${apiToken}`); // Outputs: "Using token: ***" + * ```js + * // braces.parse(pattern, [, options]); + * const ast = braces.parse('a/{b,c}/d'); + * console.log(ast); * ``` + * @param {String} pattern Brace pattern to parse + * @param {Object} options + * @return {Object} Returns an AST + * @api public */ -function setSecret(secret) { - (0, command_1.issueCommand)('add-mask', {}, secret); -} -/** - * Prepends inputPath to the PATH (for this action and future actions) - * @param inputPath - */ -function addPath(inputPath) { - const filePath = process.env['GITHUB_PATH'] || ''; - if (filePath) { - (0, file_command_1.issueFileCommand)('PATH', inputPath); - } - else { - (0, command_1.issueCommand)('add-path', {}, inputPath); - } - process.env['PATH'] = `${inputPath}${path.delimiter}${process.env['PATH']}`; -} -/** - * Gets the value of an input. - * Unless trimWhitespace is set to false in InputOptions, the value is also trimmed. - * Returns an empty string if the value is not defined. - * - * @param name name of the input to get - * @param options optional. See InputOptions. - * @returns string - */ -function getInput(name, options) { - const val = process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] || ''; - if (options && options.required && !val) { - throw new Error(`Input required and not supplied: ${name}`); - } - if (options && options.trimWhitespace === false) { - return val; - } - return val.trim(); -} -/** - * Gets the values of an multiline input. Each value is also trimmed. - * - * @param name name of the input to get - * @param options optional. See InputOptions. - * @returns string[] - * - */ -function getMultilineInput(name, options) { - const inputs = getInput(name, options) - .split('\n') - .filter(x => x !== ''); - if (options && options.trimWhitespace === false) { - return inputs; - } - return inputs.map(input => input.trim()); -} -/** - * Gets the input value of the boolean type in the YAML 1.2 "core schema" specification. - * Support boolean input list: `true | True | TRUE | false | False | FALSE` . - * The return value is also in boolean type. - * ref: https://yaml.org/spec/1.2/spec.html#id2804923 - * - * @param name name of the input to get - * @param options optional. See InputOptions. - * @returns boolean - */ -function getBooleanInput(name, options) { - const trueValue = ['true', 'True', 'TRUE']; - const falseValue = ['false', 'False', 'FALSE']; - const val = getInput(name, options); - if (trueValue.includes(val)) - return true; - if (falseValue.includes(val)) - return false; - throw new TypeError(`Input does not meet YAML 1.2 "Core Schema" specification: ${name}\n` + - `Support boolean input list: \`true | True | TRUE | false | False | FALSE\``); -} -/** - * Sets the value of an output. - * - * @param name name of the output to set - * @param value value to store. Non-string values will be converted to a string via JSON.stringify - */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -function setOutput(name, value) { - const filePath = process.env['GITHUB_OUTPUT'] || ''; - if (filePath) { - return (0, file_command_1.issueFileCommand)('OUTPUT', (0, file_command_1.prepareKeyValueMessage)(name, value)); - } - process.stdout.write(os.EOL); - (0, command_1.issueCommand)('set-output', { name }, (0, utils_1.toCommandValue)(value)); -} -/** - * Enables or disables the echoing of commands into stdout for the rest of the step. - * Echoing is disabled by default if ACTIONS_STEP_DEBUG is not set. - * - */ -function setCommandEcho(enabled) { - (0, command_1.issue)('echo', enabled ? 'on' : 'off'); -} -//----------------------------------------------------------------------- -// Results -//----------------------------------------------------------------------- -/** - * Sets the action status to failed. - * When the action exits it will be with an exit code of 1 - * @param message add error issue message - */ -function setFailed(message) { - process.exitCode = ExitCode.Failure; - error(message); -} -//----------------------------------------------------------------------- -// Logging Commands -//----------------------------------------------------------------------- -/** - * Gets whether Actions Step Debug is on or not - */ -function isDebug() { - return process.env['RUNNER_DEBUG'] === '1'; -} -/** - * Writes debug message to user log - * @param message debug message - */ -function debug(message) { - (0, command_1.issueCommand)('debug', {}, message); -} -/** - * Adds an error issue - * @param message error issue message. Errors will be converted to string via toString() - * @param properties optional properties to add to the annotation. - */ -function error(message, properties = {}) { - (0, command_1.issueCommand)('error', (0, utils_1.toCommandProperties)(properties), message instanceof Error ? message.toString() : message); -} -/** - * Adds a warning issue - * @param message warning issue message. Errors will be converted to string via toString() - * @param properties optional properties to add to the annotation. - */ -function warning(message, properties = {}) { - (0, command_1.issueCommand)('warning', (0, utils_1.toCommandProperties)(properties), message instanceof Error ? message.toString() : message); -} -/** - * Adds a notice issue - * @param message notice issue message. Errors will be converted to string via toString() - * @param properties optional properties to add to the annotation. - */ -function notice(message, properties = {}) { - (0, command_1.issueCommand)('notice', (0, utils_1.toCommandProperties)(properties), message instanceof Error ? message.toString() : message); -} -/** - * Writes info to log with console.log. - * @param message info message - */ -function info(message) { - process.stdout.write(message + os.EOL); -} + +braces.parse = (input, options = {}) => parse(input, options); + /** - * Begin an output group. - * - * Output until the next `groupEnd` will be foldable in this group + * Creates a braces string from an AST, or an AST node. * - * @param name The name of the output group - */ -function startGroup(name) { - (0, command_1.issue)('group', name); -} -/** - * End an output group. + * ```js + * const braces = require('braces'); + * let ast = braces.parse('foo/{a,b}/bar'); + * console.log(stringify(ast.nodes[2])); //=> '{a,b}' + * ``` + * @param {String} `input` Brace pattern or AST. + * @param {Object} `options` + * @return {Array} Returns an array of expanded values. + * @api public */ -function endGroup() { - (0, command_1.issue)('endgroup'); -} + +braces.stringify = (input, options = {}) => { + if (typeof input === 'string') { + return stringify(braces.parse(input, options), options); + } + return stringify(input, options); +}; + /** - * Wrap an asynchronous function call in a group. - * - * Returns the same type as the function itself. + * Compiles a brace pattern into a regex-compatible, optimized string. + * This method is called by the main [braces](#braces) function by default. * - * @param name The name of the group - * @param fn The function to wrap in the group + * ```js + * const braces = require('braces'); + * console.log(braces.compile('a/{b,c}/d')); + * //=> ['a/(b|c)/d'] + * ``` + * @param {String} `input` Brace pattern or AST. + * @param {Object} `options` + * @return {Array} Returns an array of expanded values. + * @api public */ -function group(name, fn) { - return __awaiter(this, void 0, void 0, function* () { - startGroup(name); - let result; - try { - result = yield fn(); - } - finally { - endGroup(); - } - return result; - }); -} -//----------------------------------------------------------------------- -// Wrapper action state -//----------------------------------------------------------------------- + +braces.compile = (input, options = {}) => { + if (typeof input === 'string') { + input = braces.parse(input, options); + } + return compile(input, options); +}; + /** - * Saves state for current action, the state can only be retrieved by this action's post job execution. + * Expands a brace pattern into an array. This method is called by the + * main [braces](#braces) function when `options.expand` is true. Before + * using this method it's recommended that you read the [performance notes](#performance)) + * and advantages of using [.compile](#compile) instead. * - * @param name name of the state to store - * @param value value to store. Non-string values will be converted to a string via JSON.stringify + * ```js + * const braces = require('braces'); + * console.log(braces.expand('a/{b,c}/d')); + * //=> ['a/b/d', 'a/c/d']; + * ``` + * @param {String} `pattern` Brace pattern + * @param {Object} `options` + * @return {Array} Returns an array of expanded values. + * @api public */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -function saveState(name, value) { - const filePath = process.env['GITHUB_STATE'] || ''; - if (filePath) { - return (0, file_command_1.issueFileCommand)('STATE', (0, file_command_1.prepareKeyValueMessage)(name, value)); - } - (0, command_1.issueCommand)('save-state', { name }, (0, utils_1.toCommandValue)(value)); -} + +braces.expand = (input, options = {}) => { + if (typeof input === 'string') { + input = braces.parse(input, options); + } + + let result = expand(input, options); + + // filter out empty strings if specified + if (options.noempty === true) { + result = result.filter(Boolean); + } + + // filter out duplicates if specified + if (options.nodupes === true) { + result = [...new Set(result)]; + } + + return result; +}; + /** - * Gets the value of an state set by this action's main execution. + * Processes a brace pattern and returns either an expanded array + * (if `options.expand` is true), a highly optimized regex-compatible string. + * This method is called by the main [braces](#braces) function. * - * @param name name of the state to get - * @returns string - */ -function getState(name) { - return process.env[`STATE_${name}`] || ''; -} -function getIDToken(aud) { - return __awaiter(this, void 0, void 0, function* () { - return yield oidc_utils_1.OidcClient.getIDToken(aud); - }); -} -/** - * Summary exports - */ -var summary_1 = __nccwpck_require__(606); -Object.defineProperty(exports, "summary", ({ enumerable: true, get: function () { return summary_1.summary; } })); -/** - * @deprecated use core.summary - */ -var summary_2 = __nccwpck_require__(606); -Object.defineProperty(exports, "markdownSummary", ({ enumerable: true, get: function () { return summary_2.markdownSummary; } })); -/** - * Path exports + * ```js + * const braces = require('braces'); + * console.log(braces.create('user-{200..300}/project-{a,b,c}-{1..10}')) + * //=> 'user-(20[0-9]|2[1-9][0-9]|300)/project-(a|b|c)-([1-9]|10)' + * ``` + * @param {String} `pattern` Brace pattern + * @param {Object} `options` + * @return {Array} Returns an array of expanded values. + * @api public */ -var path_utils_1 = __nccwpck_require__(2403); -Object.defineProperty(exports, "toPosixPath", ({ enumerable: true, get: function () { return path_utils_1.toPosixPath; } })); -Object.defineProperty(exports, "toWin32Path", ({ enumerable: true, get: function () { return path_utils_1.toWin32Path; } })); -Object.defineProperty(exports, "toPlatformPath", ({ enumerable: true, get: function () { return path_utils_1.toPlatformPath; } })); + +braces.create = (input, options = {}) => { + if (input === '' || input.length < 3) { + return [input]; + } + + return options.expand !== true + ? braces.compile(input, options) + : braces.expand(input, options); +}; + /** - * Platform utilities exports + * Expose "braces" */ -exports.platform = __importStar(__nccwpck_require__(5739)); -//# sourceMappingURL=core.js.map + +module.exports = braces; + /***/ }), -/***/ 2666: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { +/***/ 7521: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -// For internal use, subject to change. -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; - }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; - }; -})(); -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.issueFileCommand = issueFileCommand; -exports.prepareKeyValueMessage = prepareKeyValueMessage; -// We use any as a valid input type -/* eslint-disable @typescript-eslint/no-explicit-any */ -const crypto = __importStar(__nccwpck_require__(6982)); -const fs = __importStar(__nccwpck_require__(9896)); -const os = __importStar(__nccwpck_require__(857)); -const utils_1 = __nccwpck_require__(5219); -function issueFileCommand(command, message) { - const filePath = process.env[`GITHUB_${command}`]; - if (!filePath) { - throw new Error(`Unable to find environment variable for file command ${command}`); + +const fill = __nccwpck_require__(5514); +const utils = __nccwpck_require__(6825); + +const compile = (ast, options = {}) => { + const walk = (node, parent = {}) => { + const invalidBlock = utils.isInvalidBrace(parent); + const invalidNode = node.invalid === true && options.escapeInvalid === true; + const invalid = invalidBlock === true || invalidNode === true; + const prefix = options.escapeInvalid === true ? '\\' : ''; + let output = ''; + + if (node.isOpen === true) { + return prefix + node.value; } - if (!fs.existsSync(filePath)) { - throw new Error(`Missing file at path: ${filePath}`); + + if (node.isClose === true) { + console.log('node.isClose', prefix, node.value); + return prefix + node.value; } - fs.appendFileSync(filePath, `${(0, utils_1.toCommandValue)(message)}${os.EOL}`, { - encoding: 'utf8' - }); -} -function prepareKeyValueMessage(key, value) { - const delimiter = `ghadelimiter_${crypto.randomUUID()}`; - const convertedValue = (0, utils_1.toCommandValue)(value); - // These should realistically never happen, but just in case someone finds a - // way to exploit uuid generation let's not allow keys or values that contain - // the delimiter. - if (key.includes(delimiter)) { - throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`); + + if (node.type === 'open') { + return invalid ? prefix + node.value : '('; } - if (convertedValue.includes(delimiter)) { - throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`); + + if (node.type === 'close') { + return invalid ? prefix + node.value : ')'; } - return `${key}<<${delimiter}${os.EOL}${convertedValue}${os.EOL}${delimiter}`; -} -//# sourceMappingURL=file-command.js.map + + if (node.type === 'comma') { + return node.prev.type === 'comma' ? '' : invalid ? node.value : '|'; + } + + if (node.value) { + return node.value; + } + + if (node.nodes && node.ranges > 0) { + const args = utils.reduce(node.nodes); + const range = fill(...args, { ...options, wrap: false, toRegex: true, strictZeros: true }); + + if (range.length !== 0) { + return args.length > 1 && range.length > 1 ? `(${range})` : range; + } + } + + if (node.nodes) { + for (const child of node.nodes) { + output += walk(child, node); + } + } + + return output; + }; + + return walk(ast); +}; + +module.exports = compile; + /***/ }), -/***/ 6437: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { +/***/ 7205: +/***/ ((module) => { -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); + +module.exports = { + MAX_LENGTH: 10000, + + // Digits + CHAR_0: '0', /* 0 */ + CHAR_9: '9', /* 9 */ + + // Alphabet chars. + CHAR_UPPERCASE_A: 'A', /* A */ + CHAR_LOWERCASE_A: 'a', /* a */ + CHAR_UPPERCASE_Z: 'Z', /* Z */ + CHAR_LOWERCASE_Z: 'z', /* z */ + + CHAR_LEFT_PARENTHESES: '(', /* ( */ + CHAR_RIGHT_PARENTHESES: ')', /* ) */ + + CHAR_ASTERISK: '*', /* * */ + + // Non-alphabetic chars. + CHAR_AMPERSAND: '&', /* & */ + CHAR_AT: '@', /* @ */ + CHAR_BACKSLASH: '\\', /* \ */ + CHAR_BACKTICK: '`', /* ` */ + CHAR_CARRIAGE_RETURN: '\r', /* \r */ + CHAR_CIRCUMFLEX_ACCENT: '^', /* ^ */ + CHAR_COLON: ':', /* : */ + CHAR_COMMA: ',', /* , */ + CHAR_DOLLAR: '$', /* . */ + CHAR_DOT: '.', /* . */ + CHAR_DOUBLE_QUOTE: '"', /* " */ + CHAR_EQUAL: '=', /* = */ + CHAR_EXCLAMATION_MARK: '!', /* ! */ + CHAR_FORM_FEED: '\f', /* \f */ + CHAR_FORWARD_SLASH: '/', /* / */ + CHAR_HASH: '#', /* # */ + CHAR_HYPHEN_MINUS: '-', /* - */ + CHAR_LEFT_ANGLE_BRACKET: '<', /* < */ + CHAR_LEFT_CURLY_BRACE: '{', /* { */ + CHAR_LEFT_SQUARE_BRACKET: '[', /* [ */ + CHAR_LINE_FEED: '\n', /* \n */ + CHAR_NO_BREAK_SPACE: '\u00A0', /* \u00A0 */ + CHAR_PERCENT: '%', /* % */ + CHAR_PLUS: '+', /* + */ + CHAR_QUESTION_MARK: '?', /* ? */ + CHAR_RIGHT_ANGLE_BRACKET: '>', /* > */ + CHAR_RIGHT_CURLY_BRACE: '}', /* } */ + CHAR_RIGHT_SQUARE_BRACKET: ']', /* ] */ + CHAR_SEMICOLON: ';', /* ; */ + CHAR_SINGLE_QUOTE: '\'', /* ' */ + CHAR_SPACE: ' ', /* */ + CHAR_TAB: '\t', /* \t */ + CHAR_UNDERSCORE: '_', /* _ */ + CHAR_VERTICAL_LINE: '|', /* | */ + CHAR_ZERO_WIDTH_NOBREAK_SPACE: '\uFEFF' /* \uFEFF */ }; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.OidcClient = void 0; -const http_client_1 = __nccwpck_require__(7578); -const auth_1 = __nccwpck_require__(3446); -const core_1 = __nccwpck_require__(9239); -class OidcClient { - static createHttpClient(allowRetry = true, maxRetry = 10) { - const requestOptions = { - allowRetries: allowRetry, - maxRetries: maxRetry - }; - return new http_client_1.HttpClient('actions/oidc-client', [new auth_1.BearerCredentialHandler(OidcClient.getRequestToken())], requestOptions); + + +/***/ }), + +/***/ 1826: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + + + +const fill = __nccwpck_require__(5514); +const stringify = __nccwpck_require__(5373); +const utils = __nccwpck_require__(6825); + +const append = (queue = '', stash = '', enclose = false) => { + const result = []; + + queue = [].concat(queue); + stash = [].concat(stash); + + if (!stash.length) return queue; + if (!queue.length) { + return enclose ? utils.flatten(stash).map(ele => `{${ele}}`) : stash; + } + + for (const item of queue) { + if (Array.isArray(item)) { + for (const value of item) { + result.push(append(value, stash, enclose)); + } + } else { + for (let ele of stash) { + if (enclose === true && typeof ele === 'string') ele = `{${ele}}`; + result.push(Array.isArray(ele) ? append(item, ele, enclose) : item + ele); + } } - static getRequestToken() { - const token = process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN']; - if (!token) { - throw new Error('Unable to get ACTIONS_ID_TOKEN_REQUEST_TOKEN env variable'); - } - return token; + } + return utils.flatten(result); +}; + +const expand = (ast, options = {}) => { + const rangeLimit = options.rangeLimit === undefined ? 1000 : options.rangeLimit; + + const walk = (node, parent = {}) => { + node.queue = []; + + let p = parent; + let q = parent.queue; + + while (p.type !== 'brace' && p.type !== 'root' && p.parent) { + p = p.parent; + q = p.queue; } - static getIDTokenUrl() { - const runtimeUrl = process.env['ACTIONS_ID_TOKEN_REQUEST_URL']; - if (!runtimeUrl) { - throw new Error('Unable to get ACTIONS_ID_TOKEN_REQUEST_URL env variable'); - } - return runtimeUrl; + + if (node.invalid || node.dollar) { + q.push(append(q.pop(), stringify(node, options))); + return; } - static getCall(id_token_url) { - return __awaiter(this, void 0, void 0, function* () { - var _a; - const httpclient = OidcClient.createHttpClient(); - const res = yield httpclient - .getJson(id_token_url) - .catch(error => { - throw new Error(`Failed to get ID Token. \n - Error Code : ${error.statusCode}\n - Error Message: ${error.message}`); - }); - const id_token = (_a = res.result) === null || _a === void 0 ? void 0 : _a.value; - if (!id_token) { - throw new Error('Response json body do not have ID Token field'); - } - return id_token; - }); + + if (node.type === 'brace' && node.invalid !== true && node.nodes.length === 2) { + q.push(append(q.pop(), ['{}'])); + return; } - static getIDToken(audience) { - return __awaiter(this, void 0, void 0, function* () { - try { - // New ID Token is requested from action service - let id_token_url = OidcClient.getIDTokenUrl(); - if (audience) { - const encodedAudience = encodeURIComponent(audience); - id_token_url = `${id_token_url}&audience=${encodedAudience}`; - } - (0, core_1.debug)(`ID token url is ${id_token_url}`); - const id_token = yield OidcClient.getCall(id_token_url); - (0, core_1.setSecret)(id_token); - return id_token; - } - catch (error) { - throw new Error(`Error message: ${error.message}`); - } - }); + + if (node.nodes && node.ranges > 0) { + const args = utils.reduce(node.nodes); + + if (utils.exceedsLimit(...args, options.step, rangeLimit)) { + throw new RangeError('expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.'); + } + + let range = fill(...args, options); + if (range.length === 0) { + range = stringify(node, options); + } + + q.push(append(q.pop(), range)); + node.nodes = []; + return; } -} -exports.OidcClient = OidcClient; -//# sourceMappingURL=oidc-utils.js.map -/***/ }), + const enclose = utils.encloseBrace(node); + let queue = node.queue; + let block = node; -/***/ 2403: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + while (block.type !== 'brace' && block.type !== 'root' && block.parent) { + block = block.parent; + queue = block.queue; + } + + for (let i = 0; i < node.nodes.length; i++) { + const child = node.nodes[i]; + + if (child.type === 'comma' && node.type === 'brace') { + if (i === 1) queue.push(''); + queue.push(''); + continue; + } + + if (child.type === 'close') { + q.push(append(q.pop(), queue, enclose)); + continue; + } -"use strict"; + if (child.value && child.type !== 'open') { + queue.push(append(queue.pop(), child.value)); + continue; + } -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; + if (child.nodes) { + walk(child, node); + } } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; - }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; - }; -})(); -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.toPosixPath = toPosixPath; -exports.toWin32Path = toWin32Path; -exports.toPlatformPath = toPlatformPath; -const path = __importStar(__nccwpck_require__(6928)); -/** - * toPosixPath converts the given path to the posix form. On Windows, \\ will be - * replaced with /. - * - * @param pth. Path to transform. - * @return string Posix path. - */ -function toPosixPath(pth) { - return pth.replace(/[\\]/g, '/'); -} + + return queue; + }; + + return utils.flatten(walk(ast)); +}; + +module.exports = expand; + + +/***/ }), + +/***/ 2259: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + + + +const stringify = __nccwpck_require__(5373); + /** - * toWin32Path converts the given path to the win32 form. On Linux, / will be - * replaced with \\. - * - * @param pth. Path to transform. - * @return string Win32 path. + * Constants */ -function toWin32Path(pth) { - return pth.replace(/[/]/g, '\\'); -} + +const { + MAX_LENGTH, + CHAR_BACKSLASH, /* \ */ + CHAR_BACKTICK, /* ` */ + CHAR_COMMA, /* , */ + CHAR_DOT, /* . */ + CHAR_LEFT_PARENTHESES, /* ( */ + CHAR_RIGHT_PARENTHESES, /* ) */ + CHAR_LEFT_CURLY_BRACE, /* { */ + CHAR_RIGHT_CURLY_BRACE, /* } */ + CHAR_LEFT_SQUARE_BRACKET, /* [ */ + CHAR_RIGHT_SQUARE_BRACKET, /* ] */ + CHAR_DOUBLE_QUOTE, /* " */ + CHAR_SINGLE_QUOTE, /* ' */ + CHAR_NO_BREAK_SPACE, + CHAR_ZERO_WIDTH_NOBREAK_SPACE +} = __nccwpck_require__(7205); + /** - * toPlatformPath converts the given path to a platform-specific path. It does - * this by replacing instances of / and \ with the platform-specific path - * separator. - * - * @param pth The path to platformize. - * @return string The platform-specific path. + * parse */ -function toPlatformPath(pth) { - return pth.replace(/[/\\]/g, path.sep); -} -//# sourceMappingURL=path-utils.js.map -/***/ }), +const parse = (input, options = {}) => { + if (typeof input !== 'string') { + throw new TypeError('Expected a string'); + } + + const opts = options || {}; + const max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH; + if (input.length > max) { + throw new SyntaxError(`Input length (${input.length}), exceeds max characters (${max})`); + } -/***/ 5739: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + const ast = { type: 'root', input, nodes: [] }; + const stack = [ast]; + let block = ast; + let prev = ast; + let brackets = 0; + const length = input.length; + let index = 0; + let depth = 0; + let value; + + /** + * Helpers + */ -"use strict"; + const advance = () => input[index++]; + const push = node => { + if (node.type === 'text' && prev.type === 'dot') { + prev.type = 'text'; + } -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; + if (prev && prev.type === 'text' && node.type === 'text') { + prev.value += node.value; + return; } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; - }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; - }; -})(); -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.isLinux = exports.isMacOS = exports.isWindows = exports.arch = exports.platform = void 0; -exports.getDetails = getDetails; -const os_1 = __importDefault(__nccwpck_require__(857)); -const exec = __importStar(__nccwpck_require__(6362)); -const getWindowsInfo = () => __awaiter(void 0, void 0, void 0, function* () { - const { stdout: version } = yield exec.getExecOutput('powershell -command "(Get-CimInstance -ClassName Win32_OperatingSystem).Version"', undefined, { - silent: true - }); - const { stdout: name } = yield exec.getExecOutput('powershell -command "(Get-CimInstance -ClassName Win32_OperatingSystem).Caption"', undefined, { - silent: true - }); - return { - name: name.trim(), - version: version.trim() - }; -}); -const getMacOsInfo = () => __awaiter(void 0, void 0, void 0, function* () { - var _a, _b, _c, _d; - const { stdout } = yield exec.getExecOutput('sw_vers', undefined, { - silent: true - }); - const version = (_b = (_a = stdout.match(/ProductVersion:\s*(.+)/)) === null || _a === void 0 ? void 0 : _a[1]) !== null && _b !== void 0 ? _b : ''; - const name = (_d = (_c = stdout.match(/ProductName:\s*(.+)/)) === null || _c === void 0 ? void 0 : _c[1]) !== null && _d !== void 0 ? _d : ''; - return { - name, - version - }; -}); -const getLinuxInfo = () => __awaiter(void 0, void 0, void 0, function* () { - const { stdout } = yield exec.getExecOutput('lsb_release', ['-i', '-r', '-s'], { - silent: true - }); - const [name, version] = stdout.trim().split('\n'); - return { - name, - version - }; -}); -exports.platform = os_1.default.platform(); -exports.arch = os_1.default.arch(); -exports.isWindows = exports.platform === 'win32'; -exports.isMacOS = exports.platform === 'darwin'; -exports.isLinux = exports.platform === 'linux'; -function getDetails() { - return __awaiter(this, void 0, void 0, function* () { - return Object.assign(Object.assign({}, (yield (exports.isWindows - ? getWindowsInfo() - : exports.isMacOS - ? getMacOsInfo() - : getLinuxInfo()))), { platform: exports.platform, - arch: exports.arch, - isWindows: exports.isWindows, - isMacOS: exports.isMacOS, - isLinux: exports.isLinux }); - }); -} -//# sourceMappingURL=platform.js.map -/***/ }), + block.nodes.push(node); + node.parent = block; + node.prev = prev; + prev = node; + return node; + }; -/***/ 606: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + push({ type: 'bos' }); -"use strict"; + while (index < length) { + block = stack[stack.length - 1]; + value = advance(); -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.summary = exports.markdownSummary = exports.SUMMARY_DOCS_URL = exports.SUMMARY_ENV_VAR = void 0; -const os_1 = __nccwpck_require__(857); -const fs_1 = __nccwpck_require__(9896); -const { access, appendFile, writeFile } = fs_1.promises; -exports.SUMMARY_ENV_VAR = 'GITHUB_STEP_SUMMARY'; -exports.SUMMARY_DOCS_URL = 'https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary'; -class Summary { - constructor() { - this._buffer = ''; - } /** - * Finds the summary file path from the environment, rejects if env var is not found or file does not exist - * Also checks r/w permissions. - * - * @returns step summary file path + * Invalid chars */ - filePath() { - return __awaiter(this, void 0, void 0, function* () { - if (this._filePath) { - return this._filePath; - } - const pathFromEnv = process.env[exports.SUMMARY_ENV_VAR]; - if (!pathFromEnv) { - throw new Error(`Unable to find environment variable for $${exports.SUMMARY_ENV_VAR}. Check if your runtime environment supports job summaries.`); - } - try { - yield access(pathFromEnv, fs_1.constants.R_OK | fs_1.constants.W_OK); - } - catch (_a) { - throw new Error(`Unable to access summary file: '${pathFromEnv}'. Check if the file has correct read/write permissions.`); - } - this._filePath = pathFromEnv; - return this._filePath; - }); + + if (value === CHAR_ZERO_WIDTH_NOBREAK_SPACE || value === CHAR_NO_BREAK_SPACE) { + continue; } + /** - * Wraps content in an HTML tag, adding any HTML attributes - * - * @param {string} tag HTML tag to wrap - * @param {string | null} content content within the tag - * @param {[attribute: string]: string} attrs key-value list of HTML attributes to add - * - * @returns {string} content wrapped in HTML element + * Escaped chars */ - wrap(tag, content, attrs = {}) { - const htmlAttrs = Object.entries(attrs) - .map(([key, value]) => ` ${key}="${value}"`) - .join(''); - if (!content) { - return `<${tag}${htmlAttrs}>`; - } - return `<${tag}${htmlAttrs}>${content}`; + + if (value === CHAR_BACKSLASH) { + push({ type: 'text', value: (options.keepEscaping ? value : '') + advance() }); + continue; } + /** - * Writes text in the buffer to the summary buffer file and empties buffer. Will append by default. - * - * @param {SummaryWriteOptions} [options] (optional) options for write operation - * - * @returns {Promise} summary instance - */ - write(options) { - return __awaiter(this, void 0, void 0, function* () { - const overwrite = !!(options === null || options === void 0 ? void 0 : options.overwrite); - const filePath = yield this.filePath(); - const writeFunc = overwrite ? writeFile : appendFile; - yield writeFunc(filePath, this._buffer, { encoding: 'utf8' }); - return this.emptyBuffer(); - }); - } - /** - * Clears the summary buffer and wipes the summary file - * - * @returns {Summary} summary instance - */ - clear() { - return __awaiter(this, void 0, void 0, function* () { - return this.emptyBuffer().write({ overwrite: true }); - }); - } - /** - * Returns the current summary buffer as a string - * - * @returns {string} string of summary buffer - */ - stringify() { - return this._buffer; - } - /** - * If the summary buffer is empty - * - * @returns {boolen} true if the buffer is empty - */ - isEmptyBuffer() { - return this._buffer.length === 0; - } - /** - * Resets the summary buffer without writing to summary file - * - * @returns {Summary} summary instance + * Right square bracket (literal): ']' */ - emptyBuffer() { - this._buffer = ''; - return this; + + if (value === CHAR_RIGHT_SQUARE_BRACKET) { + push({ type: 'text', value: '\\' + value }); + continue; } + /** - * Adds raw text to the summary buffer - * - * @param {string} text content to add - * @param {boolean} [addEOL=false] (optional) append an EOL to the raw text (default: false) - * - * @returns {Summary} summary instance + * Left square bracket: '[' */ - addRaw(text, addEOL = false) { - this._buffer += text; - return addEOL ? this.addEOL() : this; + + if (value === CHAR_LEFT_SQUARE_BRACKET) { + brackets++; + + let next; + + while (index < length && (next = advance())) { + value += next; + + if (next === CHAR_LEFT_SQUARE_BRACKET) { + brackets++; + continue; + } + + if (next === CHAR_BACKSLASH) { + value += advance(); + continue; + } + + if (next === CHAR_RIGHT_SQUARE_BRACKET) { + brackets--; + + if (brackets === 0) { + break; + } + } + } + + push({ type: 'text', value }); + continue; } + /** - * Adds the operating system-specific end-of-line marker to the buffer - * - * @returns {Summary} summary instance + * Parentheses */ - addEOL() { - return this.addRaw(os_1.EOL); + + if (value === CHAR_LEFT_PARENTHESES) { + block = push({ type: 'paren', nodes: [] }); + stack.push(block); + push({ type: 'text', value }); + continue; } - /** - * Adds an HTML codeblock to the summary buffer - * - * @param {string} code content to render within fenced code block - * @param {string} lang (optional) language to syntax highlight code - * - * @returns {Summary} summary instance - */ - addCodeBlock(code, lang) { - const attrs = Object.assign({}, (lang && { lang })); - const element = this.wrap('pre', this.wrap('code', code), attrs); - return this.addRaw(element).addEOL(); + + if (value === CHAR_RIGHT_PARENTHESES) { + if (block.type !== 'paren') { + push({ type: 'text', value }); + continue; + } + block = stack.pop(); + push({ type: 'text', value }); + block = stack[stack.length - 1]; + continue; } + /** - * Adds an HTML list to the summary buffer - * - * @param {string[]} items list of items to render - * @param {boolean} [ordered=false] (optional) if the rendered list should be ordered or not (default: false) - * - * @returns {Summary} summary instance + * Quotes: '|"|` */ - addList(items, ordered = false) { - const tag = ordered ? 'ol' : 'ul'; - const listItems = items.map(item => this.wrap('li', item)).join(''); - const element = this.wrap(tag, listItems); - return this.addRaw(element).addEOL(); + + if (value === CHAR_DOUBLE_QUOTE || value === CHAR_SINGLE_QUOTE || value === CHAR_BACKTICK) { + const open = value; + let next; + + if (options.keepQuotes !== true) { + value = ''; + } + + while (index < length && (next = advance())) { + if (next === CHAR_BACKSLASH) { + value += next + advance(); + continue; + } + + if (next === open) { + if (options.keepQuotes === true) value += next; + break; + } + + value += next; + } + + push({ type: 'text', value }); + continue; } + /** - * Adds an HTML table to the summary buffer - * - * @param {SummaryTableCell[]} rows table rows - * - * @returns {Summary} summary instance + * Left curly brace: '{' */ - addTable(rows) { - const tableBody = rows - .map(row => { - const cells = row - .map(cell => { - if (typeof cell === 'string') { - return this.wrap('td', cell); - } - const { header, data, colspan, rowspan } = cell; - const tag = header ? 'th' : 'td'; - const attrs = Object.assign(Object.assign({}, (colspan && { colspan })), (rowspan && { rowspan })); - return this.wrap(tag, data, attrs); - }) - .join(''); - return this.wrap('tr', cells); - }) - .join(''); - const element = this.wrap('table', tableBody); - return this.addRaw(element).addEOL(); + + if (value === CHAR_LEFT_CURLY_BRACE) { + depth++; + + const dollar = prev.value && prev.value.slice(-1) === '$' || block.dollar === true; + const brace = { + type: 'brace', + open: true, + close: false, + dollar, + depth, + commas: 0, + ranges: 0, + nodes: [] + }; + + block = push(brace); + stack.push(block); + push({ type: 'open', value }); + continue; } + /** - * Adds a collapsable HTML details element to the summary buffer - * - * @param {string} label text for the closed state - * @param {string} content collapsable content - * - * @returns {Summary} summary instance + * Right curly brace: '}' */ - addDetails(label, content) { - const element = this.wrap('details', this.wrap('summary', label) + content); - return this.addRaw(element).addEOL(); + + if (value === CHAR_RIGHT_CURLY_BRACE) { + if (block.type !== 'brace') { + push({ type: 'text', value }); + continue; + } + + const type = 'close'; + block = stack.pop(); + block.close = true; + + push({ type, value }); + depth--; + + block = stack[stack.length - 1]; + continue; } + /** - * Adds an HTML image tag to the summary buffer - * - * @param {string} src path to the image you to embed - * @param {string} alt text description of the image - * @param {SummaryImageOptions} options (optional) addition image attributes - * - * @returns {Summary} summary instance + * Comma: ',' */ - addImage(src, alt, options) { - const { width, height } = options || {}; - const attrs = Object.assign(Object.assign({}, (width && { width })), (height && { height })); - const element = this.wrap('img', null, Object.assign({ src, alt }, attrs)); - return this.addRaw(element).addEOL(); + + if (value === CHAR_COMMA && depth > 0) { + if (block.ranges > 0) { + block.ranges = 0; + const open = block.nodes.shift(); + block.nodes = [open, { type: 'text', value: stringify(block) }]; + } + + push({ type: 'comma', value }); + block.commas++; + continue; } + /** - * Adds an HTML section heading element - * - * @param {string} text heading text - * @param {number | string} [level=1] (optional) the heading level, default: 1 - * - * @returns {Summary} summary instance + * Dot: '.' */ - addHeading(text, level) { - const tag = `h${level}`; - const allowedTag = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'].includes(tag) - ? tag - : 'h1'; - const element = this.wrap(allowedTag, text); - return this.addRaw(element).addEOL(); + + if (value === CHAR_DOT && depth > 0 && block.commas === 0) { + const siblings = block.nodes; + + if (depth === 0 || siblings.length === 0) { + push({ type: 'text', value }); + continue; + } + + if (prev.type === 'dot') { + block.range = []; + prev.value += value; + prev.type = 'range'; + + if (block.nodes.length !== 3 && block.nodes.length !== 5) { + block.invalid = true; + block.ranges = 0; + prev.type = 'text'; + continue; + } + + block.ranges++; + block.args = []; + continue; + } + + if (prev.type === 'range') { + siblings.pop(); + + const before = siblings[siblings.length - 1]; + before.value += prev.value + value; + prev = before; + block.ranges--; + continue; + } + + push({ type: 'dot', value }); + continue; } + /** - * Adds an HTML thematic break (
) to the summary buffer - * - * @returns {Summary} summary instance + * Text */ - addSeparator() { - const element = this.wrap('hr', null); - return this.addRaw(element).addEOL(); + + push({ type: 'text', value }); + } + + // Mark imbalanced braces and brackets as invalid + do { + block = stack.pop(); + + if (block.type !== 'root') { + block.nodes.forEach(node => { + if (!node.nodes) { + if (node.type === 'open') node.isOpen = true; + if (node.type === 'close') node.isClose = true; + if (!node.nodes) node.type = 'text'; + node.invalid = true; + } + }); + + // get the location of the block on parent.nodes (block's siblings) + const parent = stack[stack.length - 1]; + const index = parent.nodes.indexOf(block); + // replace the (invalid) block with it's nodes + parent.nodes.splice(index, 1, ...block.nodes); } - /** - * Adds an HTML line break (
) to the summary buffer - * - * @returns {Summary} summary instance - */ - addBreak() { - const element = this.wrap('br', null); - return this.addRaw(element).addEOL(); + } while (stack.length > 0); + + push({ type: 'eos' }); + return ast; +}; + +module.exports = parse; + + +/***/ }), + +/***/ 5373: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + + + +const utils = __nccwpck_require__(6825); + +module.exports = (ast, options = {}) => { + const stringify = (node, parent = {}) => { + const invalidBlock = options.escapeInvalid && utils.isInvalidBrace(parent); + const invalidNode = node.invalid === true && options.escapeInvalid === true; + let output = ''; + + if (node.value) { + if ((invalidBlock || invalidNode) && utils.isOpenOrClose(node)) { + return '\\' + node.value; + } + return node.value; } - /** - * Adds an HTML blockquote to the summary buffer - * - * @param {string} text quote text - * @param {string} cite (optional) citation url - * - * @returns {Summary} summary instance - */ - addQuote(text, cite) { - const attrs = Object.assign({}, (cite && { cite })); - const element = this.wrap('blockquote', text, attrs); - return this.addRaw(element).addEOL(); + + if (node.value) { + return node.value; } - /** - * Adds an HTML anchor tag to the summary buffer - * - * @param {string} text link text/content - * @param {string} href hyperlink - * - * @returns {Summary} summary instance - */ - addLink(text, href) { - const element = this.wrap('a', text, { href }); - return this.addRaw(element).addEOL(); + + if (node.nodes) { + for (const child of node.nodes) { + output += stringify(child); + } } -} -const _summary = new Summary(); -/** - * @deprecated use `core.summary` - */ -exports.markdownSummary = _summary; -exports.summary = _summary; -//# sourceMappingURL=summary.js.map + return output; + }; + + return stringify(ast); +}; + + /***/ }), -/***/ 5219: +/***/ 6825: /***/ ((__unused_webpack_module, exports) => { -"use strict"; -// We use any as a valid input type -/* eslint-disable @typescript-eslint/no-explicit-any */ -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.toCommandValue = toCommandValue; -exports.toCommandProperties = toCommandProperties; + +exports.isInteger = num => { + if (typeof num === 'number') { + return Number.isInteger(num); + } + if (typeof num === 'string' && num.trim() !== '') { + return Number.isInteger(Number(num)); + } + return false; +}; + /** - * Sanitizes an input into a string so it can be passed into issueCommand safely - * @param input input to sanitize into a string + * Find a node of the given type */ -function toCommandValue(input) { - if (input === null || input === undefined) { - return ''; - } - else if (typeof input === 'string' || input instanceof String) { - return input; - } - return JSON.stringify(input); -} + +exports.find = (node, type) => node.nodes.find(node => node.type === type); + /** - * - * @param annotationProperties - * @returns The command properties to send with the actual annotation command - * See IssueCommandProperties: https://github.com/actions/runner/blob/main/src/Runner.Worker/ActionCommandManager.cs#L646 + * Find a node of the given type */ -function toCommandProperties(annotationProperties) { - if (!Object.keys(annotationProperties).length) { - return {}; - } - return { - title: annotationProperties.title, - file: annotationProperties.file, - line: annotationProperties.startLine, - endLine: annotationProperties.endLine, - col: annotationProperties.startColumn, - endColumn: annotationProperties.endColumn - }; -} -//# sourceMappingURL=utils.js.map -/***/ }), +exports.exceedsLimit = (min, max, step = 1, limit) => { + if (limit === false) return false; + if (!exports.isInteger(min) || !exports.isInteger(max)) return false; + return ((Number(max) - Number(min)) / Number(step)) >= limit; +}; -/***/ 6362: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { +/** + * Escape the given node with '\\' before node.value + */ -"use strict"; +exports.escapeNode = (block, n = 0, type) => { + const node = block.nodes[n]; + if (!node) return; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; + if ((type && node.type === type) || node.type === 'open' || node.type === 'close') { + if (node.escaped !== true) { + node.value = '\\' + node.value; + node.escaped = true; } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; - }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; - }; -})(); -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); + } }; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.exec = exec; -exports.getExecOutput = getExecOutput; -const string_decoder_1 = __nccwpck_require__(3193); -const tr = __importStar(__nccwpck_require__(115)); + /** - * Exec a command. - * Output will be streamed to the live console. - * Returns promise with return code - * - * @param commandLine command to execute (can include additional args). Must be correctly escaped. - * @param args optional arguments for tool. Escaping is handled by the lib. - * @param options optional exec options. See ExecOptions - * @returns Promise exit code + * Returns true if the given brace node should be enclosed in literal braces */ -function exec(commandLine, args, options) { - return __awaiter(this, void 0, void 0, function* () { - const commandArgs = tr.argStringToArray(commandLine); - if (commandArgs.length === 0) { - throw new Error(`Parameter 'commandLine' cannot be null or empty.`); - } - // Path to tool to execute should be first arg - const toolPath = commandArgs[0]; - args = commandArgs.slice(1).concat(args || []); - const runner = new tr.ToolRunner(toolPath, args, options); - return runner.exec(); - }); -} + +exports.encloseBrace = node => { + if (node.type !== 'brace') return false; + if ((node.commas >> 0 + node.ranges >> 0) === 0) { + node.invalid = true; + return true; + } + return false; +}; + /** - * Exec a command and get the output. - * Output will be streamed to the live console. - * Returns promise with the exit code and collected stdout and stderr - * - * @param commandLine command to execute (can include additional args). Must be correctly escaped. - * @param args optional arguments for tool. Escaping is handled by the lib. - * @param options optional exec options. See ExecOptions - * @returns Promise exit code, stdout, and stderr + * Returns true if a brace node is invalid. */ -function getExecOutput(commandLine, args, options) { - return __awaiter(this, void 0, void 0, function* () { - var _a, _b; - let stdout = ''; - let stderr = ''; - //Using string decoder covers the case where a mult-byte character is split - const stdoutDecoder = new string_decoder_1.StringDecoder('utf8'); - const stderrDecoder = new string_decoder_1.StringDecoder('utf8'); - const originalStdoutListener = (_a = options === null || options === void 0 ? void 0 : options.listeners) === null || _a === void 0 ? void 0 : _a.stdout; - const originalStdErrListener = (_b = options === null || options === void 0 ? void 0 : options.listeners) === null || _b === void 0 ? void 0 : _b.stderr; - const stdErrListener = (data) => { - stderr += stderrDecoder.write(data); - if (originalStdErrListener) { - originalStdErrListener(data); - } - }; - const stdOutListener = (data) => { - stdout += stdoutDecoder.write(data); - if (originalStdoutListener) { - originalStdoutListener(data); - } - }; - const listeners = Object.assign(Object.assign({}, options === null || options === void 0 ? void 0 : options.listeners), { stdout: stdOutListener, stderr: stdErrListener }); - const exitCode = yield exec(commandLine, args, Object.assign(Object.assign({}, options), { listeners })); - //flush any remaining characters - stdout += stdoutDecoder.end(); - stderr += stderrDecoder.end(); - return { - exitCode, - stdout, - stderr - }; - }); + +exports.isInvalidBrace = block => { + if (block.type !== 'brace') return false; + if (block.invalid === true || block.dollar) return true; + if ((block.commas >> 0 + block.ranges >> 0) === 0) { + block.invalid = true; + return true; + } + if (block.open !== true || block.close !== true) { + block.invalid = true; + return true; + } + return false; +}; + +/** + * Returns true if a node is an open or close node + */ + +exports.isOpenOrClose = node => { + if (node.type === 'open' || node.type === 'close') { + return true; + } + return node.open === true || node.close === true; +}; + +/** + * Reduce an array of text nodes. + */ + +exports.reduce = nodes => nodes.reduce((acc, node) => { + if (node.type === 'text') acc.push(node.value); + if (node.type === 'range') node.type = 'text'; + return acc; +}, []); + +/** + * Flatten an array + */ + +exports.flatten = (...args) => { + const result = []; + + const flat = arr => { + for (let i = 0; i < arr.length; i++) { + const ele = arr[i]; + + if (Array.isArray(ele)) { + flat(ele); + continue; + } + + if (ele !== undefined) { + result.push(ele); + } + } + return result; + }; + + flat(args); + return result; +}; + + +/***/ }), + +/***/ 7494: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + + + +const cp = __nccwpck_require__(5317); +const parse = __nccwpck_require__(3913); +const enoent = __nccwpck_require__(7161); + +function spawn(command, args, options) { + // Parse the arguments + const parsed = parse(command, args, options); + + // Spawn the child process + const spawned = cp.spawn(parsed.command, parsed.args, parsed.options); + + // Hook into child process "exit" event to emit an error if the command + // does not exists, see: https://github.com/IndigoUnited/node-cross-spawn/issues/16 + enoent.hookChildProcess(spawned, parsed); + + return spawned; } -//# sourceMappingURL=exec.js.map + +function spawnSync(command, args, options) { + // Parse the arguments + const parsed = parse(command, args, options); + + // Spawn the child process + const result = cp.spawnSync(parsed.command, parsed.args, parsed.options); + + // Analyze if the command does not exist, see: https://github.com/IndigoUnited/node-cross-spawn/issues/16 + result.error = result.error || enoent.verifyENOENTSync(result.status, parsed); + + return result; +} + +module.exports = spawn; +module.exports.spawn = spawn; +module.exports.sync = spawnSync; + +module.exports._parse = parse; +module.exports._enoent = enoent; + /***/ }), -/***/ 115: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { +/***/ 7161: +/***/ ((module) => { -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; - }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; - }; -})(); -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); + +const isWin = process.platform === 'win32'; + +function notFoundError(original, syscall) { + return Object.assign(new Error(`${syscall} ${original.command} ENOENT`), { + code: 'ENOENT', + errno: 'ENOENT', + syscall: `${syscall} ${original.command}`, + path: original.command, + spawnargs: original.args, }); -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.ToolRunner = void 0; -exports.argStringToArray = argStringToArray; -const os = __importStar(__nccwpck_require__(857)); -const events = __importStar(__nccwpck_require__(4434)); -const child = __importStar(__nccwpck_require__(5317)); -const path = __importStar(__nccwpck_require__(6928)); -const io = __importStar(__nccwpck_require__(6359)); -const ioUtil = __importStar(__nccwpck_require__(6760)); -const timers_1 = __nccwpck_require__(3557); -/* eslint-disable @typescript-eslint/unbound-method */ -const IS_WINDOWS = process.platform === 'win32'; -/* - * Class for running command line tools. Handles quoting and arg parsing in a platform agnostic way. - */ -class ToolRunner extends events.EventEmitter { - constructor(toolPath, args, options) { - super(); - if (!toolPath) { - throw new Error("Parameter 'toolPath' cannot be null or empty."); - } - this.toolPath = toolPath; - this.args = args || []; - this.options = options || {}; - } - _debug(message) { - if (this.options.listeners && this.options.listeners.debug) { - this.options.listeners.debug(message); - } +} + +function hookChildProcess(cp, parsed) { + if (!isWin) { + return; } - _getCommandString(options, noPrefix) { - const toolPath = this._getSpawnFileName(); - const args = this._getSpawnArgs(options); - let cmd = noPrefix ? '' : '[command]'; // omit prefix when piped to a second tool - if (IS_WINDOWS) { - // Windows + cmd file - if (this._isCmdFile()) { - cmd += toolPath; - for (const a of args) { - cmd += ` ${a}`; - } - } - // Windows + verbatim - else if (options.windowsVerbatimArguments) { - cmd += `"${toolPath}"`; - for (const a of args) { - cmd += ` ${a}`; - } - } - // Windows (regular) - else { - cmd += this._windowsQuoteCmdArg(toolPath); - for (const a of args) { - cmd += ` ${this._windowsQuoteCmdArg(a)}`; - } - } - } - else { - // OSX/Linux - this can likely be improved with some form of quoting. - // creating processes on Unix is fundamentally different than Windows. - // on Unix, execvp() takes an arg array. - cmd += toolPath; - for (const a of args) { - cmd += ` ${a}`; + + const originalEmit = cp.emit; + + cp.emit = function (name, arg1) { + // If emitting "exit" event and exit code is 1, we need to check if + // the command exists and emit an "error" instead + // See https://github.com/IndigoUnited/node-cross-spawn/issues/16 + if (name === 'exit') { + const err = verifyENOENT(arg1, parsed); + + if (err) { + return originalEmit.call(cp, 'error', err); } } - return cmd; + + return originalEmit.apply(cp, arguments); // eslint-disable-line prefer-rest-params + }; +} + +function verifyENOENT(status, parsed) { + if (isWin && status === 1 && !parsed.file) { + return notFoundError(parsed.original, 'spawn'); } - _processLineBuffer(data, strBuffer, onLine) { - try { - let s = strBuffer + data.toString(); - let n = s.indexOf(os.EOL); - while (n > -1) { - const line = s.substring(0, n); - onLine(line); - // the rest of the string ... - s = s.substring(n + os.EOL.length); - n = s.indexOf(os.EOL); - } - return s; - } - catch (err) { - // streaming lines to console is best effort. Don't fail a build. - this._debug(`error processing line. Failed with error ${err}`); - return ''; - } + + return null; +} + +function verifyENOENTSync(status, parsed) { + if (isWin && status === 1 && !parsed.file) { + return notFoundError(parsed.original, 'spawnSync'); } - _getSpawnFileName() { - if (IS_WINDOWS) { - if (this._isCmdFile()) { - return process.env['COMSPEC'] || 'cmd.exe'; - } - } - return this.toolPath; + + return null; +} + +module.exports = { + hookChildProcess, + verifyENOENT, + verifyENOENTSync, + notFoundError, +}; + + +/***/ }), + +/***/ 3913: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + + + +const path = __nccwpck_require__(6928); +const resolveCommand = __nccwpck_require__(8062); +const escape = __nccwpck_require__(8160); +const readShebang = __nccwpck_require__(6195); + +const isWin = process.platform === 'win32'; +const isExecutableRegExp = /\.(?:com|exe)$/i; +const isCmdShimRegExp = /node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i; + +function detectShebang(parsed) { + parsed.file = resolveCommand(parsed); + + const shebang = parsed.file && readShebang(parsed.file); + + if (shebang) { + parsed.args.unshift(parsed.file); + parsed.command = shebang; + + return resolveCommand(parsed); } - _getSpawnArgs(options) { - if (IS_WINDOWS) { - if (this._isCmdFile()) { - let argline = `/D /S /C "${this._windowsQuoteCmdArg(this.toolPath)}`; - for (const a of this.args) { - argline += ' '; - argline += options.windowsVerbatimArguments - ? a - : this._windowsQuoteCmdArg(a); - } - argline += '"'; - return [argline]; - } - } - return this.args; + + return parsed.file; +} + +function parseNonShell(parsed) { + if (!isWin) { + return parsed; } - _endsWith(str, end) { - return str.endsWith(end); + + // Detect & add support for shebangs + const commandFile = detectShebang(parsed); + + // We don't need a shell if the command filename is an executable + const needsShell = !isExecutableRegExp.test(commandFile); + + // If a shell is required, use cmd.exe and take care of escaping everything correctly + // Note that `forceShell` is an hidden option used only in tests + if (parsed.options.forceShell || needsShell) { + // Need to double escape meta chars if the command is a cmd-shim located in `node_modules/.bin/` + // The cmd-shim simply calls execute the package bin file with NodeJS, proxying any argument + // Because the escape of metachars with ^ gets interpreted when the cmd.exe is first called, + // we need to double escape them + const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile); + + // Normalize posix paths into OS compatible paths (e.g.: foo/bar -> foo\bar) + // This is necessary otherwise it will always fail with ENOENT in those cases + parsed.command = path.normalize(parsed.command); + + // Escape command & arguments + parsed.command = escape.command(parsed.command); + parsed.args = parsed.args.map((arg) => escape.argument(arg, needsDoubleEscapeMetaChars)); + + const shellCommand = [parsed.command].concat(parsed.args).join(' '); + + parsed.args = ['/d', '/s', '/c', `"${shellCommand}"`]; + parsed.command = process.env.comspec || 'cmd.exe'; + parsed.options.windowsVerbatimArguments = true; // Tell node's spawn that the arguments are already escaped } - _isCmdFile() { - const upperToolPath = this.toolPath.toUpperCase(); - return (this._endsWith(upperToolPath, '.CMD') || - this._endsWith(upperToolPath, '.BAT')); - } - _windowsQuoteCmdArg(arg) { - // for .exe, apply the normal quoting rules that libuv applies - if (!this._isCmdFile()) { - return this._uvQuoteCmdArg(arg); - } - // otherwise apply quoting rules specific to the cmd.exe command line parser. - // the libuv rules are generic and are not designed specifically for cmd.exe - // command line parser. - // - // for a detailed description of the cmd.exe command line parser, refer to - // http://stackoverflow.com/questions/4094699/how-does-the-windows-command-interpreter-cmd-exe-parse-scripts/7970912#7970912 - // need quotes for empty arg - if (!arg) { - return '""'; - } - // determine whether the arg needs to be quoted - const cmdSpecialChars = [ - ' ', - '\t', - '&', - '(', - ')', - '[', - ']', - '{', - '}', - '^', - '=', - ';', - '!', - "'", - '+', - ',', - '`', - '~', - '|', - '<', - '>', - '"' - ]; - let needsQuotes = false; - for (const char of arg) { - if (cmdSpecialChars.some(x => x === char)) { - needsQuotes = true; - break; - } - } - // short-circuit if quotes not needed - if (!needsQuotes) { - return arg; - } - // the following quoting rules are very similar to the rules that by libuv applies. - // - // 1) wrap the string in quotes - // - // 2) double-up quotes - i.e. " => "" - // - // this is different from the libuv quoting rules. libuv replaces " with \", which unfortunately - // doesn't work well with a cmd.exe command line. - // - // note, replacing " with "" also works well if the arg is passed to a downstream .NET console app. - // for example, the command line: - // foo.exe "myarg:""my val""" - // is parsed by a .NET console app into an arg array: - // [ "myarg:\"my val\"" ] - // which is the same end result when applying libuv quoting rules. although the actual - // command line from libuv quoting rules would look like: - // foo.exe "myarg:\"my val\"" - // - // 3) double-up slashes that precede a quote, - // e.g. hello \world => "hello \world" - // hello\"world => "hello\\""world" - // hello\\"world => "hello\\\\""world" - // hello world\ => "hello world\\" - // - // technically this is not required for a cmd.exe command line, or the batch argument parser. - // the reasons for including this as a .cmd quoting rule are: - // - // a) this is optimized for the scenario where the argument is passed from the .cmd file to an - // external program. many programs (e.g. .NET console apps) rely on the slash-doubling rule. - // - // b) it's what we've been doing previously (by deferring to node default behavior) and we - // haven't heard any complaints about that aspect. - // - // note, a weakness of the quoting rules chosen here, is that % is not escaped. in fact, % cannot be - // escaped when used on the command line directly - even though within a .cmd file % can be escaped - // by using %%. - // - // the saving grace is, on the command line, %var% is left as-is if var is not defined. this contrasts - // the line parsing rules within a .cmd file, where if var is not defined it is replaced with nothing. - // - // one option that was explored was replacing % with ^% - i.e. %var% => ^%var^%. this hack would - // often work, since it is unlikely that var^ would exist, and the ^ character is removed when the - // variable is used. the problem, however, is that ^ is not removed when %* is used to pass the args - // to an external program. - // - // an unexplored potential solution for the % escaping problem, is to create a wrapper .cmd file. - // % can be escaped within a .cmd file. - let reverse = '"'; - let quoteHit = true; - for (let i = arg.length; i > 0; i--) { - // walk the string in reverse - reverse += arg[i - 1]; - if (quoteHit && arg[i - 1] === '\\') { - reverse += '\\'; // double the slash - } - else if (arg[i - 1] === '"') { - quoteHit = true; - reverse += '"'; // double the quote - } - else { - quoteHit = false; - } - } - reverse += '"'; - return reverse.split('').reverse().join(''); - } - _uvQuoteCmdArg(arg) { - // Tool runner wraps child_process.spawn() and needs to apply the same quoting as - // Node in certain cases where the undocumented spawn option windowsVerbatimArguments - // is used. - // - // Since this function is a port of quote_cmd_arg from Node 4.x (technically, lib UV, - // see https://github.com/nodejs/node/blob/v4.x/deps/uv/src/win/process.c for details), - // pasting copyright notice from Node within this function: - // - // Copyright Joyent, Inc. and other Node contributors. All rights reserved. - // - // 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. - if (!arg) { - // Need double quotation for empty argument - return '""'; - } - if (!arg.includes(' ') && !arg.includes('\t') && !arg.includes('"')) { - // No quotation needed - return arg; - } - if (!arg.includes('"') && !arg.includes('\\')) { - // No embedded double quotes or backslashes, so I can just wrap - // quote marks around the whole thing. - return `"${arg}"`; - } - // Expected input/output: - // input : hello"world - // output: "hello\"world" - // input : hello""world - // output: "hello\"\"world" - // input : hello\world - // output: hello\world - // input : hello\\world - // output: hello\\world - // input : hello\"world - // output: "hello\\\"world" - // input : hello\\"world - // output: "hello\\\\\"world" - // input : hello world\ - // output: "hello world\\" - note the comment in libuv actually reads "hello world\" - // but it appears the comment is wrong, it should be "hello world\\" - let reverse = '"'; - let quoteHit = true; - for (let i = arg.length; i > 0; i--) { - // walk the string in reverse - reverse += arg[i - 1]; - if (quoteHit && arg[i - 1] === '\\') { - reverse += '\\'; - } - else if (arg[i - 1] === '"') { - quoteHit = true; - reverse += '\\'; - } - else { - quoteHit = false; - } - } - reverse += '"'; - return reverse.split('').reverse().join(''); - } - _cloneExecOptions(options) { - options = options || {}; - const result = { - cwd: options.cwd || process.cwd(), - env: options.env || process.env, - silent: options.silent || false, - windowsVerbatimArguments: options.windowsVerbatimArguments || false, - failOnStdErr: options.failOnStdErr || false, - ignoreReturnCode: options.ignoreReturnCode || false, - delay: options.delay || 10000 - }; - result.outStream = options.outStream || process.stdout; - result.errStream = options.errStream || process.stderr; - return result; - } - _getSpawnOptions(options, toolPath) { - options = options || {}; - const result = {}; - result.cwd = options.cwd; - result.env = options.env; - result['windowsVerbatimArguments'] = - options.windowsVerbatimArguments || this._isCmdFile(); - if (options.windowsVerbatimArguments) { - result.argv0 = `"${toolPath}"`; - } - return result; - } - /** - * Exec a tool. - * Output will be streamed to the live console. - * Returns promise with return code - * - * @param tool path to tool to exec - * @param options optional exec options. See ExecOptions - * @returns number - */ - exec() { - return __awaiter(this, void 0, void 0, function* () { - // root the tool path if it is unrooted and contains relative pathing - if (!ioUtil.isRooted(this.toolPath) && - (this.toolPath.includes('/') || - (IS_WINDOWS && this.toolPath.includes('\\')))) { - // prefer options.cwd if it is specified, however options.cwd may also need to be rooted - this.toolPath = path.resolve(process.cwd(), this.options.cwd || process.cwd(), this.toolPath); - } - // if the tool is only a file name, then resolve it from the PATH - // otherwise verify it exists (add extension on Windows if necessary) - this.toolPath = yield io.which(this.toolPath, true); - return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () { - this._debug(`exec tool: ${this.toolPath}`); - this._debug('arguments:'); - for (const arg of this.args) { - this._debug(` ${arg}`); - } - const optionsNonNull = this._cloneExecOptions(this.options); - if (!optionsNonNull.silent && optionsNonNull.outStream) { - optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os.EOL); - } - const state = new ExecState(optionsNonNull, this.toolPath); - state.on('debug', (message) => { - this._debug(message); - }); - if (this.options.cwd && !(yield ioUtil.exists(this.options.cwd))) { - return reject(new Error(`The cwd: ${this.options.cwd} does not exist!`)); - } - const fileName = this._getSpawnFileName(); - const cp = child.spawn(fileName, this._getSpawnArgs(optionsNonNull), this._getSpawnOptions(this.options, fileName)); - let stdbuffer = ''; - if (cp.stdout) { - cp.stdout.on('data', (data) => { - if (this.options.listeners && this.options.listeners.stdout) { - this.options.listeners.stdout(data); - } - if (!optionsNonNull.silent && optionsNonNull.outStream) { - optionsNonNull.outStream.write(data); - } - stdbuffer = this._processLineBuffer(data, stdbuffer, (line) => { - if (this.options.listeners && this.options.listeners.stdline) { - this.options.listeners.stdline(line); - } - }); - }); - } - let errbuffer = ''; - if (cp.stderr) { - cp.stderr.on('data', (data) => { - state.processStderr = true; - if (this.options.listeners && this.options.listeners.stderr) { - this.options.listeners.stderr(data); - } - if (!optionsNonNull.silent && - optionsNonNull.errStream && - optionsNonNull.outStream) { - const s = optionsNonNull.failOnStdErr - ? optionsNonNull.errStream - : optionsNonNull.outStream; - s.write(data); - } - errbuffer = this._processLineBuffer(data, errbuffer, (line) => { - if (this.options.listeners && this.options.listeners.errline) { - this.options.listeners.errline(line); - } - }); - }); - } - cp.on('error', (err) => { - state.processError = err.message; - state.processExited = true; - state.processClosed = true; - state.CheckComplete(); - }); - cp.on('exit', (code) => { - state.processExitCode = code; - state.processExited = true; - this._debug(`Exit code ${code} received from tool '${this.toolPath}'`); - state.CheckComplete(); - }); - cp.on('close', (code) => { - state.processExitCode = code; - state.processExited = true; - state.processClosed = true; - this._debug(`STDIO streams have closed for tool '${this.toolPath}'`); - state.CheckComplete(); - }); - state.on('done', (error, exitCode) => { - if (stdbuffer.length > 0) { - this.emit('stdline', stdbuffer); - } - if (errbuffer.length > 0) { - this.emit('errline', errbuffer); - } - cp.removeAllListeners(); - if (error) { - reject(error); - } - else { - resolve(exitCode); - } - }); - if (this.options.input) { - if (!cp.stdin) { - throw new Error('child process missing stdin'); - } - cp.stdin.end(this.options.input); - } - })); - }); - } -} -exports.ToolRunner = ToolRunner; -/** - * Convert an arg string to an array of args. Handles escaping - * - * @param argString string of arguments - * @returns string[] array of arguments - */ -function argStringToArray(argString) { - const args = []; - let inQuotes = false; - let escaped = false; - let arg = ''; - function append(c) { - // we only escape double quotes. - if (escaped && c !== '"') { - arg += '\\'; - } - arg += c; - escaped = false; - } - for (let i = 0; i < argString.length; i++) { - const c = argString.charAt(i); - if (c === '"') { - if (!escaped) { - inQuotes = !inQuotes; - } - else { - append(c); - } - continue; - } - if (c === '\\' && escaped) { - append(c); - continue; - } - if (c === '\\' && inQuotes) { - escaped = true; - continue; - } - if (c === ' ' && !inQuotes) { - if (arg.length > 0) { - args.push(arg); - arg = ''; - } - continue; - } - append(c); - } - if (arg.length > 0) { - args.push(arg.trim()); - } - return args; -} -class ExecState extends events.EventEmitter { - constructor(options, toolPath) { - super(); - this.processClosed = false; // tracks whether the process has exited and stdio is closed - this.processError = ''; - this.processExitCode = 0; - this.processExited = false; // tracks whether the process has exited - this.processStderr = false; // tracks whether stderr was written to - this.delay = 10000; // 10 seconds - this.done = false; - this.timeout = null; - if (!toolPath) { - throw new Error('toolPath must not be empty'); - } - this.options = options; - this.toolPath = toolPath; - if (options.delay) { - this.delay = options.delay; - } - } - CheckComplete() { - if (this.done) { - return; - } - if (this.processClosed) { - this._setResult(); - } - else if (this.processExited) { - this.timeout = (0, timers_1.setTimeout)(ExecState.HandleTimeout, this.delay, this); - } - } - _debug(message) { - this.emit('debug', message); - } - _setResult() { - // determine whether there is an error - let error; - if (this.processExited) { - if (this.processError) { - error = new Error(`There was an error when attempting to execute the process '${this.toolPath}'. This may indicate the process failed to start. Error: ${this.processError}`); - } - else if (this.processExitCode !== 0 && !this.options.ignoreReturnCode) { - error = new Error(`The process '${this.toolPath}' failed with exit code ${this.processExitCode}`); - } - else if (this.processStderr && this.options.failOnStdErr) { - error = new Error(`The process '${this.toolPath}' failed because one or more lines were written to the STDERR stream`); - } - } - // clear the timeout - if (this.timeout) { - clearTimeout(this.timeout); - this.timeout = null; - } - this.done = true; - this.emit('done', error, this.processExitCode); - } - static HandleTimeout(state) { - if (state.done) { - return; - } - if (!state.processClosed && state.processExited) { - const message = `The STDIO streams did not close within ${state.delay / 1000} seconds of the exit event from process '${state.toolPath}'. This may indicate a child process inherited the STDIO streams and has not yet exited.`; - state._debug(message); - } - state._setResult(); + + return parsed; +} + +function parse(command, args, options) { + // Normalize arguments, similar to nodejs + if (args && !Array.isArray(args)) { + options = args; + args = null; } + + args = args ? args.slice(0) : []; // Clone array to avoid changing the original + options = Object.assign({}, options); // Clone object to avoid changing the original + + // Build our parsed object + const parsed = { + command, + args, + options, + file: undefined, + original: { + command, + args, + }, + }; + + // Delegate further parsing to shell or non-shell + return options.shell ? parsed : parseNonShell(parsed); } -//# sourceMappingURL=toolrunner.js.map + +module.exports = parse; + /***/ }), -/***/ 3446: -/***/ (function(__unused_webpack_module, exports) { +/***/ 8160: +/***/ ((module) => { -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.PersonalAccessTokenCredentialHandler = exports.BearerCredentialHandler = exports.BasicCredentialHandler = void 0; -class BasicCredentialHandler { - constructor(username, password) { - this.username = username; - this.password = password; - } - prepareRequest(options) { - if (!options.headers) { - throw Error('The request has no headers'); - } - options.headers['Authorization'] = `Basic ${Buffer.from(`${this.username}:${this.password}`).toString('base64')}`; - } - // This handler cannot handle 401 - canHandleAuthentication() { - return false; - } - handleAuthentication() { - return __awaiter(this, void 0, void 0, function* () { - throw new Error('not implemented'); - }); - } + +// See http://www.robvanderwoude.com/escapechars.php +const metaCharsRegExp = /([()\][%!^"`<>&|;, *?])/g; + +function escapeCommand(arg) { + // Escape meta chars + arg = arg.replace(metaCharsRegExp, '^$1'); + + return arg; } -exports.BasicCredentialHandler = BasicCredentialHandler; -class BearerCredentialHandler { - constructor(token) { - this.token = token; - } - // currently implements pre-authorization - // TODO: support preAuth = false where it hooks on 401 - prepareRequest(options) { - if (!options.headers) { - throw Error('The request has no headers'); - } - options.headers['Authorization'] = `Bearer ${this.token}`; - } - // This handler cannot handle 401 - canHandleAuthentication() { - return false; - } - handleAuthentication() { - return __awaiter(this, void 0, void 0, function* () { - throw new Error('not implemented'); - }); + +function escapeArgument(arg, doubleEscapeMetaChars) { + // Convert to string + arg = `${arg}`; + + // Algorithm below is based on https://qntm.org/cmd + // It's slightly altered to disable JS backtracking to avoid hanging on specially crafted input + // Please see https://github.com/moxystudio/node-cross-spawn/pull/160 for more information + + // Sequence of backslashes followed by a double quote: + // double up all the backslashes and escape the double quote + arg = arg.replace(/(?=(\\+?)?)\1"/g, '$1$1\\"'); + + // Sequence of backslashes followed by the end of the string + // (which will become a double quote later): + // double up all the backslashes + arg = arg.replace(/(?=(\\+?)?)\1$/, '$1$1'); + + // All other backslashes occur literally + + // Quote the whole thing: + arg = `"${arg}"`; + + // Escape meta chars + arg = arg.replace(metaCharsRegExp, '^$1'); + + // Double escape meta chars if necessary + if (doubleEscapeMetaChars) { + arg = arg.replace(metaCharsRegExp, '^$1'); } + + return arg; } -exports.BearerCredentialHandler = BearerCredentialHandler; -class PersonalAccessTokenCredentialHandler { - constructor(token) { - this.token = token; - } - // currently implements pre-authorization - // TODO: support preAuth = false where it hooks on 401 - prepareRequest(options) { - if (!options.headers) { - throw Error('The request has no headers'); - } - options.headers['Authorization'] = `Basic ${Buffer.from(`PAT:${this.token}`).toString('base64')}`; - } - // This handler cannot handle 401 - canHandleAuthentication() { - return false; - } - handleAuthentication() { - return __awaiter(this, void 0, void 0, function* () { - throw new Error('not implemented'); - }); - } + +module.exports.command = escapeCommand; +module.exports.argument = escapeArgument; + + +/***/ }), + +/***/ 6195: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + + + +const fs = __nccwpck_require__(9896); +const shebangCommand = __nccwpck_require__(6707); + +function readShebang(command) { + // Read the first 150 bytes from the file + const size = 150; + const buffer = Buffer.alloc(size); + + let fd; + + try { + fd = fs.openSync(command, 'r'); + fs.readSync(fd, buffer, 0, size, 0); + fs.closeSync(fd); + } catch (e) { /* Empty */ } + + // Attempt to extract shebang (null is returned if not a shebang) + return shebangCommand(buffer.toString()); } -exports.PersonalAccessTokenCredentialHandler = PersonalAccessTokenCredentialHandler; -//# sourceMappingURL=auth.js.map + +module.exports = readShebang; + /***/ }), -/***/ 7578: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { +/***/ 8062: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -/* eslint-disable @typescript-eslint/no-explicit-any */ -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; - }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; - }; -})(); -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.HttpClient = exports.HttpClientResponse = exports.HttpClientError = exports.MediaTypes = exports.Headers = exports.HttpCodes = void 0; -exports.getProxyUrl = getProxyUrl; -exports.isHttps = isHttps; -const http = __importStar(__nccwpck_require__(8611)); -const https = __importStar(__nccwpck_require__(5692)); -const pm = __importStar(__nccwpck_require__(246)); -const tunnel = __importStar(__nccwpck_require__(2937)); -const undici_1 = __nccwpck_require__(9153); -var HttpCodes; -(function (HttpCodes) { - HttpCodes[HttpCodes["OK"] = 200] = "OK"; - HttpCodes[HttpCodes["MultipleChoices"] = 300] = "MultipleChoices"; - HttpCodes[HttpCodes["MovedPermanently"] = 301] = "MovedPermanently"; - HttpCodes[HttpCodes["ResourceMoved"] = 302] = "ResourceMoved"; - HttpCodes[HttpCodes["SeeOther"] = 303] = "SeeOther"; - HttpCodes[HttpCodes["NotModified"] = 304] = "NotModified"; - HttpCodes[HttpCodes["UseProxy"] = 305] = "UseProxy"; - HttpCodes[HttpCodes["SwitchProxy"] = 306] = "SwitchProxy"; - HttpCodes[HttpCodes["TemporaryRedirect"] = 307] = "TemporaryRedirect"; - HttpCodes[HttpCodes["PermanentRedirect"] = 308] = "PermanentRedirect"; - HttpCodes[HttpCodes["BadRequest"] = 400] = "BadRequest"; - HttpCodes[HttpCodes["Unauthorized"] = 401] = "Unauthorized"; - HttpCodes[HttpCodes["PaymentRequired"] = 402] = "PaymentRequired"; - HttpCodes[HttpCodes["Forbidden"] = 403] = "Forbidden"; - HttpCodes[HttpCodes["NotFound"] = 404] = "NotFound"; - HttpCodes[HttpCodes["MethodNotAllowed"] = 405] = "MethodNotAllowed"; - HttpCodes[HttpCodes["NotAcceptable"] = 406] = "NotAcceptable"; - HttpCodes[HttpCodes["ProxyAuthenticationRequired"] = 407] = "ProxyAuthenticationRequired"; - HttpCodes[HttpCodes["RequestTimeout"] = 408] = "RequestTimeout"; - HttpCodes[HttpCodes["Conflict"] = 409] = "Conflict"; - HttpCodes[HttpCodes["Gone"] = 410] = "Gone"; - HttpCodes[HttpCodes["TooManyRequests"] = 429] = "TooManyRequests"; - HttpCodes[HttpCodes["InternalServerError"] = 500] = "InternalServerError"; - HttpCodes[HttpCodes["NotImplemented"] = 501] = "NotImplemented"; - HttpCodes[HttpCodes["BadGateway"] = 502] = "BadGateway"; - HttpCodes[HttpCodes["ServiceUnavailable"] = 503] = "ServiceUnavailable"; - HttpCodes[HttpCodes["GatewayTimeout"] = 504] = "GatewayTimeout"; -})(HttpCodes || (exports.HttpCodes = HttpCodes = {})); -var Headers; -(function (Headers) { - Headers["Accept"] = "accept"; - Headers["ContentType"] = "content-type"; -})(Headers || (exports.Headers = Headers = {})); -var MediaTypes; -(function (MediaTypes) { - MediaTypes["ApplicationJson"] = "application/json"; -})(MediaTypes || (exports.MediaTypes = MediaTypes = {})); -/** - * Returns the proxy URL, depending upon the supplied url and proxy environment variables. - * @param serverUrl The server URL where the request will be sent. For example, https://api.github.com - */ -function getProxyUrl(serverUrl) { - const proxyUrl = pm.getProxyUrl(new URL(serverUrl)); - return proxyUrl ? proxyUrl.href : ''; -} -const HttpRedirectCodes = [ - HttpCodes.MovedPermanently, - HttpCodes.ResourceMoved, - HttpCodes.SeeOther, - HttpCodes.TemporaryRedirect, - HttpCodes.PermanentRedirect -]; -const HttpResponseRetryCodes = [ - HttpCodes.BadGateway, - HttpCodes.ServiceUnavailable, - HttpCodes.GatewayTimeout -]; -const RetryableHttpVerbs = ['OPTIONS', 'GET', 'DELETE', 'HEAD']; -const ExponentialBackoffCeiling = 10; -const ExponentialBackoffTimeSlice = 5; -class HttpClientError extends Error { - constructor(message, statusCode) { - super(message); - this.name = 'HttpClientError'; - this.statusCode = statusCode; - Object.setPrototypeOf(this, HttpClientError.prototype); - } -} -exports.HttpClientError = HttpClientError; -class HttpClientResponse { - constructor(message) { - this.message = message; - } - readBody() { - return __awaiter(this, void 0, void 0, function* () { - return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () { - let output = Buffer.alloc(0); - this.message.on('data', (chunk) => { - output = Buffer.concat([output, chunk]); - }); - this.message.on('end', () => { - resolve(output.toString()); - }); - })); - }); - } - readBodyBuffer() { - return __awaiter(this, void 0, void 0, function* () { - return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () { - const chunks = []; - this.message.on('data', (chunk) => { - chunks.push(chunk); - }); - this.message.on('end', () => { - resolve(Buffer.concat(chunks)); - }); - })); - }); - } -} -exports.HttpClientResponse = HttpClientResponse; -function isHttps(requestUrl) { - const parsedUrl = new URL(requestUrl); - return parsedUrl.protocol === 'https:'; -} -class HttpClient { - constructor(userAgent, handlers, requestOptions) { - this._ignoreSslError = false; - this._allowRedirects = true; - this._allowRedirectDowngrade = false; - this._maxRedirects = 50; - this._allowRetries = false; - this._maxRetries = 1; - this._keepAlive = false; - this._disposed = false; - this.userAgent = this._getUserAgentWithOrchestrationId(userAgent); - this.handlers = handlers || []; - this.requestOptions = requestOptions; - if (requestOptions) { - if (requestOptions.ignoreSslError != null) { - this._ignoreSslError = requestOptions.ignoreSslError; - } - this._socketTimeout = requestOptions.socketTimeout; - if (requestOptions.allowRedirects != null) { - this._allowRedirects = requestOptions.allowRedirects; - } - if (requestOptions.allowRedirectDowngrade != null) { - this._allowRedirectDowngrade = requestOptions.allowRedirectDowngrade; - } - if (requestOptions.maxRedirects != null) { - this._maxRedirects = Math.max(requestOptions.maxRedirects, 0); - } - if (requestOptions.keepAlive != null) { - this._keepAlive = requestOptions.keepAlive; - } - if (requestOptions.allowRetries != null) { - this._allowRetries = requestOptions.allowRetries; - } - if (requestOptions.maxRetries != null) { - this._maxRetries = requestOptions.maxRetries; - } - } - } - options(requestUrl, additionalHeaders) { - return __awaiter(this, void 0, void 0, function* () { - return this.request('OPTIONS', requestUrl, null, additionalHeaders || {}); - }); - } - get(requestUrl, additionalHeaders) { - return __awaiter(this, void 0, void 0, function* () { - return this.request('GET', requestUrl, null, additionalHeaders || {}); - }); - } - del(requestUrl, additionalHeaders) { - return __awaiter(this, void 0, void 0, function* () { - return this.request('DELETE', requestUrl, null, additionalHeaders || {}); - }); - } - post(requestUrl, data, additionalHeaders) { - return __awaiter(this, void 0, void 0, function* () { - return this.request('POST', requestUrl, data, additionalHeaders || {}); - }); - } - patch(requestUrl, data, additionalHeaders) { - return __awaiter(this, void 0, void 0, function* () { - return this.request('PATCH', requestUrl, data, additionalHeaders || {}); - }); - } - put(requestUrl, data, additionalHeaders) { - return __awaiter(this, void 0, void 0, function* () { - return this.request('PUT', requestUrl, data, additionalHeaders || {}); - }); - } - head(requestUrl, additionalHeaders) { - return __awaiter(this, void 0, void 0, function* () { - return this.request('HEAD', requestUrl, null, additionalHeaders || {}); - }); - } - sendStream(verb, requestUrl, stream, additionalHeaders) { - return __awaiter(this, void 0, void 0, function* () { - return this.request(verb, requestUrl, stream, additionalHeaders); - }); - } - /** - * Gets a typed object from an endpoint - * Be aware that not found returns a null. Other errors (4xx, 5xx) reject the promise - */ - getJson(requestUrl_1) { - return __awaiter(this, arguments, void 0, function* (requestUrl, additionalHeaders = {}) { - additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); - const res = yield this.get(requestUrl, additionalHeaders); - return this._processResponse(res, this.requestOptions); - }); - } - postJson(requestUrl_1, obj_1) { - return __awaiter(this, arguments, void 0, function* (requestUrl, obj, additionalHeaders = {}) { - const data = JSON.stringify(obj, null, 2); - additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); - additionalHeaders[Headers.ContentType] = - this._getExistingOrDefaultContentTypeHeader(additionalHeaders, MediaTypes.ApplicationJson); - const res = yield this.post(requestUrl, data, additionalHeaders); - return this._processResponse(res, this.requestOptions); - }); - } - putJson(requestUrl_1, obj_1) { - return __awaiter(this, arguments, void 0, function* (requestUrl, obj, additionalHeaders = {}) { - const data = JSON.stringify(obj, null, 2); - additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); - additionalHeaders[Headers.ContentType] = - this._getExistingOrDefaultContentTypeHeader(additionalHeaders, MediaTypes.ApplicationJson); - const res = yield this.put(requestUrl, data, additionalHeaders); - return this._processResponse(res, this.requestOptions); - }); - } - patchJson(requestUrl_1, obj_1) { - return __awaiter(this, arguments, void 0, function* (requestUrl, obj, additionalHeaders = {}) { - const data = JSON.stringify(obj, null, 2); - additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); - additionalHeaders[Headers.ContentType] = - this._getExistingOrDefaultContentTypeHeader(additionalHeaders, MediaTypes.ApplicationJson); - const res = yield this.patch(requestUrl, data, additionalHeaders); - return this._processResponse(res, this.requestOptions); - }); - } - /** - * Makes a raw http request. - * All other methods such as get, post, patch, and request ultimately call this. - * Prefer get, del, post and patch - */ - request(verb, requestUrl, data, headers) { - return __awaiter(this, void 0, void 0, function* () { - if (this._disposed) { - throw new Error('Client has already been disposed.'); - } - const parsedUrl = new URL(requestUrl); - let info = this._prepareRequest(verb, parsedUrl, headers); - // Only perform retries on reads since writes may not be idempotent. - const maxTries = this._allowRetries && RetryableHttpVerbs.includes(verb) - ? this._maxRetries + 1 - : 1; - let numTries = 0; - let response; - do { - response = yield this.requestRaw(info, data); - // Check if it's an authentication challenge - if (response && - response.message && - response.message.statusCode === HttpCodes.Unauthorized) { - let authenticationHandler; - for (const handler of this.handlers) { - if (handler.canHandleAuthentication(response)) { - authenticationHandler = handler; - break; - } - } - if (authenticationHandler) { - return authenticationHandler.handleAuthentication(this, info, data); - } - else { - // We have received an unauthorized response but have no handlers to handle it. - // Let the response return to the caller. - return response; - } - } - let redirectsRemaining = this._maxRedirects; - while (response.message.statusCode && - HttpRedirectCodes.includes(response.message.statusCode) && - this._allowRedirects && - redirectsRemaining > 0) { - const redirectUrl = response.message.headers['location']; - if (!redirectUrl) { - // if there's no location to redirect to, we won't - break; - } - const parsedRedirectUrl = new URL(redirectUrl); - if (parsedUrl.protocol === 'https:' && - parsedUrl.protocol !== parsedRedirectUrl.protocol && - !this._allowRedirectDowngrade) { - throw new Error('Redirect from HTTPS to HTTP protocol. This downgrade is not allowed for security reasons. If you want to allow this behavior, set the allowRedirectDowngrade option to true.'); - } - // we need to finish reading the response before reassigning response - // which will leak the open socket. - yield response.readBody(); - // strip authorization header if redirected to a different hostname - if (parsedRedirectUrl.hostname !== parsedUrl.hostname) { - for (const header in headers) { - // header names are case insensitive - if (header.toLowerCase() === 'authorization') { - delete headers[header]; - } - } - } - // let's make the request with the new redirectUrl - info = this._prepareRequest(verb, parsedRedirectUrl, headers); - response = yield this.requestRaw(info, data); - redirectsRemaining--; - } - if (!response.message.statusCode || - !HttpResponseRetryCodes.includes(response.message.statusCode)) { - // If not a retry code, return immediately instead of retrying - return response; - } - numTries += 1; - if (numTries < maxTries) { - yield response.readBody(); - yield this._performExponentialBackoff(numTries); - } - } while (numTries < maxTries); - return response; - }); - } - /** - * Needs to be called if keepAlive is set to true in request options. - */ - dispose() { - if (this._agent) { - this._agent.destroy(); + +const path = __nccwpck_require__(6928); +const which = __nccwpck_require__(9676); +const getPathKey = __nccwpck_require__(449); + +function resolveCommandAttempt(parsed, withoutPathExt) { + const env = parsed.options.env || process.env; + const cwd = process.cwd(); + const hasCustomCwd = parsed.options.cwd != null; + // Worker threads do not have process.chdir() + const shouldSwitchCwd = hasCustomCwd && process.chdir !== undefined && !process.chdir.disabled; + + // If a custom `cwd` was specified, we need to change the process cwd + // because `which` will do stat calls but does not support a custom cwd + if (shouldSwitchCwd) { + try { + process.chdir(parsed.options.cwd); + } catch (err) { + /* Empty */ } - this._disposed = true; - } - /** - * Raw request. - * @param info - * @param data - */ - requestRaw(info, data) { - return __awaiter(this, void 0, void 0, function* () { - return new Promise((resolve, reject) => { - function callbackForResult(err, res) { - if (err) { - reject(err); - } - else if (!res) { - // If `err` is not passed, then `res` must be passed. - reject(new Error('Unknown error')); - } - else { - resolve(res); - } - } - this.requestRawWithCallback(info, data, callbackForResult); - }); - }); } - /** - * Raw request with callback. - * @param info - * @param data - * @param onResult - */ - requestRawWithCallback(info, data, onResult) { - if (typeof data === 'string') { - if (!info.options.headers) { - info.options.headers = {}; - } - info.options.headers['Content-Length'] = Buffer.byteLength(data, 'utf8'); - } - let callbackCalled = false; - function handleResult(err, res) { - if (!callbackCalled) { - callbackCalled = true; - onResult(err, res); - } - } - const req = info.httpModule.request(info.options, (msg) => { - const res = new HttpClientResponse(msg); - handleResult(undefined, res); - }); - let socket; - req.on('socket', sock => { - socket = sock; - }); - // If we ever get disconnected, we want the socket to timeout eventually - req.setTimeout(this._socketTimeout || 3 * 60000, () => { - if (socket) { - socket.end(); - } - handleResult(new Error(`Request timeout: ${info.options.path}`)); - }); - req.on('error', function (err) { - // err has statusCode property - // res should have headers - handleResult(err); + + let resolved; + + try { + resolved = which.sync(parsed.command, { + path: env[getPathKey({ env })], + pathExt: withoutPathExt ? path.delimiter : undefined, }); - if (data && typeof data === 'string') { - req.write(data, 'utf8'); - } - if (data && typeof data !== 'string') { - data.on('close', function () { - req.end(); - }); - data.pipe(req); - } - else { - req.end(); - } - } - /** - * Gets an http agent. This function is useful when you need an http agent that handles - * routing through a proxy server - depending upon the url and proxy environment variables. - * @param serverUrl The server URL where the request will be sent. For example, https://api.github.com - */ - getAgent(serverUrl) { - const parsedUrl = new URL(serverUrl); - return this._getAgent(parsedUrl); - } - getAgentDispatcher(serverUrl) { - const parsedUrl = new URL(serverUrl); - const proxyUrl = pm.getProxyUrl(parsedUrl); - const useProxy = proxyUrl && proxyUrl.hostname; - if (!useProxy) { - return; - } - return this._getProxyAgentDispatcher(parsedUrl, proxyUrl); - } - _prepareRequest(method, requestUrl, headers) { - const info = {}; - info.parsedUrl = requestUrl; - const usingSsl = info.parsedUrl.protocol === 'https:'; - info.httpModule = usingSsl ? https : http; - const defaultPort = usingSsl ? 443 : 80; - info.options = {}; - info.options.host = info.parsedUrl.hostname; - info.options.port = info.parsedUrl.port - ? parseInt(info.parsedUrl.port) - : defaultPort; - info.options.path = - (info.parsedUrl.pathname || '') + (info.parsedUrl.search || ''); - info.options.method = method; - info.options.headers = this._mergeHeaders(headers); - if (this.userAgent != null) { - info.options.headers['user-agent'] = this.userAgent; - } - info.options.agent = this._getAgent(info.parsedUrl); - // gives handlers an opportunity to participate - if (this.handlers) { - for (const handler of this.handlers) { - handler.prepareRequest(info.options); - } - } - return info; - } - _mergeHeaders(headers) { - if (this.requestOptions && this.requestOptions.headers) { - return Object.assign({}, lowercaseKeys(this.requestOptions.headers), lowercaseKeys(headers || {})); + } catch (e) { + /* Empty */ + } finally { + if (shouldSwitchCwd) { + process.chdir(cwd); } - return lowercaseKeys(headers || {}); } - /** - * Gets an existing header value or returns a default. - * Handles converting number header values to strings since HTTP headers must be strings. - * Note: This returns string | string[] since some headers can have multiple values. - * For headers that must always be a single string (like Content-Type), use the - * specialized _getExistingOrDefaultContentTypeHeader method instead. - */ - _getExistingOrDefaultHeader(additionalHeaders, header, _default) { - let clientHeader; - if (this.requestOptions && this.requestOptions.headers) { - const headerValue = lowercaseKeys(this.requestOptions.headers)[header]; - if (headerValue) { - clientHeader = - typeof headerValue === 'number' ? headerValue.toString() : headerValue; - } - } - const additionalValue = additionalHeaders[header]; - if (additionalValue !== undefined) { - return typeof additionalValue === 'number' - ? additionalValue.toString() - : additionalValue; - } - if (clientHeader !== undefined) { - return clientHeader; - } - return _default; - } - /** - * Specialized version of _getExistingOrDefaultHeader for Content-Type header. - * Always returns a single string (not an array) since Content-Type should be a single value. - * Converts arrays to comma-separated strings and numbers to strings to ensure type safety. - * This was split from _getExistingOrDefaultHeader to provide stricter typing for callers - * that assign the result to places expecting a string (e.g., additionalHeaders[Headers.ContentType]). - */ - _getExistingOrDefaultContentTypeHeader(additionalHeaders, _default) { - let clientHeader; - if (this.requestOptions && this.requestOptions.headers) { - const headerValue = lowercaseKeys(this.requestOptions.headers)[Headers.ContentType]; - if (headerValue) { - if (typeof headerValue === 'number') { - clientHeader = String(headerValue); - } - else if (Array.isArray(headerValue)) { - clientHeader = headerValue.join(', '); - } - else { - clientHeader = headerValue; - } - } - } - const additionalValue = additionalHeaders[Headers.ContentType]; - // Return the first non-undefined value, converting numbers or arrays to strings if necessary - if (additionalValue !== undefined) { - if (typeof additionalValue === 'number') { - return String(additionalValue); - } - else if (Array.isArray(additionalValue)) { - return additionalValue.join(', '); - } - else { - return additionalValue; - } - } - if (clientHeader !== undefined) { - return clientHeader; - } - return _default; - } - _getAgent(parsedUrl) { - let agent; - const proxyUrl = pm.getProxyUrl(parsedUrl); - const useProxy = proxyUrl && proxyUrl.hostname; - if (this._keepAlive && useProxy) { - agent = this._proxyAgent; - } - if (!useProxy) { - agent = this._agent; - } - // if agent is already assigned use that agent. - if (agent) { - return agent; - } - const usingSsl = parsedUrl.protocol === 'https:'; - let maxSockets = 100; - if (this.requestOptions) { - maxSockets = this.requestOptions.maxSockets || http.globalAgent.maxSockets; - } - // This is `useProxy` again, but we need to check `proxyURl` directly for TypeScripts's flow analysis. - if (proxyUrl && proxyUrl.hostname) { - const agentOptions = { - maxSockets, - keepAlive: this._keepAlive, - proxy: Object.assign(Object.assign({}, ((proxyUrl.username || proxyUrl.password) && { - proxyAuth: `${proxyUrl.username}:${proxyUrl.password}` - })), { host: proxyUrl.hostname, port: proxyUrl.port }) - }; - let tunnelAgent; - const overHttps = proxyUrl.protocol === 'https:'; - if (usingSsl) { - tunnelAgent = overHttps ? tunnel.httpsOverHttps : tunnel.httpsOverHttp; - } - else { - tunnelAgent = overHttps ? tunnel.httpOverHttps : tunnel.httpOverHttp; - } - agent = tunnelAgent(agentOptions); - this._proxyAgent = agent; - } - // if tunneling agent isn't assigned create a new agent - if (!agent) { - const options = { keepAlive: this._keepAlive, maxSockets }; - agent = usingSsl ? new https.Agent(options) : new http.Agent(options); - this._agent = agent; - } - if (usingSsl && this._ignoreSslError) { - // we don't want to set NODE_TLS_REJECT_UNAUTHORIZED=0 since that will affect request for entire process - // http.RequestOptions doesn't expose a way to modify RequestOptions.agent.options - // we have to cast it to any and change it directly - agent.options = Object.assign(agent.options || {}, { - rejectUnauthorized: false - }); - } - return agent; - } - _getProxyAgentDispatcher(parsedUrl, proxyUrl) { - let proxyAgent; - if (this._keepAlive) { - proxyAgent = this._proxyAgentDispatcher; - } - // if agent is already assigned use that agent. - if (proxyAgent) { - return proxyAgent; - } - const usingSsl = parsedUrl.protocol === 'https:'; - proxyAgent = new undici_1.ProxyAgent(Object.assign({ uri: proxyUrl.href, pipelining: !this._keepAlive ? 0 : 1 }, ((proxyUrl.username || proxyUrl.password) && { - token: `Basic ${Buffer.from(`${proxyUrl.username}:${proxyUrl.password}`).toString('base64')}` - }))); - this._proxyAgentDispatcher = proxyAgent; - if (usingSsl && this._ignoreSslError) { - // we don't want to set NODE_TLS_REJECT_UNAUTHORIZED=0 since that will affect request for entire process - // http.RequestOptions doesn't expose a way to modify RequestOptions.agent.options - // we have to cast it to any and change it directly - proxyAgent.options = Object.assign(proxyAgent.options.requestTls || {}, { - rejectUnauthorized: false - }); - } - return proxyAgent; - } - _getUserAgentWithOrchestrationId(userAgent) { - const baseUserAgent = userAgent || 'actions/http-client'; - const orchId = process.env['ACTIONS_ORCHESTRATION_ID']; - if (orchId) { - // Sanitize the orchestration ID to ensure it contains only valid characters - // Valid characters: 0-9, a-z, _, -, . - const sanitizedId = orchId.replace(/[^a-z0-9_.-]/gi, '_'); - return `${baseUserAgent} actions_orchestration_id/${sanitizedId}`; - } - return baseUserAgent; - } - _performExponentialBackoff(retryNumber) { - return __awaiter(this, void 0, void 0, function* () { - retryNumber = Math.min(ExponentialBackoffCeiling, retryNumber); - const ms = ExponentialBackoffTimeSlice * Math.pow(2, retryNumber); - return new Promise(resolve => setTimeout(() => resolve(), ms)); - }); - } - _processResponse(res, options) { - return __awaiter(this, void 0, void 0, function* () { - return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () { - const statusCode = res.message.statusCode || 0; - const response = { - statusCode, - result: null, - headers: {} - }; - // not found leads to null obj returned - if (statusCode === HttpCodes.NotFound) { - resolve(response); - } - // get the result from the body - function dateTimeDeserializer(key, value) { - if (typeof value === 'string') { - const a = new Date(value); - if (!isNaN(a.valueOf())) { - return a; - } - } - return value; - } - let obj; - let contents; - try { - contents = yield res.readBody(); - if (contents && contents.length > 0) { - if (options && options.deserializeDates) { - obj = JSON.parse(contents, dateTimeDeserializer); - } - else { - obj = JSON.parse(contents); - } - response.result = obj; - } - response.headers = res.message.headers; - } - catch (err) { - // Invalid resource (contents not json); leaving result obj null - } - // note that 3xx redirects are handled by the http layer. - if (statusCode > 299) { - let msg; - // if exception/error in body, attempt to get better error - if (obj && obj.message) { - msg = obj.message; - } - else if (contents && contents.length > 0) { - // it may be the case that the exception is in the body message as string - msg = contents; - } - else { - msg = `Failed request: (${statusCode})`; - } - const err = new HttpClientError(msg, statusCode); - err.result = response.result; - reject(err); - } - else { - resolve(response); - } - })); - }); + + // If we successfully resolved, ensure that an absolute path is returned + // Note that when a custom `cwd` was used, we need to resolve to an absolute path based on it + if (resolved) { + resolved = path.resolve(hasCustomCwd ? parsed.options.cwd : '', resolved); } + + return resolved; } -exports.HttpClient = HttpClient; -const lowercaseKeys = (obj) => Object.keys(obj).reduce((c, k) => ((c[k.toLowerCase()] = obj[k]), c), {}); -//# sourceMappingURL=index.js.map + +function resolveCommand(parsed) { + return resolveCommandAttempt(parsed) || resolveCommandAttempt(parsed, true); +} + +module.exports = resolveCommand; + /***/ }), -/***/ 246: -/***/ ((__unused_webpack_module, exports) => { +/***/ 2706: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.getProxyUrl = getProxyUrl; -exports.checkBypass = checkBypass; -function getProxyUrl(reqUrl) { - const usingSsl = reqUrl.protocol === 'https:'; - if (checkBypass(reqUrl)) { - return undefined; - } - const proxyVar = (() => { - if (usingSsl) { - return process.env['https_proxy'] || process.env['HTTPS_PROXY']; - } - else { - return process.env['http_proxy'] || process.env['HTTP_PROXY']; - } - })(); - if (proxyVar) { - try { - return new DecodedURL(proxyVar); - } - catch (_a) { - if (!proxyVar.startsWith('http://') && !proxyVar.startsWith('https://')) - return new DecodedURL(`http://${proxyVar}`); - } - } - else { - return undefined; - } -} -function checkBypass(reqUrl) { - if (!reqUrl.hostname) { - return false; - } - const reqHost = reqUrl.hostname; - if (isLoopbackAddress(reqHost)) { - return true; - } - const noProxy = process.env['no_proxy'] || process.env['NO_PROXY'] || ''; - if (!noProxy) { - return false; - } - // Determine the request port - let reqPort; - if (reqUrl.port) { - reqPort = Number(reqUrl.port); - } - else if (reqUrl.protocol === 'http:') { - reqPort = 80; - } - else if (reqUrl.protocol === 'https:') { - reqPort = 443; - } - // Format the request hostname and hostname with port - const upperReqHosts = [reqUrl.hostname.toUpperCase()]; - if (typeof reqPort === 'number') { - upperReqHosts.push(`${upperReqHosts[0]}:${reqPort}`); - } - // Compare request host against noproxy - for (const upperNoProxyItem of noProxy - .split(',') - .map(x => x.trim().toUpperCase()) - .filter(x => x)) { - if (upperNoProxyItem === '*' || - upperReqHosts.some(x => x === upperNoProxyItem || - x.endsWith(`.${upperNoProxyItem}`) || - (upperNoProxyItem.startsWith('.') && - x.endsWith(`${upperNoProxyItem}`)))) { - return true; - } - } - return false; -} -function isLoopbackAddress(host) { - const hostLower = host.toLowerCase(); - return (hostLower === 'localhost' || - hostLower.startsWith('127.') || - hostLower.startsWith('[::1]') || - hostLower.startsWith('[0:0:0:0:0:0:0:1]')); -} -class DecodedURL extends URL { - constructor(url, base) { - super(url, base); - this._decodedUsername = decodeURIComponent(super.username); - this._decodedPassword = decodeURIComponent(super.password); - } - get username() { - return this._decodedUsername; - } - get password() { - return this._decodedPassword; - } -} -//# sourceMappingURL=proxy.js.map +const path = __nccwpck_require__(6928); +const childProcess = __nccwpck_require__(5317); +const crossSpawn = __nccwpck_require__(7494); +const stripFinalNewline = __nccwpck_require__(9005); +const npmRunPath = __nccwpck_require__(9584); +const onetime = __nccwpck_require__(5816); +const makeError = __nccwpck_require__(5588); +const normalizeStdio = __nccwpck_require__(2751); +const {spawnedKill, spawnedCancel, setupTimeout, validateTimeout, setExitHandler} = __nccwpck_require__(1212); +const {handleInput, getSpawnedResult, makeAllStream, validateInputSync} = __nccwpck_require__(1620); +const {mergePromise, getSpawnedPromise} = __nccwpck_require__(2403); +const {joinCommand, parseCommand, getEscapedCommand} = __nccwpck_require__(5011); -/***/ }), +const DEFAULT_MAX_BUFFER = 1000 * 1000 * 100; -/***/ 6760: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { +const getEnv = ({env: envOption, extendEnv, preferLocal, localDir, execPath}) => { + const env = extendEnv ? {...process.env, ...envOption} : envOption; -"use strict"; + if (preferLocal) { + return npmRunPath.env({env, cwd: localDir, execPath}); + } -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; - }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; - }; -})(); -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); + return env; }; -var _a; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.READONLY = exports.UV_FS_O_EXLOCK = exports.IS_WINDOWS = exports.unlink = exports.symlink = exports.stat = exports.rmdir = exports.rm = exports.rename = exports.readdir = exports.open = exports.mkdir = exports.lstat = exports.copyFile = exports.chmod = void 0; -exports.readlink = readlink; -exports.exists = exists; -exports.isDirectory = isDirectory; -exports.isRooted = isRooted; -exports.tryGetExecutablePath = tryGetExecutablePath; -exports.getCmdPath = getCmdPath; -const fs = __importStar(__nccwpck_require__(9896)); -const path = __importStar(__nccwpck_require__(6928)); -_a = fs.promises -// export const {open} = 'fs' -, exports.chmod = _a.chmod, exports.copyFile = _a.copyFile, exports.lstat = _a.lstat, exports.mkdir = _a.mkdir, exports.open = _a.open, exports.readdir = _a.readdir, exports.rename = _a.rename, exports.rm = _a.rm, exports.rmdir = _a.rmdir, exports.stat = _a.stat, exports.symlink = _a.symlink, exports.unlink = _a.unlink; -// export const {open} = 'fs' -exports.IS_WINDOWS = process.platform === 'win32'; -/** - * Custom implementation of readlink to ensure Windows junctions - * maintain trailing backslash for backward compatibility with Node.js < 24 - * - * In Node.js 20, Windows junctions (directory symlinks) always returned paths - * with trailing backslashes. Node.js 24 removed this behavior, which breaks - * code that relied on this format for path operations. - * - * This implementation restores the Node 20 behavior by adding a trailing - * backslash to all junction results on Windows. - */ -function readlink(fsPath) { - return __awaiter(this, void 0, void 0, function* () { - const result = yield fs.promises.readlink(fsPath); - // On Windows, restore Node 20 behavior: add trailing backslash to all results - // since junctions on Windows are always directory links - if (exports.IS_WINDOWS && !result.endsWith('\\')) { - return `${result}\\`; - } - return result; - }); -} -// See https://github.com/nodejs/node/blob/d0153aee367422d0858105abec186da4dff0a0c5/deps/uv/include/uv/win.h#L691 -exports.UV_FS_O_EXLOCK = 0x10000000; -exports.READONLY = fs.constants.O_RDONLY; -function exists(fsPath) { - return __awaiter(this, void 0, void 0, function* () { - try { - yield (0, exports.stat)(fsPath); - } - catch (err) { - if (err.code === 'ENOENT') { - return false; - } - throw err; - } - return true; - }); -} -function isDirectory(fsPath_1) { - return __awaiter(this, arguments, void 0, function* (fsPath, useStat = false) { - const stats = useStat ? yield (0, exports.stat)(fsPath) : yield (0, exports.lstat)(fsPath); - return stats.isDirectory(); - }); -} -/** - * On OSX/Linux, true if path starts with '/'. On Windows, true for paths like: - * \, \hello, \\hello\share, C:, and C:\hello (and corresponding alternate separator cases). - */ -function isRooted(p) { - p = normalizeSeparators(p); - if (!p) { - throw new Error('isRooted() parameter "p" cannot be empty'); - } - if (exports.IS_WINDOWS) { - return (p.startsWith('\\') || /^[A-Z]:/i.test(p) // e.g. \ or \hello or \\hello - ); // e.g. C: or C:\hello - } - return p.startsWith('/'); -} -/** - * Best effort attempt to determine whether a file exists and is executable. - * @param filePath file path to check - * @param extensions additional file extensions to try - * @return if file exists and is executable, returns the file path. otherwise empty string. - */ -function tryGetExecutablePath(filePath, extensions) { - return __awaiter(this, void 0, void 0, function* () { - let stats = undefined; - try { - // test file exists - stats = yield (0, exports.stat)(filePath); - } - catch (err) { - if (err.code !== 'ENOENT') { - // eslint-disable-next-line no-console - console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`); - } - } - if (stats && stats.isFile()) { - if (exports.IS_WINDOWS) { - // on Windows, test for valid extension - const upperExt = path.extname(filePath).toUpperCase(); - if (extensions.some(validExt => validExt.toUpperCase() === upperExt)) { - return filePath; - } - } - else { - if (isUnixExecutable(stats)) { - return filePath; - } - } - } - // try each extension - const originalFilePath = filePath; - for (const extension of extensions) { - filePath = originalFilePath + extension; - stats = undefined; - try { - stats = yield (0, exports.stat)(filePath); - } - catch (err) { - if (err.code !== 'ENOENT') { - // eslint-disable-next-line no-console - console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`); - } - } - if (stats && stats.isFile()) { - if (exports.IS_WINDOWS) { - // preserve the case of the actual file (since an extension was appended) - try { - const directory = path.dirname(filePath); - const upperName = path.basename(filePath).toUpperCase(); - for (const actualName of yield (0, exports.readdir)(directory)) { - if (upperName === actualName.toUpperCase()) { - filePath = path.join(directory, actualName); - break; - } - } - } - catch (err) { - // eslint-disable-next-line no-console - console.log(`Unexpected error attempting to determine the actual case of the file '${filePath}': ${err}`); - } - return filePath; - } - else { - if (isUnixExecutable(stats)) { - return filePath; - } - } - } - } - return ''; - }); -} -function normalizeSeparators(p) { - p = p || ''; - if (exports.IS_WINDOWS) { - // convert slashes on Windows - p = p.replace(/\//g, '\\'); - // remove redundant slashes - return p.replace(/\\\\+/g, '\\'); - } - // remove redundant slashes - return p.replace(/\/\/+/g, '/'); -} -// on Mac/Linux, test the execute bit -// R W X R W X R W X -// 256 128 64 32 16 8 4 2 1 -function isUnixExecutable(stats) { - return ((stats.mode & 1) > 0 || - ((stats.mode & 8) > 0 && - process.getgid !== undefined && - stats.gid === process.getgid()) || - ((stats.mode & 64) > 0 && - process.getuid !== undefined && - stats.uid === process.getuid())); -} -// Get the path of cmd.exe in windows -function getCmdPath() { - var _a; - return (_a = process.env['COMSPEC']) !== null && _a !== void 0 ? _a : `cmd.exe`; -} -//# sourceMappingURL=io-util.js.map -/***/ }), +const handleArguments = (file, args, options = {}) => { + const parsed = crossSpawn._parse(file, args, options); + file = parsed.command; + args = parsed.args; + options = parsed.options; + + options = { + maxBuffer: DEFAULT_MAX_BUFFER, + buffer: true, + stripFinalNewline: true, + extendEnv: true, + preferLocal: false, + localDir: options.cwd || process.cwd(), + execPath: process.execPath, + encoding: 'utf8', + reject: true, + cleanup: true, + all: false, + windowsHide: true, + ...options + }; -/***/ 6359: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + options.env = getEnv(options); -"use strict"; + options.stdio = normalizeStdio(options); -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; - }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; - }; -})(); -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); + if (process.platform === 'win32' && path.basename(file, '.exe') === 'cmd') { + // #116 + args.unshift('/q'); + } + + return {file, args, options, parsed}; }; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.cp = cp; -exports.mv = mv; -exports.rmRF = rmRF; -exports.mkdirP = mkdirP; -exports.which = which; -exports.findInPath = findInPath; -const assert_1 = __nccwpck_require__(2613); -const path = __importStar(__nccwpck_require__(6928)); -const ioUtil = __importStar(__nccwpck_require__(6760)); -/** - * Copies a file or folder. - * Based off of shelljs - https://github.com/shelljs/shelljs/blob/9237f66c52e5daa40458f94f9565e18e8132f5a6/src/cp.js - * - * @param source source path - * @param dest destination path - * @param options optional. See CopyOptions. - */ -function cp(source_1, dest_1) { - return __awaiter(this, arguments, void 0, function* (source, dest, options = {}) { - const { force, recursive, copySourceDirectory } = readCopyOptions(options); - const destStat = (yield ioUtil.exists(dest)) ? yield ioUtil.stat(dest) : null; - // Dest is an existing file, but not forcing - if (destStat && destStat.isFile() && !force) { - return; - } - // If dest is an existing directory, should copy inside. - const newDest = destStat && destStat.isDirectory() && copySourceDirectory - ? path.join(dest, path.basename(source)) - : dest; - if (!(yield ioUtil.exists(source))) { - throw new Error(`no such file or directory: ${source}`); - } - const sourceStat = yield ioUtil.stat(source); - if (sourceStat.isDirectory()) { - if (!recursive) { - throw new Error(`Failed to copy. ${source} is a directory, but tried to copy without recursive flag.`); - } - else { - yield cpDirRecursive(source, newDest, 0, force); - } - } - else { - if (path.relative(source, newDest) === '') { - // a file cannot be copied to itself - throw new Error(`'${newDest}' and '${source}' are the same file`); - } - yield copyFile(source, newDest, force); - } - }); -} -/** - * Moves a path. - * - * @param source source path - * @param dest destination path - * @param options optional. See MoveOptions. - */ -function mv(source_1, dest_1) { - return __awaiter(this, arguments, void 0, function* (source, dest, options = {}) { - if (yield ioUtil.exists(dest)) { - let destExists = true; - if (yield ioUtil.isDirectory(dest)) { - // If dest is directory copy src into dest - dest = path.join(dest, path.basename(source)); - destExists = yield ioUtil.exists(dest); - } - if (destExists) { - if (options.force == null || options.force) { - yield rmRF(dest); - } - else { - throw new Error('Destination already exists'); - } - } - } - yield mkdirP(path.dirname(dest)); - yield ioUtil.rename(source, dest); - }); -} -/** - * Remove a path recursively with force - * - * @param inputPath path to remove - */ -function rmRF(inputPath) { - return __awaiter(this, void 0, void 0, function* () { - if (ioUtil.IS_WINDOWS) { - // Check for invalid characters - // https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file - if (/[*"<>|]/.test(inputPath)) { - throw new Error('File path must not contain `*`, `"`, `<`, `>` or `|` on Windows'); - } - } - try { - // note if path does not exist, error is silent - yield ioUtil.rm(inputPath, { - force: true, - maxRetries: 3, - recursive: true, - retryDelay: 300 - }); - } - catch (err) { - throw new Error(`File was unable to be removed ${err}`); - } - }); -} -/** - * Make a directory. Creates the full path with folders in between - * Will throw if it fails - * - * @param fsPath path to create - * @returns Promise - */ -function mkdirP(fsPath) { - return __awaiter(this, void 0, void 0, function* () { - (0, assert_1.ok)(fsPath, 'a path argument must be provided'); - yield ioUtil.mkdir(fsPath, { recursive: true }); - }); -} -/** - * Returns path of a tool had the tool actually been invoked. Resolves via paths. - * If you check and the tool does not exist, it will throw. - * - * @param tool name of the tool - * @param check whether to check if tool exists - * @returns Promise path to tool - */ -function which(tool, check) { - return __awaiter(this, void 0, void 0, function* () { - if (!tool) { - throw new Error("parameter 'tool' is required"); - } - // recursive when check=true - if (check) { - const result = yield which(tool, false); - if (!result) { - if (ioUtil.IS_WINDOWS) { - throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also verify the file has a valid extension for an executable file.`); - } - else { - throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also check the file mode to verify the file is executable.`); - } - } - return result; - } - const matches = yield findInPath(tool); - if (matches && matches.length > 0) { - return matches[0]; - } - return ''; - }); -} -/** - * Returns a list of all occurrences of the given tool on the system path. - * - * @returns Promise the paths of the tool - */ -function findInPath(tool) { - return __awaiter(this, void 0, void 0, function* () { - if (!tool) { - throw new Error("parameter 'tool' is required"); - } - // build the list of extensions to try - const extensions = []; - if (ioUtil.IS_WINDOWS && process.env['PATHEXT']) { - for (const extension of process.env['PATHEXT'].split(path.delimiter)) { - if (extension) { - extensions.push(extension); - } - } - } - // if it's rooted, return it if exists. otherwise return empty. - if (ioUtil.isRooted(tool)) { - const filePath = yield ioUtil.tryGetExecutablePath(tool, extensions); - if (filePath) { - return [filePath]; - } - return []; - } - // if any path separators, return empty - if (tool.includes(path.sep)) { - return []; - } - // build the list of directories - // - // Note, technically "where" checks the current directory on Windows. From a toolkit perspective, - // it feels like we should not do this. Checking the current directory seems like more of a use - // case of a shell, and the which() function exposed by the toolkit should strive for consistency - // across platforms. - const directories = []; - if (process.env.PATH) { - for (const p of process.env.PATH.split(path.delimiter)) { - if (p) { - directories.push(p); - } - } - } - // find all matches - const matches = []; - for (const directory of directories) { - const filePath = yield ioUtil.tryGetExecutablePath(path.join(directory, tool), extensions); - if (filePath) { - matches.push(filePath); - } - } - return matches; - }); -} -function readCopyOptions(options) { - const force = options.force == null ? true : options.force; - const recursive = Boolean(options.recursive); - const copySourceDirectory = options.copySourceDirectory == null - ? true - : Boolean(options.copySourceDirectory); - return { force, recursive, copySourceDirectory }; -} -function cpDirRecursive(sourceDir, destDir, currentDepth, force) { - return __awaiter(this, void 0, void 0, function* () { - // Ensure there is not a run away recursive copy - if (currentDepth >= 255) - return; - currentDepth++; - yield mkdirP(destDir); - const files = yield ioUtil.readdir(sourceDir); - for (const fileName of files) { - const srcFile = `${sourceDir}/${fileName}`; - const destFile = `${destDir}/${fileName}`; - const srcFileStat = yield ioUtil.lstat(srcFile); - if (srcFileStat.isDirectory()) { - // Recurse - yield cpDirRecursive(srcFile, destFile, currentDepth, force); - } - else { - yield copyFile(srcFile, destFile, force); - } - } - // Change the mode for the newly created directory - yield ioUtil.chmod(destDir, (yield ioUtil.stat(sourceDir)).mode); - }); -} -// Buffered file copy -function copyFile(srcFile, destFile, force) { - return __awaiter(this, void 0, void 0, function* () { - if ((yield ioUtil.lstat(srcFile)).isSymbolicLink()) { - // unlink/re-link it - try { - yield ioUtil.lstat(destFile); - yield ioUtil.unlink(destFile); - } - catch (e) { - // Try to override file permission - if (e.code === 'EPERM') { - yield ioUtil.chmod(destFile, '0666'); - yield ioUtil.unlink(destFile); - } - // other errors = it doesn't exist, no work to do - } - // Copy over symlink - const symlinkFull = yield ioUtil.readlink(srcFile); - yield ioUtil.symlink(symlinkFull, destFile, ioUtil.IS_WINDOWS ? 'junction' : null); - } - else if (!(yield ioUtil.exists(destFile)) || force) { - yield ioUtil.copyFile(srcFile, destFile); - } - }); -} -//# sourceMappingURL=io.js.map - -/***/ }), -/***/ 5044: -/***/ (function(module, exports, __nccwpck_require__) { +const handleOutput = (options, value, error) => { + if (typeof value !== 'string' && !Buffer.isBuffer(value)) { + // When `execa.sync()` errors, we normalize it to '' to mimic `execa()` + return error === undefined ? undefined : ''; + } -"use strict"; + if (options.stripFinalNewline) { + return stripFinalNewline(value); + } -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; - }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; - }; -})(); -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); + return value; }; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports._findMatch = _findMatch; -exports._getOsVersion = _getOsVersion; -exports._readLinuxVersionFile = _readLinuxVersionFile; -const semver = __importStar(__nccwpck_require__(3764)); -const core_1 = __nccwpck_require__(9239); -// needs to be require for core node modules to be mocked -/* eslint @typescript-eslint/no-require-imports: 0 */ -const os = __nccwpck_require__(857); -const cp = __nccwpck_require__(5317); -const fs = __nccwpck_require__(9896); -function _findMatch(versionSpec, stable, candidates, archFilter) { - return __awaiter(this, void 0, void 0, function* () { - const platFilter = os.platform(); - let result; - let match; - let file; - for (const candidate of candidates) { - const version = candidate.version; - (0, core_1.debug)(`check ${version} satisfies ${versionSpec}`); - if (semver.satisfies(version, versionSpec) && - (!stable || candidate.stable === stable)) { - file = candidate.files.find(item => { - (0, core_1.debug)(`${item.arch}===${archFilter} && ${item.platform}===${platFilter}`); - let chk = item.arch === archFilter && item.platform === platFilter; - if (chk && item.platform_version) { - const osVersion = module.exports._getOsVersion(); - if (osVersion === item.platform_version) { - chk = true; - } - else { - chk = semver.satisfies(osVersion, item.platform_version); - } - } - return chk; - }); - if (file) { - (0, core_1.debug)(`matched ${candidate.version}`); - match = candidate; - break; - } - } - } - if (match && file) { - // clone since we're mutating the file list to be only the file that matches - result = Object.assign({}, match); - result.files = [file]; - } - return result; - }); -} -function _getOsVersion() { - // TODO: add windows and other linux, arm variants - // right now filtering on version is only an ubuntu and macos scenario for tools we build for hosted (python) - const plat = os.platform(); - let version = ''; - if (plat === 'darwin') { - version = cp.execSync('sw_vers -productVersion').toString(); - } - else if (plat === 'linux') { - // lsb_release process not in some containers, readfile - // Run cat /etc/lsb-release - // DISTRIB_ID=Ubuntu - // DISTRIB_RELEASE=18.04 - // DISTRIB_CODENAME=bionic - // DISTRIB_DESCRIPTION="Ubuntu 18.04.4 LTS" - const lsbContents = module.exports._readLinuxVersionFile(); - if (lsbContents) { - const lines = lsbContents.split('\n'); - for (const line of lines) { - const parts = line.split('='); - if (parts.length === 2 && - (parts[0].trim() === 'VERSION_ID' || - parts[0].trim() === 'DISTRIB_RELEASE')) { - version = parts[1].trim().replace(/^"/, '').replace(/"$/, ''); - break; - } - } - } - } - return version; -} -function _readLinuxVersionFile() { - const lsbReleaseFile = '/etc/lsb-release'; - const osReleaseFile = '/etc/os-release'; - let contents = ''; - if (fs.existsSync(lsbReleaseFile)) { - contents = fs.readFileSync(lsbReleaseFile).toString(); - } - else if (fs.existsSync(osReleaseFile)) { - contents = fs.readFileSync(osReleaseFile).toString(); - } - return contents; -} -//# sourceMappingURL=manifest.js.map -/***/ }), +const execa = (file, args, options) => { + const parsed = handleArguments(file, args, options); + const command = joinCommand(file, args); + const escapedCommand = getEscapedCommand(file, args); -/***/ 1828: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + validateTimeout(parsed.options); -"use strict"; + let spawned; + try { + spawned = childProcess.spawn(parsed.file, parsed.args, parsed.options); + } catch (error) { + // Ensure the returned error is always both a promise and a child process + const dummySpawned = new childProcess.ChildProcess(); + const errorPromise = Promise.reject(makeError({ + error, + stdout: '', + stderr: '', + all: '', + command, + escapedCommand, + parsed, + timedOut: false, + isCanceled: false, + killed: false + })); + return mergePromise(dummySpawned, errorPromise); + } -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; - }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; - }; -})(); -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.RetryHelper = void 0; -const core = __importStar(__nccwpck_require__(9239)); -/** - * Internal class for retries - */ -class RetryHelper { - constructor(maxAttempts, minSeconds, maxSeconds) { - if (maxAttempts < 1) { - throw new Error('max attempts should be greater than or equal to 1'); - } - this.maxAttempts = maxAttempts; - this.minSeconds = Math.floor(minSeconds); - this.maxSeconds = Math.floor(maxSeconds); - if (this.minSeconds > this.maxSeconds) { - throw new Error('min seconds should be less than or equal to max seconds'); - } - } - execute(action, isRetryable) { - return __awaiter(this, void 0, void 0, function* () { - let attempt = 1; - while (attempt < this.maxAttempts) { - // Try - try { - return yield action(); - } - catch (err) { - if (isRetryable && !isRetryable(err)) { - throw err; - } - core.info(err.message); - } - // Sleep - const seconds = this.getSleepAmount(); - core.info(`Waiting ${seconds} seconds before trying again`); - yield this.sleep(seconds); - attempt++; - } - // Last attempt - return yield action(); - }); - } - getSleepAmount() { - return (Math.floor(Math.random() * (this.maxSeconds - this.minSeconds + 1)) + - this.minSeconds); - } - sleep(seconds) { - return __awaiter(this, void 0, void 0, function* () { - return new Promise(resolve => setTimeout(resolve, seconds * 1000)); - }); - } -} -exports.RetryHelper = RetryHelper; -//# sourceMappingURL=retry-helper.js.map + const spawnedPromise = getSpawnedPromise(spawned); + const timedPromise = setupTimeout(spawned, parsed.options, spawnedPromise); + const processDone = setExitHandler(spawned, parsed.options, timedPromise); -/***/ }), + const context = {isCanceled: false}; + + spawned.kill = spawnedKill.bind(null, spawned.kill.bind(spawned)); + spawned.cancel = spawnedCancel.bind(null, spawned, context); -/***/ 0: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + const handlePromise = async () => { + const [{error, exitCode, signal, timedOut}, stdoutResult, stderrResult, allResult] = await getSpawnedResult(spawned, parsed.options, processDone); + const stdout = handleOutput(parsed.options, stdoutResult); + const stderr = handleOutput(parsed.options, stderrResult); + const all = handleOutput(parsed.options, allResult); -"use strict"; + if (error || exitCode !== 0 || signal !== null) { + const returnedError = makeError({ + error, + exitCode, + signal, + stdout, + stderr, + all, + command, + escapedCommand, + parsed, + timedOut, + isCanceled: context.isCanceled, + killed: spawned.killed + }); -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; - }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; - }; -})(); -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); + if (!parsed.options.reject) { + return returnedError; + } + + throw returnedError; + } + + return { + command, + escapedCommand, + exitCode: 0, + stdout, + stderr, + all, + failed: false, + timedOut: false, + isCanceled: false, + killed: false + }; + }; + + const handlePromiseOnce = onetime(handlePromise); + + handleInput(spawned, parsed.options.input); + + spawned.all = makeAllStream(spawned, parsed.options); + + return mergePromise(spawned, handlePromiseOnce); }; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.HTTPError = void 0; -exports.downloadTool = downloadTool; -exports.extract7z = extract7z; -exports.extractTar = extractTar; -exports.extractXar = extractXar; -exports.extractZip = extractZip; -exports.cacheDir = cacheDir; -exports.cacheFile = cacheFile; -exports.find = find; -exports.findAllVersions = findAllVersions; -exports.getManifestFromRepo = getManifestFromRepo; -exports.findFromManifest = findFromManifest; -exports.isExplicitVersion = isExplicitVersion; -exports.evaluateVersions = evaluateVersions; -const core = __importStar(__nccwpck_require__(9239)); -const io = __importStar(__nccwpck_require__(6359)); -const crypto = __importStar(__nccwpck_require__(6982)); -const fs = __importStar(__nccwpck_require__(9896)); -const mm = __importStar(__nccwpck_require__(5044)); -const os = __importStar(__nccwpck_require__(857)); -const path = __importStar(__nccwpck_require__(6928)); -const httpm = __importStar(__nccwpck_require__(7578)); -const semver = __importStar(__nccwpck_require__(3764)); -const stream = __importStar(__nccwpck_require__(2203)); -const util = __importStar(__nccwpck_require__(9023)); -const assert_1 = __nccwpck_require__(2613); -const exec_1 = __nccwpck_require__(6362); -const retry_helper_1 = __nccwpck_require__(1828); -class HTTPError extends Error { - constructor(httpStatusCode) { - super(`Unexpected HTTP response: ${httpStatusCode}`); - this.httpStatusCode = httpStatusCode; - Object.setPrototypeOf(this, new.target.prototype); - } -} -exports.HTTPError = HTTPError; -const IS_WINDOWS = process.platform === 'win32'; -const IS_MAC = process.platform === 'darwin'; -const userAgent = 'actions/tool-cache'; -/** - * Download a tool from an url and stream it into a file - * - * @param url url of tool to download - * @param dest path to download tool - * @param auth authorization header - * @param headers other headers - * @returns path to downloaded tool - */ -function downloadTool(url, dest, auth, headers) { - return __awaiter(this, void 0, void 0, function* () { - dest = dest || path.join(_getTempDirectory(), crypto.randomUUID()); - yield io.mkdirP(path.dirname(dest)); - core.debug(`Downloading ${url}`); - core.debug(`Destination ${dest}`); - const maxAttempts = 3; - const minSeconds = _getGlobal('TEST_DOWNLOAD_TOOL_RETRY_MIN_SECONDS', 10); - const maxSeconds = _getGlobal('TEST_DOWNLOAD_TOOL_RETRY_MAX_SECONDS', 20); - const retryHelper = new retry_helper_1.RetryHelper(maxAttempts, minSeconds, maxSeconds); - return yield retryHelper.execute(() => __awaiter(this, void 0, void 0, function* () { - return yield downloadToolAttempt(url, dest || '', auth, headers); - }), (err) => { - if (err instanceof HTTPError && err.httpStatusCode) { - // Don't retry anything less than 500, except 408 Request Timeout and 429 Too Many Requests - if (err.httpStatusCode < 500 && - err.httpStatusCode !== 408 && - err.httpStatusCode !== 429) { - return false; - } - } - // Otherwise retry - return true; - }); - }); -} -function downloadToolAttempt(url, dest, auth, headers) { - return __awaiter(this, void 0, void 0, function* () { - if (fs.existsSync(dest)) { - throw new Error(`Destination file path ${dest} already exists`); - } - // Get the response headers - const http = new httpm.HttpClient(userAgent, [], { - allowRetries: false - }); - if (auth) { - core.debug('set auth'); - if (headers === undefined) { - headers = {}; - } - headers.authorization = auth; - } - const response = yield http.get(url, headers); - if (response.message.statusCode !== 200) { - const err = new HTTPError(response.message.statusCode); - core.debug(`Failed to download from "${url}". Code(${response.message.statusCode}) Message(${response.message.statusMessage})`); - throw err; - } - // Download the response body - const pipeline = util.promisify(stream.pipeline); - const responseMessageFactory = _getGlobal('TEST_DOWNLOAD_TOOL_RESPONSE_MESSAGE_FACTORY', () => response.message); - const readStream = responseMessageFactory(); - let succeeded = false; - try { - yield pipeline(readStream, fs.createWriteStream(dest)); - core.debug('download complete'); - succeeded = true; - return dest; - } - finally { - // Error, delete dest before retry - if (!succeeded) { - core.debug('download failed'); - try { - yield io.rmRF(dest); - } - catch (err) { - core.debug(`Failed to delete '${dest}'. ${err.message}`); - } - } - } - }); -} -/** - * Extract a .7z file - * - * @param file path to the .7z file - * @param dest destination directory. Optional. - * @param _7zPath path to 7zr.exe. Optional, for long path support. Most .7z archives do not have this - * problem. If your .7z archive contains very long paths, you can pass the path to 7zr.exe which will - * gracefully handle long paths. By default 7zdec.exe is used because it is a very small program and is - * bundled with the tool lib. However it does not support long paths. 7zr.exe is the reduced command line - * interface, it is smaller than the full command line interface, and it does support long paths. At the - * time of this writing, it is freely available from the LZMA SDK that is available on the 7zip website. - * Be sure to check the current license agreement. If 7zr.exe is bundled with your action, then the path - * to 7zr.exe can be pass to this function. - * @returns path to the destination directory - */ -function extract7z(file, dest, _7zPath) { - return __awaiter(this, void 0, void 0, function* () { - (0, assert_1.ok)(IS_WINDOWS, 'extract7z() not supported on current OS'); - (0, assert_1.ok)(file, 'parameter "file" is required'); - dest = yield _createExtractFolder(dest); - const originalCwd = process.cwd(); - process.chdir(dest); - if (_7zPath) { - try { - const logLevel = core.isDebug() ? '-bb1' : '-bb0'; - const args = [ - 'x', // eXtract files with full paths - logLevel, // -bb[0-3] : set output log level - '-bd', // disable progress indicator - '-sccUTF-8', // set charset for for console input/output - file - ]; - const options = { - silent: true - }; - yield (0, exec_1.exec)(`"${_7zPath}"`, args, options); - } - finally { - process.chdir(originalCwd); - } - } - else { - const escapedScript = path - .join(__dirname, '..', 'scripts', 'Invoke-7zdec.ps1') - .replace(/'/g, "''") - .replace(/"|\n|\r/g, ''); // double-up single quotes, remove double quotes and newlines - const escapedFile = file.replace(/'/g, "''").replace(/"|\n|\r/g, ''); - const escapedTarget = dest.replace(/'/g, "''").replace(/"|\n|\r/g, ''); - const command = `& '${escapedScript}' -Source '${escapedFile}' -Target '${escapedTarget}'`; - const args = [ - '-NoLogo', - '-Sta', - '-NoProfile', - '-NonInteractive', - '-ExecutionPolicy', - 'Unrestricted', - '-Command', - command - ]; - const options = { - silent: true - }; - try { - const powershellPath = yield io.which('powershell', true); - yield (0, exec_1.exec)(`"${powershellPath}"`, args, options); - } - finally { - process.chdir(originalCwd); - } - } - return dest; - }); -} -/** - * Extract a compressed tar archive - * - * @param file path to the tar - * @param dest destination directory. Optional. - * @param flags flags for the tar command to use for extraction. Defaults to 'xz' (extracting gzipped tars). Optional. - * @returns path to the destination directory - */ -function extractTar(file_1, dest_1) { - return __awaiter(this, arguments, void 0, function* (file, dest, flags = 'xz') { - if (!file) { - throw new Error("parameter 'file' is required"); - } - // Create dest - dest = yield _createExtractFolder(dest); - // Determine whether GNU tar - core.debug('Checking tar --version'); - let versionOutput = ''; - yield (0, exec_1.exec)('tar --version', [], { - ignoreReturnCode: true, - silent: true, - listeners: { - stdout: (data) => (versionOutput += data.toString()), - stderr: (data) => (versionOutput += data.toString()) - } - }); - core.debug(versionOutput.trim()); - const isGnuTar = versionOutput.toUpperCase().includes('GNU TAR'); - // Initialize args - let args; - if (flags instanceof Array) { - args = flags; - } - else { - args = [flags]; - } - if (core.isDebug() && !flags.includes('v')) { - args.push('-v'); - } - let destArg = dest; - let fileArg = file; - if (IS_WINDOWS && isGnuTar) { - args.push('--force-local'); - destArg = dest.replace(/\\/g, '/'); - // Technically only the dest needs to have `/` but for aesthetic consistency - // convert slashes in the file arg too. - fileArg = file.replace(/\\/g, '/'); - } - if (isGnuTar) { - // Suppress warnings when using GNU tar to extract archives created by BSD tar - args.push('--warning=no-unknown-keyword'); - args.push('--overwrite'); - } - args.push('-C', destArg, '-f', fileArg); - yield (0, exec_1.exec)(`tar`, args); - return dest; - }); -} -/** - * Extract a xar compatible archive - * - * @param file path to the archive - * @param dest destination directory. Optional. - * @param flags flags for the xar. Optional. - * @returns path to the destination directory - */ -function extractXar(file_1, dest_1) { - return __awaiter(this, arguments, void 0, function* (file, dest, flags = []) { - (0, assert_1.ok)(IS_MAC, 'extractXar() not supported on current OS'); - (0, assert_1.ok)(file, 'parameter "file" is required'); - dest = yield _createExtractFolder(dest); - let args; - if (flags instanceof Array) { - args = flags; - } - else { - args = [flags]; - } - args.push('-x', '-C', dest, '-f', file); - if (core.isDebug()) { - args.push('-v'); - } - const xarPath = yield io.which('xar', true); - yield (0, exec_1.exec)(`"${xarPath}"`, _unique(args)); - return dest; - }); -} -/** - * Extract a zip - * - * @param file path to the zip - * @param dest destination directory. Optional. - * @returns path to the destination directory - */ -function extractZip(file, dest) { - return __awaiter(this, void 0, void 0, function* () { - if (!file) { - throw new Error("parameter 'file' is required"); - } - dest = yield _createExtractFolder(dest); - if (IS_WINDOWS) { - yield extractZipWin(file, dest); - } - else { - yield extractZipNix(file, dest); - } - return dest; - }); -} -function extractZipWin(file, dest) { - return __awaiter(this, void 0, void 0, function* () { - // build the powershell command - const escapedFile = file.replace(/'/g, "''").replace(/"|\n|\r/g, ''); // double-up single quotes, remove double quotes and newlines - const escapedDest = dest.replace(/'/g, "''").replace(/"|\n|\r/g, ''); - const pwshPath = yield io.which('pwsh', false); - //To match the file overwrite behavior on nix systems, we use the overwrite = true flag for ExtractToDirectory - //and the -Force flag for Expand-Archive as a fallback - if (pwshPath) { - //attempt to use pwsh with ExtractToDirectory, if this fails attempt Expand-Archive - const pwshCommand = [ - `$ErrorActionPreference = 'Stop' ;`, - `try { Add-Type -AssemblyName System.IO.Compression.ZipFile } catch { } ;`, - `try { [System.IO.Compression.ZipFile]::ExtractToDirectory('${escapedFile}', '${escapedDest}', $true) }`, - `catch { if (($_.Exception.GetType().FullName -eq 'System.Management.Automation.MethodException') -or ($_.Exception.GetType().FullName -eq 'System.Management.Automation.RuntimeException') ){ Expand-Archive -LiteralPath '${escapedFile}' -DestinationPath '${escapedDest}' -Force } else { throw $_ } } ;` - ].join(' '); - const args = [ - '-NoLogo', - '-NoProfile', - '-NonInteractive', - '-ExecutionPolicy', - 'Unrestricted', - '-Command', - pwshCommand - ]; - core.debug(`Using pwsh at path: ${pwshPath}`); - yield (0, exec_1.exec)(`"${pwshPath}"`, args); - } - else { - const powershellCommand = [ - `$ErrorActionPreference = 'Stop' ;`, - `try { Add-Type -AssemblyName System.IO.Compression.FileSystem } catch { } ;`, - `if ((Get-Command -Name Expand-Archive -Module Microsoft.PowerShell.Archive -ErrorAction Ignore)) { Expand-Archive -LiteralPath '${escapedFile}' -DestinationPath '${escapedDest}' -Force }`, - `else {[System.IO.Compression.ZipFile]::ExtractToDirectory('${escapedFile}', '${escapedDest}', $true) }` - ].join(' '); - const args = [ - '-NoLogo', - '-Sta', - '-NoProfile', - '-NonInteractive', - '-ExecutionPolicy', - 'Unrestricted', - '-Command', - powershellCommand - ]; - const powershellPath = yield io.which('powershell', true); - core.debug(`Using powershell at path: ${powershellPath}`); - yield (0, exec_1.exec)(`"${powershellPath}"`, args); - } - }); -} -function extractZipNix(file, dest) { - return __awaiter(this, void 0, void 0, function* () { - const unzipPath = yield io.which('unzip', true); - const args = [file]; - if (!core.isDebug()) { - args.unshift('-q'); - } - args.unshift('-o'); //overwrite with -o, otherwise a prompt is shown which freezes the run - yield (0, exec_1.exec)(`"${unzipPath}"`, args, { cwd: dest }); - }); -} -/** - * Caches a directory and installs it into the tool cacheDir - * - * @param sourceDir the directory to cache into tools - * @param tool tool name - * @param version version of the tool. semver format - * @param arch architecture of the tool. Optional. Defaults to machine architecture - */ -function cacheDir(sourceDir, tool, version, arch) { - return __awaiter(this, void 0, void 0, function* () { - version = semver.clean(version) || version; - arch = arch || os.arch(); - core.debug(`Caching tool ${tool} ${version} ${arch}`); - core.debug(`source dir: ${sourceDir}`); - if (!fs.statSync(sourceDir).isDirectory()) { - throw new Error('sourceDir is not a directory'); - } - // Create the tool dir - const destPath = yield _createToolPath(tool, version, arch); - // copy each child item. do not move. move can fail on Windows - // due to anti-virus software having an open handle on a file. - for (const itemName of fs.readdirSync(sourceDir)) { - const s = path.join(sourceDir, itemName); - yield io.cp(s, destPath, { recursive: true }); - } - // write .complete - _completeToolPath(tool, version, arch); - return destPath; - }); -} -/** - * Caches a downloaded file (GUID) and installs it - * into the tool cache with a given targetName - * - * @param sourceFile the file to cache into tools. Typically a result of downloadTool which is a guid. - * @param targetFile the name of the file name in the tools directory - * @param tool tool name - * @param version version of the tool. semver format - * @param arch architecture of the tool. Optional. Defaults to machine architecture - */ -function cacheFile(sourceFile, targetFile, tool, version, arch) { - return __awaiter(this, void 0, void 0, function* () { - version = semver.clean(version) || version; - arch = arch || os.arch(); - core.debug(`Caching tool ${tool} ${version} ${arch}`); - core.debug(`source file: ${sourceFile}`); - if (!fs.statSync(sourceFile).isFile()) { - throw new Error('sourceFile is not a file'); - } - // create the tool dir - const destFolder = yield _createToolPath(tool, version, arch); - // copy instead of move. move can fail on Windows due to - // anti-virus software having an open handle on a file. - const destPath = path.join(destFolder, targetFile); - core.debug(`destination file ${destPath}`); - yield io.cp(sourceFile, destPath); - // write .complete - _completeToolPath(tool, version, arch); - return destFolder; - }); -} -/** - * Finds the path to a tool version in the local installed tool cache - * - * @param toolName name of the tool - * @param versionSpec version of the tool - * @param arch optional arch. defaults to arch of computer - */ -function find(toolName, versionSpec, arch) { - if (!toolName) { - throw new Error('toolName parameter is required'); - } - if (!versionSpec) { - throw new Error('versionSpec parameter is required'); - } - arch = arch || os.arch(); - // attempt to resolve an explicit version - if (!isExplicitVersion(versionSpec)) { - const localVersions = findAllVersions(toolName, arch); - const match = evaluateVersions(localVersions, versionSpec); - versionSpec = match; - } - // check for the explicit version in the cache - let toolPath = ''; - if (versionSpec) { - versionSpec = semver.clean(versionSpec) || ''; - const cachePath = path.join(_getCacheDirectory(), toolName, versionSpec, arch); - core.debug(`checking cache: ${cachePath}`); - if (fs.existsSync(cachePath) && fs.existsSync(`${cachePath}.complete`)) { - core.debug(`Found tool in cache ${toolName} ${versionSpec} ${arch}`); - toolPath = cachePath; - } - else { - core.debug('not found'); - } - } - return toolPath; -} -/** - * Finds the paths to all versions of a tool that are installed in the local tool cache - * - * @param toolName name of the tool - * @param arch optional arch. defaults to arch of computer - */ -function findAllVersions(toolName, arch) { - const versions = []; - arch = arch || os.arch(); - const toolPath = path.join(_getCacheDirectory(), toolName); - if (fs.existsSync(toolPath)) { - const children = fs.readdirSync(toolPath); - for (const child of children) { - if (isExplicitVersion(child)) { - const fullPath = path.join(toolPath, child, arch || ''); - if (fs.existsSync(fullPath) && fs.existsSync(`${fullPath}.complete`)) { - versions.push(child); - } - } - } - } - return versions; -} -function getManifestFromRepo(owner_1, repo_1, auth_1) { - return __awaiter(this, arguments, void 0, function* (owner, repo, auth, branch = 'master') { - let releases = []; - const treeUrl = `https://api.github.com/repos/${owner}/${repo}/git/trees/${branch}`; - const http = new httpm.HttpClient('tool-cache'); - const headers = {}; - if (auth) { - core.debug('set auth'); - headers.authorization = auth; - } - const response = yield http.getJson(treeUrl, headers); - if (!response.result) { - return releases; - } - let manifestUrl = ''; - for (const item of response.result.tree) { - if (item.path === 'versions-manifest.json') { - manifestUrl = item.url; - break; - } - } - headers['accept'] = 'application/vnd.github.VERSION.raw'; - let versionsRaw = yield (yield http.get(manifestUrl, headers)).readBody(); - if (versionsRaw) { - // shouldn't be needed but protects against invalid json saved with BOM - versionsRaw = versionsRaw.replace(/^\uFEFF/, ''); - try { - releases = JSON.parse(versionsRaw); - } - catch (_a) { - core.debug('Invalid json'); - } - } - return releases; - }); -} -function findFromManifest(versionSpec_1, stable_1, manifest_1) { - return __awaiter(this, arguments, void 0, function* (versionSpec, stable, manifest, archFilter = os.arch()) { - // wrap the internal impl - const match = yield mm._findMatch(versionSpec, stable, manifest, archFilter); - return match; - }); -} -function _createExtractFolder(dest) { - return __awaiter(this, void 0, void 0, function* () { - if (!dest) { - // create a temp dir - dest = path.join(_getTempDirectory(), crypto.randomUUID()); - } - yield io.mkdirP(dest); - return dest; - }); -} -function _createToolPath(tool, version, arch) { - return __awaiter(this, void 0, void 0, function* () { - const folderPath = path.join(_getCacheDirectory(), tool, semver.clean(version) || version, arch || ''); - core.debug(`destination ${folderPath}`); - const markerPath = `${folderPath}.complete`; - yield io.rmRF(folderPath); - yield io.rmRF(markerPath); - yield io.mkdirP(folderPath); - return folderPath; - }); -} -function _completeToolPath(tool, version, arch) { - const folderPath = path.join(_getCacheDirectory(), tool, semver.clean(version) || version, arch || ''); - const markerPath = `${folderPath}.complete`; - fs.writeFileSync(markerPath, ''); - core.debug('finished caching tool'); -} -/** - * Check if version string is explicit - * - * @param versionSpec version string to check - */ -function isExplicitVersion(versionSpec) { - const c = semver.clean(versionSpec) || ''; - core.debug(`isExplicit: ${c}`); - const valid = semver.valid(c) != null; - core.debug(`explicit? ${valid}`); - return valid; -} -/** - * Get the highest satisfiying semantic version in `versions` which satisfies `versionSpec` - * - * @param versions array of versions to evaluate - * @param versionSpec semantic version spec to satisfy - */ -function evaluateVersions(versions, versionSpec) { - let version = ''; - core.debug(`evaluating ${versions.length} versions`); - versions = versions.sort((a, b) => { - if (semver.gt(a, b)) { - return 1; - } - return -1; - }); - for (let i = versions.length - 1; i >= 0; i--) { - const potential = versions[i]; - const satisfied = semver.satisfies(potential, versionSpec); - if (satisfied) { - version = potential; - break; - } - } - if (version) { - core.debug(`matched: ${version}`); - } - else { - core.debug('match not found'); - } - return version; -} -/** - * Gets RUNNER_TOOL_CACHE - */ -function _getCacheDirectory() { - const cacheDirectory = process.env['RUNNER_TOOL_CACHE'] || ''; - (0, assert_1.ok)(cacheDirectory, 'Expected RUNNER_TOOL_CACHE to be defined'); - return cacheDirectory; -} -/** - * Gets RUNNER_TEMP - */ -function _getTempDirectory() { - const tempDirectory = process.env['RUNNER_TEMP'] || ''; - (0, assert_1.ok)(tempDirectory, 'Expected RUNNER_TEMP to be defined'); - return tempDirectory; -} -/** - * Gets a global variable - */ -function _getGlobal(key, defaultValue) { - /* eslint-disable @typescript-eslint/no-explicit-any */ - const value = global[key]; - /* eslint-enable @typescript-eslint/no-explicit-any */ - return value !== undefined ? value : defaultValue; -} -/** - * Returns an array of unique values. - * @param values Values to make unique. - */ -function _unique(values) { - return Array.from(new Set(values)); -} -//# sourceMappingURL=tool-cache.js.map - -/***/ }), - -/***/ 9492: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.createFileSystemAdapter = exports.FILE_SYSTEM_ADAPTER = void 0; -const fs = __nccwpck_require__(9896); -exports.FILE_SYSTEM_ADAPTER = { - lstat: fs.lstat, - stat: fs.stat, - lstatSync: fs.lstatSync, - statSync: fs.statSync, - readdir: fs.readdir, - readdirSync: fs.readdirSync -}; -function createFileSystemAdapter(fsMethods) { - if (fsMethods === undefined) { - return exports.FILE_SYSTEM_ADAPTER; - } - return Object.assign(Object.assign({}, exports.FILE_SYSTEM_ADAPTER), fsMethods); -} -exports.createFileSystemAdapter = createFileSystemAdapter; - -/***/ }), +module.exports = execa; -/***/ 1827: -/***/ ((__unused_webpack_module, exports) => { +module.exports.sync = (file, args, options) => { + const parsed = handleArguments(file, args, options); + const command = joinCommand(file, args); + const escapedCommand = getEscapedCommand(file, args); -"use strict"; + validateInputSync(parsed.options); -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.IS_SUPPORT_READDIR_WITH_FILE_TYPES = void 0; -const NODE_PROCESS_VERSION_PARTS = process.versions.node.split('.'); -if (NODE_PROCESS_VERSION_PARTS[0] === undefined || NODE_PROCESS_VERSION_PARTS[1] === undefined) { - throw new Error(`Unexpected behavior. The 'process.versions.node' variable has invalid value: ${process.versions.node}`); -} -const MAJOR_VERSION = Number.parseInt(NODE_PROCESS_VERSION_PARTS[0], 10); -const MINOR_VERSION = Number.parseInt(NODE_PROCESS_VERSION_PARTS[1], 10); -const SUPPORTED_MAJOR_VERSION = 10; -const SUPPORTED_MINOR_VERSION = 10; -const IS_MATCHED_BY_MAJOR = MAJOR_VERSION > SUPPORTED_MAJOR_VERSION; -const IS_MATCHED_BY_MAJOR_AND_MINOR = MAJOR_VERSION === SUPPORTED_MAJOR_VERSION && MINOR_VERSION >= SUPPORTED_MINOR_VERSION; -/** - * IS `true` for Node.js 10.10 and greater. - */ -exports.IS_SUPPORT_READDIR_WITH_FILE_TYPES = IS_MATCHED_BY_MAJOR || IS_MATCHED_BY_MAJOR_AND_MINOR; + let result; + try { + result = childProcess.spawnSync(parsed.file, parsed.args, parsed.options); + } catch (error) { + throw makeError({ + error, + stdout: '', + stderr: '', + all: '', + command, + escapedCommand, + parsed, + timedOut: false, + isCanceled: false, + killed: false + }); + } + const stdout = handleOutput(parsed.options, result.stdout, result.error); + const stderr = handleOutput(parsed.options, result.stderr, result.error); -/***/ }), + if (result.error || result.status !== 0 || result.signal !== null) { + const error = makeError({ + stdout, + stderr, + error: result.error, + signal: result.signal, + exitCode: result.status, + command, + escapedCommand, + parsed, + timedOut: result.error && result.error.code === 'ETIMEDOUT', + isCanceled: false, + killed: result.signal !== null + }); -/***/ 2770: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + if (!parsed.options.reject) { + return error; + } -"use strict"; + throw error; + } -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.Settings = exports.scandirSync = exports.scandir = void 0; -const async = __nccwpck_require__(6991); -const sync = __nccwpck_require__(4308); -const settings_1 = __nccwpck_require__(3233); -exports.Settings = settings_1.default; -function scandir(path, optionsOrSettingsOrCallback, callback) { - if (typeof optionsOrSettingsOrCallback === 'function') { - async.read(path, getSettings(), optionsOrSettingsOrCallback); - return; - } - async.read(path, getSettings(optionsOrSettingsOrCallback), callback); -} -exports.scandir = scandir; -function scandirSync(path, optionsOrSettings) { - const settings = getSettings(optionsOrSettings); - return sync.read(path, settings); -} -exports.scandirSync = scandirSync; -function getSettings(settingsOrOptions = {}) { - if (settingsOrOptions instanceof settings_1.default) { - return settingsOrOptions; - } - return new settings_1.default(settingsOrOptions); -} + return { + command, + escapedCommand, + exitCode: 0, + stdout, + stderr, + failed: false, + timedOut: false, + isCanceled: false, + killed: false + }; +}; +module.exports.command = (command, options) => { + const [file, ...args] = parseCommand(command); + return execa(file, args, options); +}; -/***/ }), +module.exports.commandSync = (command, options) => { + const [file, ...args] = parseCommand(command); + return execa.sync(file, args, options); +}; -/***/ 6991: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { +module.exports.node = (scriptPath, args, options = {}) => { + if (args && !Array.isArray(args) && typeof args === 'object') { + options = args; + args = []; + } -"use strict"; + const stdio = normalizeStdio.node(options); + const defaultExecArgv = process.execArgv.filter(arg => !arg.startsWith('--inspect')); -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.readdir = exports.readdirWithFileTypes = exports.read = void 0; -const fsStat = __nccwpck_require__(3824); -const rpl = __nccwpck_require__(5172); -const constants_1 = __nccwpck_require__(1827); -const utils = __nccwpck_require__(6828); -const common = __nccwpck_require__(9142); -function read(directory, settings, callback) { - if (!settings.stats && constants_1.IS_SUPPORT_READDIR_WITH_FILE_TYPES) { - readdirWithFileTypes(directory, settings, callback); - return; - } - readdir(directory, settings, callback); -} -exports.read = read; -function readdirWithFileTypes(directory, settings, callback) { - settings.fs.readdir(directory, { withFileTypes: true }, (readdirError, dirents) => { - if (readdirError !== null) { - callFailureCallback(callback, readdirError); - return; - } - const entries = dirents.map((dirent) => ({ - dirent, - name: dirent.name, - path: common.joinPathSegments(directory, dirent.name, settings.pathSegmentSeparator) - })); - if (!settings.followSymbolicLinks) { - callSuccessCallback(callback, entries); - return; - } - const tasks = entries.map((entry) => makeRplTaskEntry(entry, settings)); - rpl(tasks, (rplError, rplEntries) => { - if (rplError !== null) { - callFailureCallback(callback, rplError); - return; - } - callSuccessCallback(callback, rplEntries); - }); - }); -} -exports.readdirWithFileTypes = readdirWithFileTypes; -function makeRplTaskEntry(entry, settings) { - return (done) => { - if (!entry.dirent.isSymbolicLink()) { - done(null, entry); - return; - } - settings.fs.stat(entry.path, (statError, stats) => { - if (statError !== null) { - if (settings.throwErrorOnBrokenSymbolicLink) { - done(statError); - return; - } - done(null, entry); - return; - } - entry.dirent = utils.fs.createDirentFromStats(entry.name, stats); - done(null, entry); - }); - }; -} -function readdir(directory, settings, callback) { - settings.fs.readdir(directory, (readdirError, names) => { - if (readdirError !== null) { - callFailureCallback(callback, readdirError); - return; - } - const tasks = names.map((name) => { - const path = common.joinPathSegments(directory, name, settings.pathSegmentSeparator); - return (done) => { - fsStat.stat(path, settings.fsStatSettings, (error, stats) => { - if (error !== null) { - done(error); - return; - } - const entry = { - name, - path, - dirent: utils.fs.createDirentFromStats(name, stats) - }; - if (settings.stats) { - entry.stats = stats; - } - done(null, entry); - }); - }; - }); - rpl(tasks, (rplError, entries) => { - if (rplError !== null) { - callFailureCallback(callback, rplError); - return; - } - callSuccessCallback(callback, entries); - }); - }); -} -exports.readdir = readdir; -function callFailureCallback(callback, error) { - callback(error); -} -function callSuccessCallback(callback, result) { - callback(null, result); -} + const { + nodePath = process.execPath, + nodeOptions = defaultExecArgv + } = options; + + return execa( + nodePath, + [ + ...nodeOptions, + scriptPath, + ...(Array.isArray(args) ? args : []) + ], + { + ...options, + stdin: undefined, + stdout: undefined, + stderr: undefined, + stdio, + shell: false + } + ); +}; /***/ }), -/***/ 9142: -/***/ ((__unused_webpack_module, exports) => { +/***/ 5011: +/***/ ((module) => { -"use strict"; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.joinPathSegments = void 0; -function joinPathSegments(a, b, separator) { - /** - * The correct handling of cases when the first segment is a root (`/`, `C:/`) or UNC path (`//?/C:/`). - */ - if (a.endsWith(separator)) { - return a + b; - } - return a + separator + b; -} -exports.joinPathSegments = joinPathSegments; +const normalizeArgs = (file, args = []) => { + if (!Array.isArray(args)) { + return [file]; + } + + return [file, ...args]; +}; +const NO_ESCAPE_REGEXP = /^[\w.-]+$/; +const DOUBLE_QUOTES_REGEXP = /"/g; -/***/ }), +const escapeArg = arg => { + if (typeof arg !== 'string' || NO_ESCAPE_REGEXP.test(arg)) { + return arg; + } -/***/ 4308: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + return `"${arg.replace(DOUBLE_QUOTES_REGEXP, '\\"')}"`; +}; -"use strict"; +const joinCommand = (file, args) => { + return normalizeArgs(file, args).join(' '); +}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.readdir = exports.readdirWithFileTypes = exports.read = void 0; -const fsStat = __nccwpck_require__(3824); -const constants_1 = __nccwpck_require__(1827); -const utils = __nccwpck_require__(6828); -const common = __nccwpck_require__(9142); -function read(directory, settings) { - if (!settings.stats && constants_1.IS_SUPPORT_READDIR_WITH_FILE_TYPES) { - return readdirWithFileTypes(directory, settings); - } - return readdir(directory, settings); -} -exports.read = read; -function readdirWithFileTypes(directory, settings) { - const dirents = settings.fs.readdirSync(directory, { withFileTypes: true }); - return dirents.map((dirent) => { - const entry = { - dirent, - name: dirent.name, - path: common.joinPathSegments(directory, dirent.name, settings.pathSegmentSeparator) - }; - if (entry.dirent.isSymbolicLink() && settings.followSymbolicLinks) { - try { - const stats = settings.fs.statSync(entry.path); - entry.dirent = utils.fs.createDirentFromStats(entry.name, stats); - } - catch (error) { - if (settings.throwErrorOnBrokenSymbolicLink) { - throw error; - } - } - } - return entry; - }); -} -exports.readdirWithFileTypes = readdirWithFileTypes; -function readdir(directory, settings) { - const names = settings.fs.readdirSync(directory); - return names.map((name) => { - const entryPath = common.joinPathSegments(directory, name, settings.pathSegmentSeparator); - const stats = fsStat.statSync(entryPath, settings.fsStatSettings); - const entry = { - name, - path: entryPath, - dirent: utils.fs.createDirentFromStats(name, stats) - }; - if (settings.stats) { - entry.stats = stats; - } - return entry; - }); -} -exports.readdir = readdir; +const getEscapedCommand = (file, args) => { + return normalizeArgs(file, args).map(arg => escapeArg(arg)).join(' '); +}; + +const SPACES_REGEXP = / +/g; + +// Handle `execa.command()` +const parseCommand = command => { + const tokens = []; + for (const token of command.trim().split(SPACES_REGEXP)) { + // Allow spaces to be escaped by a backslash if not meant as a delimiter + const previousToken = tokens[tokens.length - 1]; + if (previousToken && previousToken.endsWith('\\')) { + // Merge previous token with current one + tokens[tokens.length - 1] = `${previousToken.slice(0, -1)} ${token}`; + } else { + tokens.push(token); + } + } + + return tokens; +}; + +module.exports = { + joinCommand, + getEscapedCommand, + parseCommand +}; /***/ }), -/***/ 3233: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { +/***/ 5588: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -Object.defineProperty(exports, "__esModule", ({ value: true })); -const path = __nccwpck_require__(6928); -const fsStat = __nccwpck_require__(3824); -const fs = __nccwpck_require__(9492); -class Settings { - constructor(_options = {}) { - this._options = _options; - this.followSymbolicLinks = this._getValue(this._options.followSymbolicLinks, false); - this.fs = fs.createFileSystemAdapter(this._options.fs); - this.pathSegmentSeparator = this._getValue(this._options.pathSegmentSeparator, path.sep); - this.stats = this._getValue(this._options.stats, false); - this.throwErrorOnBrokenSymbolicLink = this._getValue(this._options.throwErrorOnBrokenSymbolicLink, true); - this.fsStatSettings = new fsStat.Settings({ - followSymbolicLink: this.followSymbolicLinks, - fs: this.fs, - throwErrorOnBrokenSymbolicLink: this.throwErrorOnBrokenSymbolicLink - }); - } - _getValue(option, value) { - return option !== null && option !== void 0 ? option : value; - } -} -exports["default"] = Settings; +const {signalsByName} = __nccwpck_require__(4796); +const getErrorPrefix = ({timedOut, timeout, errorCode, signal, signalDescription, exitCode, isCanceled}) => { + if (timedOut) { + return `timed out after ${timeout} milliseconds`; + } -/***/ }), + if (isCanceled) { + return 'was canceled'; + } -/***/ 5221: -/***/ ((__unused_webpack_module, exports) => { + if (errorCode !== undefined) { + return `failed with ${errorCode}`; + } -"use strict"; + if (signal !== undefined) { + return `was killed with ${signal} (${signalDescription})`; + } -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.createDirentFromStats = void 0; -class DirentFromStats { - constructor(name, stats) { - this.name = name; - this.isBlockDevice = stats.isBlockDevice.bind(stats); - this.isCharacterDevice = stats.isCharacterDevice.bind(stats); - this.isDirectory = stats.isDirectory.bind(stats); - this.isFIFO = stats.isFIFO.bind(stats); - this.isFile = stats.isFile.bind(stats); - this.isSocket = stats.isSocket.bind(stats); - this.isSymbolicLink = stats.isSymbolicLink.bind(stats); - } -} -function createDirentFromStats(name, stats) { - return new DirentFromStats(name, stats); -} -exports.createDirentFromStats = createDirentFromStats; + if (exitCode !== undefined) { + return `failed with exit code ${exitCode}`; + } + return 'failed'; +}; -/***/ }), +const makeError = ({ + stdout, + stderr, + all, + error, + signal, + exitCode, + command, + escapedCommand, + timedOut, + isCanceled, + killed, + parsed: {options: {timeout}} +}) => { + // `signal` and `exitCode` emitted on `spawned.on('exit')` event can be `null`. + // We normalize them to `undefined` + exitCode = exitCode === null ? undefined : exitCode; + signal = signal === null ? undefined : signal; + const signalDescription = signal === undefined ? undefined : signalsByName[signal].description; -/***/ 6828: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + const errorCode = error && error.code; -"use strict"; + const prefix = getErrorPrefix({timedOut, timeout, errorCode, signal, signalDescription, exitCode, isCanceled}); + const execaMessage = `Command ${prefix}: ${command}`; + const isError = Object.prototype.toString.call(error) === '[object Error]'; + const shortMessage = isError ? `${execaMessage}\n${error.message}` : execaMessage; + const message = [shortMessage, stderr, stdout].filter(Boolean).join('\n'); -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.fs = void 0; -const fs = __nccwpck_require__(5221); -exports.fs = fs; + if (isError) { + error.originalMessage = error.message; + error.message = message; + } else { + error = new Error(message); + } + error.shortMessage = shortMessage; + error.command = command; + error.escapedCommand = escapedCommand; + error.exitCode = exitCode; + error.signal = signal; + error.signalDescription = signalDescription; + error.stdout = stdout; + error.stderr = stderr; -/***/ }), + if (all !== undefined) { + error.all = all; + } -/***/ 5994: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + if ('bufferedData' in error) { + delete error.bufferedData; + } -"use strict"; + error.failed = true; + error.timedOut = Boolean(timedOut); + error.isCanceled = isCanceled; + error.killed = killed && !timedOut; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.createFileSystemAdapter = exports.FILE_SYSTEM_ADAPTER = void 0; -const fs = __nccwpck_require__(9896); -exports.FILE_SYSTEM_ADAPTER = { - lstat: fs.lstat, - stat: fs.stat, - lstatSync: fs.lstatSync, - statSync: fs.statSync + return error; }; -function createFileSystemAdapter(fsMethods) { - if (fsMethods === undefined) { - return exports.FILE_SYSTEM_ADAPTER; - } - return Object.assign(Object.assign({}, exports.FILE_SYSTEM_ADAPTER), fsMethods); -} -exports.createFileSystemAdapter = createFileSystemAdapter; + +module.exports = makeError; /***/ }), -/***/ 3824: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { +/***/ 1212: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.statSync = exports.stat = exports.Settings = void 0; -const async = __nccwpck_require__(2085); -const sync = __nccwpck_require__(2598); -const settings_1 = __nccwpck_require__(8975); -exports.Settings = settings_1.default; -function stat(path, optionsOrSettingsOrCallback, callback) { - if (typeof optionsOrSettingsOrCallback === 'function') { - async.read(path, getSettings(), optionsOrSettingsOrCallback); - return; - } - async.read(path, getSettings(optionsOrSettingsOrCallback), callback); -} -exports.stat = stat; -function statSync(path, optionsOrSettings) { - const settings = getSettings(optionsOrSettings); - return sync.read(path, settings); -} -exports.statSync = statSync; -function getSettings(settingsOrOptions = {}) { - if (settingsOrOptions instanceof settings_1.default) { - return settingsOrOptions; - } - return new settings_1.default(settingsOrOptions); -} - - -/***/ }), - -/***/ 2085: -/***/ ((__unused_webpack_module, exports) => { +const os = __nccwpck_require__(857); +const onExit = __nccwpck_require__(2638); -"use strict"; +const DEFAULT_FORCE_KILL_TIMEOUT = 1000 * 5; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.read = void 0; -function read(path, settings, callback) { - settings.fs.lstat(path, (lstatError, lstat) => { - if (lstatError !== null) { - callFailureCallback(callback, lstatError); - return; - } - if (!lstat.isSymbolicLink() || !settings.followSymbolicLink) { - callSuccessCallback(callback, lstat); - return; - } - settings.fs.stat(path, (statError, stat) => { - if (statError !== null) { - if (settings.throwErrorOnBrokenSymbolicLink) { - callFailureCallback(callback, statError); - return; - } - callSuccessCallback(callback, lstat); - return; - } - if (settings.markSymbolicLink) { - stat.isSymbolicLink = () => true; - } - callSuccessCallback(callback, stat); - }); - }); -} -exports.read = read; -function callFailureCallback(callback, error) { - callback(error); -} -function callSuccessCallback(callback, result) { - callback(null, result); -} +// Monkey-patches `childProcess.kill()` to add `forceKillAfterTimeout` behavior +const spawnedKill = (kill, signal = 'SIGTERM', options = {}) => { + const killResult = kill(signal); + setKillTimeout(kill, signal, options, killResult); + return killResult; +}; +const setKillTimeout = (kill, signal, options, killResult) => { + if (!shouldForceKill(signal, options, killResult)) { + return; + } -/***/ }), + const timeout = getForceKillAfterTimeout(options); + const t = setTimeout(() => { + kill('SIGKILL'); + }, timeout); -/***/ 2598: -/***/ ((__unused_webpack_module, exports) => { + // Guarded because there's no `.unref()` when `execa` is used in the renderer + // process in Electron. This cannot be tested since we don't run tests in + // Electron. + // istanbul ignore else + if (t.unref) { + t.unref(); + } +}; -"use strict"; +const shouldForceKill = (signal, {forceKillAfterTimeout}, killResult) => { + return isSigterm(signal) && forceKillAfterTimeout !== false && killResult; +}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.read = void 0; -function read(path, settings) { - const lstat = settings.fs.lstatSync(path); - if (!lstat.isSymbolicLink() || !settings.followSymbolicLink) { - return lstat; - } - try { - const stat = settings.fs.statSync(path); - if (settings.markSymbolicLink) { - stat.isSymbolicLink = () => true; - } - return stat; - } - catch (error) { - if (!settings.throwErrorOnBrokenSymbolicLink) { - return lstat; - } - throw error; - } -} -exports.read = read; +const isSigterm = signal => { + return signal === os.constants.signals.SIGTERM || + (typeof signal === 'string' && signal.toUpperCase() === 'SIGTERM'); +}; +const getForceKillAfterTimeout = ({forceKillAfterTimeout = true}) => { + if (forceKillAfterTimeout === true) { + return DEFAULT_FORCE_KILL_TIMEOUT; + } -/***/ }), + if (!Number.isFinite(forceKillAfterTimeout) || forceKillAfterTimeout < 0) { + throw new TypeError(`Expected the \`forceKillAfterTimeout\` option to be a non-negative integer, got \`${forceKillAfterTimeout}\` (${typeof forceKillAfterTimeout})`); + } -/***/ 8975: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + return forceKillAfterTimeout; +}; -"use strict"; +// `childProcess.cancel()` +const spawnedCancel = (spawned, context) => { + const killResult = spawned.kill(); -Object.defineProperty(exports, "__esModule", ({ value: true })); -const fs = __nccwpck_require__(5994); -class Settings { - constructor(_options = {}) { - this._options = _options; - this.followSymbolicLink = this._getValue(this._options.followSymbolicLink, true); - this.fs = fs.createFileSystemAdapter(this._options.fs); - this.markSymbolicLink = this._getValue(this._options.markSymbolicLink, false); - this.throwErrorOnBrokenSymbolicLink = this._getValue(this._options.throwErrorOnBrokenSymbolicLink, true); - } - _getValue(option, value) { - return option !== null && option !== void 0 ? option : value; - } -} -exports["default"] = Settings; + if (killResult) { + context.isCanceled = true; + } +}; +const timeoutKill = (spawned, signal, reject) => { + spawned.kill(signal); + reject(Object.assign(new Error('Timed out'), {timedOut: true, signal})); +}; -/***/ }), +// `timeout` option handling +const setupTimeout = (spawned, {timeout, killSignal = 'SIGTERM'}, spawnedPromise) => { + if (timeout === 0 || timeout === undefined) { + return spawnedPromise; + } -/***/ 2552: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + let timeoutId; + const timeoutPromise = new Promise((resolve, reject) => { + timeoutId = setTimeout(() => { + timeoutKill(spawned, killSignal, reject); + }, timeout); + }); -"use strict"; + const safeSpawnedPromise = spawnedPromise.finally(() => { + clearTimeout(timeoutId); + }); -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.Settings = exports.walkStream = exports.walkSync = exports.walk = void 0; -const async_1 = __nccwpck_require__(9997); -const stream_1 = __nccwpck_require__(4697); -const sync_1 = __nccwpck_require__(638); -const settings_1 = __nccwpck_require__(4039); -exports.Settings = settings_1.default; -function walk(directory, optionsOrSettingsOrCallback, callback) { - if (typeof optionsOrSettingsOrCallback === 'function') { - new async_1.default(directory, getSettings()).read(optionsOrSettingsOrCallback); - return; - } - new async_1.default(directory, getSettings(optionsOrSettingsOrCallback)).read(callback); -} -exports.walk = walk; -function walkSync(directory, optionsOrSettings) { - const settings = getSettings(optionsOrSettings); - const provider = new sync_1.default(directory, settings); - return provider.read(); -} -exports.walkSync = walkSync; -function walkStream(directory, optionsOrSettings) { - const settings = getSettings(optionsOrSettings); - const provider = new stream_1.default(directory, settings); - return provider.read(); -} -exports.walkStream = walkStream; -function getSettings(settingsOrOptions = {}) { - if (settingsOrOptions instanceof settings_1.default) { - return settingsOrOptions; - } - return new settings_1.default(settingsOrOptions); -} + return Promise.race([timeoutPromise, safeSpawnedPromise]); +}; +const validateTimeout = ({timeout}) => { + if (timeout !== undefined && (!Number.isFinite(timeout) || timeout < 0)) { + throw new TypeError(`Expected the \`timeout\` option to be a non-negative integer, got \`${timeout}\` (${typeof timeout})`); + } +}; -/***/ }), +// `cleanup` option handling +const setExitHandler = async (spawned, {cleanup, detached}, timedPromise) => { + if (!cleanup || detached) { + return timedPromise; + } -/***/ 9997: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + const removeExitHandler = onExit(() => { + spawned.kill(); + }); -"use strict"; + return timedPromise.finally(() => { + removeExitHandler(); + }); +}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -const async_1 = __nccwpck_require__(4387); -class AsyncProvider { - constructor(_root, _settings) { - this._root = _root; - this._settings = _settings; - this._reader = new async_1.default(this._root, this._settings); - this._storage = []; - } - read(callback) { - this._reader.onError((error) => { - callFailureCallback(callback, error); - }); - this._reader.onEntry((entry) => { - this._storage.push(entry); - }); - this._reader.onEnd(() => { - callSuccessCallback(callback, this._storage); - }); - this._reader.read(); - } -} -exports["default"] = AsyncProvider; -function callFailureCallback(callback, error) { - callback(error); -} -function callSuccessCallback(callback, entries) { - callback(null, entries); -} +module.exports = { + spawnedKill, + spawnedCancel, + setupTimeout, + validateTimeout, + setExitHandler +}; /***/ }), -/***/ 4697: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; +/***/ 2403: +/***/ ((module) => { -Object.defineProperty(exports, "__esModule", ({ value: true })); -const stream_1 = __nccwpck_require__(2203); -const async_1 = __nccwpck_require__(4387); -class StreamProvider { - constructor(_root, _settings) { - this._root = _root; - this._settings = _settings; - this._reader = new async_1.default(this._root, this._settings); - this._stream = new stream_1.Readable({ - objectMode: true, - read: () => { }, - destroy: () => { - if (!this._reader.isDestroyed) { - this._reader.destroy(); - } - } - }); - } - read() { - this._reader.onError((error) => { - this._stream.emit('error', error); - }); - this._reader.onEntry((entry) => { - this._stream.push(entry); - }); - this._reader.onEnd(() => { - this._stream.push(null); - }); - this._reader.read(); - return this._stream; - } -} -exports["default"] = StreamProvider; -/***/ }), +const nativePromisePrototype = (async () => {})().constructor.prototype; +const descriptors = ['then', 'catch', 'finally'].map(property => [ + property, + Reflect.getOwnPropertyDescriptor(nativePromisePrototype, property) +]); -/***/ 638: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { +// The return value is a mixin of `childProcess` and `Promise` +const mergePromise = (spawned, promise) => { + for (const [property, descriptor] of descriptors) { + // Starting the main `promise` is deferred to avoid consuming streams + const value = typeof promise === 'function' ? + (...args) => Reflect.apply(descriptor.value, promise(), args) : + descriptor.value.bind(promise); -"use strict"; + Reflect.defineProperty(spawned, property, {...descriptor, value}); + } -Object.defineProperty(exports, "__esModule", ({ value: true })); -const sync_1 = __nccwpck_require__(2800); -class SyncProvider { - constructor(_root, _settings) { - this._root = _root; - this._settings = _settings; - this._reader = new sync_1.default(this._root, this._settings); - } - read() { - return this._reader.read(); - } -} -exports["default"] = SyncProvider; + return spawned; +}; +// Use promises instead of `child_process` events +const getSpawnedPromise = spawned => { + return new Promise((resolve, reject) => { + spawned.on('exit', (exitCode, signal) => { + resolve({exitCode, signal}); + }); -/***/ }), + spawned.on('error', error => { + reject(error); + }); -/***/ 4387: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + if (spawned.stdin) { + spawned.stdin.on('error', error => { + reject(error); + }); + } + }); +}; -"use strict"; +module.exports = { + mergePromise, + getSpawnedPromise +}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -const events_1 = __nccwpck_require__(4434); -const fsScandir = __nccwpck_require__(2770); -const fastq = __nccwpck_require__(1014); -const common = __nccwpck_require__(4178); -const reader_1 = __nccwpck_require__(2776); -class AsyncReader extends reader_1.default { - constructor(_root, _settings) { - super(_root, _settings); - this._settings = _settings; - this._scandir = fsScandir.scandir; - this._emitter = new events_1.EventEmitter(); - this._queue = fastq(this._worker.bind(this), this._settings.concurrency); - this._isFatalError = false; - this._isDestroyed = false; - this._queue.drain = () => { - if (!this._isFatalError) { - this._emitter.emit('end'); - } - }; - } - read() { - this._isFatalError = false; - this._isDestroyed = false; - setImmediate(() => { - this._pushToQueue(this._root, this._settings.basePath); - }); - return this._emitter; - } - get isDestroyed() { - return this._isDestroyed; - } - destroy() { - if (this._isDestroyed) { - throw new Error('The reader is already destroyed'); - } - this._isDestroyed = true; - this._queue.killAndDrain(); - } - onEntry(callback) { - this._emitter.on('entry', callback); - } - onError(callback) { - this._emitter.once('error', callback); - } - onEnd(callback) { - this._emitter.once('end', callback); - } - _pushToQueue(directory, base) { - const queueItem = { directory, base }; - this._queue.push(queueItem, (error) => { - if (error !== null) { - this._handleError(error); - } - }); - } - _worker(item, done) { - this._scandir(item.directory, this._settings.fsScandirSettings, (error, entries) => { - if (error !== null) { - done(error, undefined); - return; - } - for (const entry of entries) { - this._handleEntry(entry, item.base); - } - done(null, undefined); - }); - } - _handleError(error) { - if (this._isDestroyed || !common.isFatalError(this._settings, error)) { - return; - } - this._isFatalError = true; - this._isDestroyed = true; - this._emitter.emit('error', error); - } - _handleEntry(entry, base) { - if (this._isDestroyed || this._isFatalError) { - return; - } - const fullpath = entry.path; - if (base !== undefined) { - entry.path = common.joinPathSegments(base, entry.name, this._settings.pathSegmentSeparator); - } - if (common.isAppliedFilter(this._settings.entryFilter, entry)) { - this._emitEntry(entry); - } - if (entry.dirent.isDirectory() && common.isAppliedFilter(this._settings.deepFilter, entry)) { - this._pushToQueue(fullpath, base === undefined ? undefined : entry.path); - } - } - _emitEntry(entry) { - this._emitter.emit('entry', entry); - } -} -exports["default"] = AsyncReader; /***/ }), -/***/ 4178: -/***/ ((__unused_webpack_module, exports) => { +/***/ 2751: +/***/ ((module) => { -"use strict"; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.joinPathSegments = exports.replacePathSegmentSeparator = exports.isAppliedFilter = exports.isFatalError = void 0; -function isFatalError(settings, error) { - if (settings.errorFilter === null) { - return true; - } - return !settings.errorFilter(error); -} -exports.isFatalError = isFatalError; -function isAppliedFilter(filter, value) { - return filter === null || filter(value); -} -exports.isAppliedFilter = isAppliedFilter; -function replacePathSegmentSeparator(filepath, separator) { - return filepath.split(/[/\\]/).join(separator); -} -exports.replacePathSegmentSeparator = replacePathSegmentSeparator; -function joinPathSegments(a, b, separator) { - if (a === '') { - return b; - } - /** - * The correct handling of cases when the first segment is a root (`/`, `C:/`) or UNC path (`//?/C:/`). - */ - if (a.endsWith(separator)) { - return a + b; - } - return a + separator + b; -} -exports.joinPathSegments = joinPathSegments; +const aliases = ['stdin', 'stdout', 'stderr']; +const hasAlias = options => aliases.some(alias => options[alias] !== undefined); -/***/ }), +const normalizeStdio = options => { + if (!options) { + return; + } -/***/ 2776: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + const {stdio} = options; -"use strict"; + if (stdio === undefined) { + return aliases.map(alias => options[alias]); + } -Object.defineProperty(exports, "__esModule", ({ value: true })); -const common = __nccwpck_require__(4178); -class Reader { - constructor(_root, _settings) { - this._root = _root; - this._settings = _settings; - this._root = common.replacePathSegmentSeparator(_root, _settings.pathSegmentSeparator); - } -} -exports["default"] = Reader; + if (hasAlias(options)) { + throw new Error(`It's not possible to provide \`stdio\` in combination with one of ${aliases.map(alias => `\`${alias}\``).join(', ')}`); + } + if (typeof stdio === 'string') { + return stdio; + } -/***/ }), + if (!Array.isArray(stdio)) { + throw new TypeError(`Expected \`stdio\` to be of type \`string\` or \`Array\`, got \`${typeof stdio}\``); + } -/***/ 2800: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + const length = Math.max(stdio.length, aliases.length); + return Array.from({length}, (value, index) => stdio[index]); +}; -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -const fsScandir = __nccwpck_require__(2770); -const common = __nccwpck_require__(4178); -const reader_1 = __nccwpck_require__(2776); -class SyncReader extends reader_1.default { - constructor() { - super(...arguments); - this._scandir = fsScandir.scandirSync; - this._storage = []; - this._queue = new Set(); - } - read() { - this._pushToQueue(this._root, this._settings.basePath); - this._handleQueue(); - return this._storage; - } - _pushToQueue(directory, base) { - this._queue.add({ directory, base }); - } - _handleQueue() { - for (const item of this._queue.values()) { - this._handleDirectory(item.directory, item.base); - } - } - _handleDirectory(directory, base) { - try { - const entries = this._scandir(directory, this._settings.fsScandirSettings); - for (const entry of entries) { - this._handleEntry(entry, base); - } - } - catch (error) { - this._handleError(error); - } - } - _handleError(error) { - if (!common.isFatalError(this._settings, error)) { - return; - } - throw error; - } - _handleEntry(entry, base) { - const fullpath = entry.path; - if (base !== undefined) { - entry.path = common.joinPathSegments(base, entry.name, this._settings.pathSegmentSeparator); - } - if (common.isAppliedFilter(this._settings.entryFilter, entry)) { - this._pushToStorage(entry); - } - if (entry.dirent.isDirectory() && common.isAppliedFilter(this._settings.deepFilter, entry)) { - this._pushToQueue(fullpath, base === undefined ? undefined : entry.path); - } - } - _pushToStorage(entry) { - this._storage.push(entry); - } -} -exports["default"] = SyncReader; +module.exports = normalizeStdio; +// `ipc` is pushed unless it is already present +module.exports.node = options => { + const stdio = normalizeStdio(options); -/***/ }), + if (stdio === 'ipc') { + return 'ipc'; + } -/***/ 4039: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + if (stdio === undefined || typeof stdio === 'string') { + return [stdio, stdio, stdio, 'ipc']; + } -"use strict"; + if (stdio.includes('ipc')) { + return stdio; + } -Object.defineProperty(exports, "__esModule", ({ value: true })); -const path = __nccwpck_require__(6928); -const fsScandir = __nccwpck_require__(2770); -class Settings { - constructor(_options = {}) { - this._options = _options; - this.basePath = this._getValue(this._options.basePath, undefined); - this.concurrency = this._getValue(this._options.concurrency, Number.POSITIVE_INFINITY); - this.deepFilter = this._getValue(this._options.deepFilter, null); - this.entryFilter = this._getValue(this._options.entryFilter, null); - this.errorFilter = this._getValue(this._options.errorFilter, null); - this.pathSegmentSeparator = this._getValue(this._options.pathSegmentSeparator, path.sep); - this.fsScandirSettings = new fsScandir.Settings({ - followSymbolicLinks: this._options.followSymbolicLinks, - fs: this._options.fs, - pathSegmentSeparator: this._options.pathSegmentSeparator, - stats: this._options.stats, - throwErrorOnBrokenSymbolicLink: this._options.throwErrorOnBrokenSymbolicLink - }); - } - _getValue(option, value) { - return option !== null && option !== void 0 ? option : value; - } -} -exports["default"] = Settings; + return [...stdio, 'ipc']; +}; /***/ }), -/***/ 727: +/***/ 1620: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; - - -const stringify = __nccwpck_require__(2670); -const compile = __nccwpck_require__(2714); -const expand = __nccwpck_require__(539); -const parse = __nccwpck_require__(5920); - -/** - * Expand the given pattern or create a regex-compatible string. - * - * ```js - * const braces = require('braces'); - * console.log(braces('{a,b,c}', { compile: true })); //=> ['(a|b|c)'] - * console.log(braces('{a,b,c}')); //=> ['a', 'b', 'c'] - * ``` - * @param {String} `str` - * @param {Object} `options` - * @return {String} - * @api public - */ -const braces = (input, options = {}) => { - let output = []; +const isStream = __nccwpck_require__(3783); +const getStream = __nccwpck_require__(4333); +const mergeStream = __nccwpck_require__(1340); - if (Array.isArray(input)) { - for (const pattern of input) { - const result = braces.create(pattern, options); - if (Array.isArray(result)) { - output.push(...result); - } else { - output.push(result); - } - } - } else { - output = [].concat(braces.create(input, options)); - } +// `input` option +const handleInput = (spawned, input) => { + // Checking for stdin is workaround for https://github.com/nodejs/node/issues/26852 + // @todo remove `|| spawned.stdin === undefined` once we drop support for Node.js <=12.2.0 + if (input === undefined || spawned.stdin === undefined) { + return; + } - if (options && options.expand === true && options.nodupes === true) { - output = [...new Set(output)]; - } - return output; + if (isStream(input)) { + input.pipe(spawned.stdin); + } else { + spawned.stdin.end(input); + } }; -/** - * Parse the given `str` with the given `options`. - * - * ```js - * // braces.parse(pattern, [, options]); - * const ast = braces.parse('a/{b,c}/d'); - * console.log(ast); - * ``` - * @param {String} pattern Brace pattern to parse - * @param {Object} options - * @return {Object} Returns an AST - * @api public - */ - -braces.parse = (input, options = {}) => parse(input, options); +// `all` interleaves `stdout` and `stderr` +const makeAllStream = (spawned, {all}) => { + if (!all || (!spawned.stdout && !spawned.stderr)) { + return; + } -/** - * Creates a braces string from an AST, or an AST node. - * - * ```js - * const braces = require('braces'); - * let ast = braces.parse('foo/{a,b}/bar'); - * console.log(stringify(ast.nodes[2])); //=> '{a,b}' - * ``` - * @param {String} `input` Brace pattern or AST. - * @param {Object} `options` - * @return {Array} Returns an array of expanded values. - * @api public - */ + const mixed = mergeStream(); -braces.stringify = (input, options = {}) => { - if (typeof input === 'string') { - return stringify(braces.parse(input, options), options); - } - return stringify(input, options); -}; + if (spawned.stdout) { + mixed.add(spawned.stdout); + } -/** - * Compiles a brace pattern into a regex-compatible, optimized string. - * This method is called by the main [braces](#braces) function by default. - * - * ```js - * const braces = require('braces'); - * console.log(braces.compile('a/{b,c}/d')); - * //=> ['a/(b|c)/d'] - * ``` - * @param {String} `input` Brace pattern or AST. - * @param {Object} `options` - * @return {Array} Returns an array of expanded values. - * @api public - */ + if (spawned.stderr) { + mixed.add(spawned.stderr); + } -braces.compile = (input, options = {}) => { - if (typeof input === 'string') { - input = braces.parse(input, options); - } - return compile(input, options); + return mixed; }; -/** - * Expands a brace pattern into an array. This method is called by the - * main [braces](#braces) function when `options.expand` is true. Before - * using this method it's recommended that you read the [performance notes](#performance)) - * and advantages of using [.compile](#compile) instead. - * - * ```js - * const braces = require('braces'); - * console.log(braces.expand('a/{b,c}/d')); - * //=> ['a/b/d', 'a/c/d']; - * ``` - * @param {String} `pattern` Brace pattern - * @param {Object} `options` - * @return {Array} Returns an array of expanded values. - * @api public - */ +// On failure, `result.stdout|stderr|all` should contain the currently buffered stream +const getBufferedData = async (stream, streamPromise) => { + if (!stream) { + return; + } -braces.expand = (input, options = {}) => { - if (typeof input === 'string') { - input = braces.parse(input, options); - } + stream.destroy(); - let result = expand(input, options); + try { + return await streamPromise; + } catch (error) { + return error.bufferedData; + } +}; - // filter out empty strings if specified - if (options.noempty === true) { - result = result.filter(Boolean); - } +const getStreamPromise = (stream, {encoding, buffer, maxBuffer}) => { + if (!stream || !buffer) { + return; + } - // filter out duplicates if specified - if (options.nodupes === true) { - result = [...new Set(result)]; - } + if (encoding) { + return getStream(stream, {encoding, maxBuffer}); + } - return result; + return getStream.buffer(stream, {maxBuffer}); }; -/** - * Processes a brace pattern and returns either an expanded array - * (if `options.expand` is true), a highly optimized regex-compatible string. - * This method is called by the main [braces](#braces) function. - * - * ```js - * const braces = require('braces'); - * console.log(braces.create('user-{200..300}/project-{a,b,c}-{1..10}')) - * //=> 'user-(20[0-9]|2[1-9][0-9]|300)/project-(a|b|c)-([1-9]|10)' - * ``` - * @param {String} `pattern` Brace pattern - * @param {Object} `options` - * @return {Array} Returns an array of expanded values. - * @api public - */ +// Retrieve result of child process: exit code, signal, error, streams (stdout/stderr/all) +const getSpawnedResult = async ({stdout, stderr, all}, {encoding, buffer, maxBuffer}, processDone) => { + const stdoutPromise = getStreamPromise(stdout, {encoding, buffer, maxBuffer}); + const stderrPromise = getStreamPromise(stderr, {encoding, buffer, maxBuffer}); + const allPromise = getStreamPromise(all, {encoding, buffer, maxBuffer: maxBuffer * 2}); -braces.create = (input, options = {}) => { - if (input === '' || input.length < 3) { - return [input]; - } + try { + return await Promise.all([processDone, stdoutPromise, stderrPromise, allPromise]); + } catch (error) { + return Promise.all([ + {error, signal: error.signal, timedOut: error.timedOut}, + getBufferedData(stdout, stdoutPromise), + getBufferedData(stderr, stderrPromise), + getBufferedData(all, allPromise) + ]); + } +}; - return options.expand !== true - ? braces.compile(input, options) - : braces.expand(input, options); +const validateInputSync = ({input}) => { + if (isStream(input)) { + throw new TypeError('The `input` option cannot be a stream in sync mode'); + } }; -/** - * Expose "braces" - */ +module.exports = { + handleInput, + makeAllStream, + getSpawnedResult, + validateInputSync +}; -module.exports = braces; /***/ }), -/***/ 2714: +/***/ 2206: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; - - -const fill = __nccwpck_require__(6017); -const utils = __nccwpck_require__(9794); - -const compile = (ast, options = {}) => { - const walk = (node, parent = {}) => { - const invalidBlock = utils.isInvalidBrace(parent); - const invalidNode = node.invalid === true && options.escapeInvalid === true; - const invalid = invalidBlock === true || invalidNode === true; - const prefix = options.escapeInvalid === true ? '\\' : ''; - let output = ''; - - if (node.isOpen === true) { - return prefix + node.value; - } - if (node.isClose === true) { - console.log('node.isClose', prefix, node.value); - return prefix + node.value; +const taskManager = __nccwpck_require__(1437); +const async_1 = __nccwpck_require__(8483); +const stream_1 = __nccwpck_require__(7183); +const sync_1 = __nccwpck_require__(7904); +const settings_1 = __nccwpck_require__(7861); +const utils = __nccwpck_require__(4184); +async function FastGlob(source, options) { + assertPatternsInput(source); + const works = getWorks(source, async_1.default, options); + const result = await Promise.all(works); + return utils.array.flatten(result); +} +// https://github.com/typescript-eslint/typescript-eslint/issues/60 +// eslint-disable-next-line no-redeclare +(function (FastGlob) { + FastGlob.glob = FastGlob; + FastGlob.globSync = sync; + FastGlob.globStream = stream; + FastGlob.async = FastGlob; + function sync(source, options) { + assertPatternsInput(source); + const works = getWorks(source, sync_1.default, options); + return utils.array.flatten(works); } - - if (node.type === 'open') { - return invalid ? prefix + node.value : '('; + FastGlob.sync = sync; + function stream(source, options) { + assertPatternsInput(source); + const works = getWorks(source, stream_1.default, options); + /** + * The stream returned by the provider cannot work with an asynchronous iterator. + * To support asynchronous iterators, regardless of the number of tasks, we always multiplex streams. + * This affects performance (+25%). I don't see best solution right now. + */ + return utils.stream.merge(works); } - - if (node.type === 'close') { - return invalid ? prefix + node.value : ')'; + FastGlob.stream = stream; + function generateTasks(source, options) { + assertPatternsInput(source); + const patterns = [].concat(source); + const settings = new settings_1.default(options); + return taskManager.generate(patterns, settings); } - - if (node.type === 'comma') { - return node.prev.type === 'comma' ? '' : invalid ? node.value : '|'; + FastGlob.generateTasks = generateTasks; + function isDynamicPattern(source, options) { + assertPatternsInput(source); + const settings = new settings_1.default(options); + return utils.pattern.isDynamicPattern(source, settings); } - - if (node.value) { - return node.value; + FastGlob.isDynamicPattern = isDynamicPattern; + function escapePath(source) { + assertPatternsInput(source); + return utils.path.escape(source); } - - if (node.nodes && node.ranges > 0) { - const args = utils.reduce(node.nodes); - const range = fill(...args, { ...options, wrap: false, toRegex: true, strictZeros: true }); - - if (range.length !== 0) { - return args.length > 1 && range.length > 1 ? `(${range})` : range; - } + FastGlob.escapePath = escapePath; + function convertPathToPattern(source) { + assertPatternsInput(source); + return utils.path.convertPathToPattern(source); } - - if (node.nodes) { - for (const child of node.nodes) { - output += walk(child, node); - } + FastGlob.convertPathToPattern = convertPathToPattern; + let posix; + (function (posix) { + function escapePath(source) { + assertPatternsInput(source); + return utils.path.escapePosixPath(source); + } + posix.escapePath = escapePath; + function convertPathToPattern(source) { + assertPatternsInput(source); + return utils.path.convertPosixPathToPattern(source); + } + posix.convertPathToPattern = convertPathToPattern; + })(posix = FastGlob.posix || (FastGlob.posix = {})); + let win32; + (function (win32) { + function escapePath(source) { + assertPatternsInput(source); + return utils.path.escapeWindowsPath(source); + } + win32.escapePath = escapePath; + function convertPathToPattern(source) { + assertPatternsInput(source); + return utils.path.convertWindowsPathToPattern(source); + } + win32.convertPathToPattern = convertPathToPattern; + })(win32 = FastGlob.win32 || (FastGlob.win32 = {})); +})(FastGlob || (FastGlob = {})); +function getWorks(source, _Provider, options) { + const patterns = [].concat(source); + const settings = new settings_1.default(options); + const tasks = taskManager.generate(patterns, settings); + const provider = new _Provider(settings); + return tasks.map(provider.read, provider); +} +function assertPatternsInput(input) { + const source = [].concat(input); + const isValidSource = source.every((item) => utils.string.isString(item) && !utils.string.isEmpty(item)); + if (!isValidSource) { + throw new TypeError('Patterns must be a string (non empty) or an array of strings'); } - - return output; - }; - - return walk(ast); -}; - -module.exports = compile; +} +module.exports = FastGlob; /***/ }), -/***/ 2426: -/***/ ((module) => { - -"use strict"; - - -module.exports = { - MAX_LENGTH: 10000, - - // Digits - CHAR_0: '0', /* 0 */ - CHAR_9: '9', /* 9 */ - - // Alphabet chars. - CHAR_UPPERCASE_A: 'A', /* A */ - CHAR_LOWERCASE_A: 'a', /* a */ - CHAR_UPPERCASE_Z: 'Z', /* Z */ - CHAR_LOWERCASE_Z: 'z', /* z */ - - CHAR_LEFT_PARENTHESES: '(', /* ( */ - CHAR_RIGHT_PARENTHESES: ')', /* ) */ +/***/ 1437: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - CHAR_ASTERISK: '*', /* * */ - // Non-alphabetic chars. - CHAR_AMPERSAND: '&', /* & */ - CHAR_AT: '@', /* @ */ - CHAR_BACKSLASH: '\\', /* \ */ - CHAR_BACKTICK: '`', /* ` */ - CHAR_CARRIAGE_RETURN: '\r', /* \r */ - CHAR_CIRCUMFLEX_ACCENT: '^', /* ^ */ - CHAR_COLON: ':', /* : */ - CHAR_COMMA: ',', /* , */ - CHAR_DOLLAR: '$', /* . */ - CHAR_DOT: '.', /* . */ - CHAR_DOUBLE_QUOTE: '"', /* " */ - CHAR_EQUAL: '=', /* = */ - CHAR_EXCLAMATION_MARK: '!', /* ! */ - CHAR_FORM_FEED: '\f', /* \f */ - CHAR_FORWARD_SLASH: '/', /* / */ - CHAR_HASH: '#', /* # */ - CHAR_HYPHEN_MINUS: '-', /* - */ - CHAR_LEFT_ANGLE_BRACKET: '<', /* < */ - CHAR_LEFT_CURLY_BRACE: '{', /* { */ - CHAR_LEFT_SQUARE_BRACKET: '[', /* [ */ - CHAR_LINE_FEED: '\n', /* \n */ - CHAR_NO_BREAK_SPACE: '\u00A0', /* \u00A0 */ - CHAR_PERCENT: '%', /* % */ - CHAR_PLUS: '+', /* + */ - CHAR_QUESTION_MARK: '?', /* ? */ - CHAR_RIGHT_ANGLE_BRACKET: '>', /* > */ - CHAR_RIGHT_CURLY_BRACE: '}', /* } */ - CHAR_RIGHT_SQUARE_BRACKET: ']', /* ] */ - CHAR_SEMICOLON: ';', /* ; */ - CHAR_SINGLE_QUOTE: '\'', /* ' */ - CHAR_SPACE: ' ', /* */ - CHAR_TAB: '\t', /* \t */ - CHAR_UNDERSCORE: '_', /* _ */ - CHAR_VERTICAL_LINE: '|', /* | */ - CHAR_ZERO_WIDTH_NOBREAK_SPACE: '\uFEFF' /* \uFEFF */ -}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.convertPatternGroupToTask = exports.convertPatternGroupsToTasks = exports.groupPatternsByBaseDirectory = exports.getNegativePatternsAsPositive = exports.getPositivePatterns = exports.convertPatternsToTasks = exports.generate = void 0; +const utils = __nccwpck_require__(4184); +function generate(input, settings) { + const patterns = processPatterns(input, settings); + const ignore = processPatterns(settings.ignore, settings); + const positivePatterns = getPositivePatterns(patterns); + const negativePatterns = getNegativePatternsAsPositive(patterns, ignore); + const staticPatterns = positivePatterns.filter((pattern) => utils.pattern.isStaticPattern(pattern, settings)); + const dynamicPatterns = positivePatterns.filter((pattern) => utils.pattern.isDynamicPattern(pattern, settings)); + const staticTasks = convertPatternsToTasks(staticPatterns, negativePatterns, /* dynamic */ false); + const dynamicTasks = convertPatternsToTasks(dynamicPatterns, negativePatterns, /* dynamic */ true); + return staticTasks.concat(dynamicTasks); +} +exports.generate = generate; +function processPatterns(input, settings) { + let patterns = input; + /** + * The original pattern like `{,*,**,a/*}` can lead to problems checking the depth when matching entry + * and some problems with the micromatch package (see fast-glob issues: #365, #394). + * + * To solve this problem, we expand all patterns containing brace expansion. This can lead to a slight slowdown + * in matching in the case of a large set of patterns after expansion. + */ + if (settings.braceExpansion) { + patterns = utils.pattern.expandPatternsWithBraceExpansion(patterns); + } + /** + * If the `baseNameMatch` option is enabled, we must add globstar to patterns, so that they can be used + * at any nesting level. + * + * We do this here, because otherwise we have to complicate the filtering logic. For example, we need to change + * the pattern in the filter before creating a regular expression. There is no need to change the patterns + * in the application. Only on the input. + */ + if (settings.baseNameMatch) { + patterns = patterns.map((pattern) => pattern.includes('/') ? pattern : `**/${pattern}`); + } + /** + * This method also removes duplicate slashes that may have been in the pattern or formed as a result of expansion. + */ + return patterns.map((pattern) => utils.pattern.removeDuplicateSlashes(pattern)); +} +/** + * Returns tasks grouped by basic pattern directories. + * + * Patterns that can be found inside (`./`) and outside (`../`) the current directory are handled separately. + * This is necessary because directory traversal starts at the base directory and goes deeper. + */ +function convertPatternsToTasks(positive, negative, dynamic) { + const tasks = []; + const patternsOutsideCurrentDirectory = utils.pattern.getPatternsOutsideCurrentDirectory(positive); + const patternsInsideCurrentDirectory = utils.pattern.getPatternsInsideCurrentDirectory(positive); + const outsideCurrentDirectoryGroup = groupPatternsByBaseDirectory(patternsOutsideCurrentDirectory); + const insideCurrentDirectoryGroup = groupPatternsByBaseDirectory(patternsInsideCurrentDirectory); + tasks.push(...convertPatternGroupsToTasks(outsideCurrentDirectoryGroup, negative, dynamic)); + /* + * For the sake of reducing future accesses to the file system, we merge all tasks within the current directory + * into a global task, if at least one pattern refers to the root (`.`). In this case, the global task covers the rest. + */ + if ('.' in insideCurrentDirectoryGroup) { + tasks.push(convertPatternGroupToTask('.', patternsInsideCurrentDirectory, negative, dynamic)); + } + else { + tasks.push(...convertPatternGroupsToTasks(insideCurrentDirectoryGroup, negative, dynamic)); + } + return tasks; +} +exports.convertPatternsToTasks = convertPatternsToTasks; +function getPositivePatterns(patterns) { + return utils.pattern.getPositivePatterns(patterns); +} +exports.getPositivePatterns = getPositivePatterns; +function getNegativePatternsAsPositive(patterns, ignore) { + const negative = utils.pattern.getNegativePatterns(patterns).concat(ignore); + const positive = negative.map(utils.pattern.convertToPositivePattern); + return positive; +} +exports.getNegativePatternsAsPositive = getNegativePatternsAsPositive; +function groupPatternsByBaseDirectory(patterns) { + const group = {}; + return patterns.reduce((collection, pattern) => { + const base = utils.pattern.getBaseDirectory(pattern); + if (base in collection) { + collection[base].push(pattern); + } + else { + collection[base] = [pattern]; + } + return collection; + }, group); +} +exports.groupPatternsByBaseDirectory = groupPatternsByBaseDirectory; +function convertPatternGroupsToTasks(positive, negative, dynamic) { + return Object.keys(positive).map((base) => { + return convertPatternGroupToTask(base, positive[base], negative, dynamic); + }); +} +exports.convertPatternGroupsToTasks = convertPatternGroupsToTasks; +function convertPatternGroupToTask(base, positive, negative, dynamic) { + return { + dynamic, + positive, + negative, + base, + patterns: [].concat(positive, negative.map(utils.pattern.convertToNegativePattern)) + }; +} +exports.convertPatternGroupToTask = convertPatternGroupToTask; /***/ }), -/***/ 539: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +/***/ 8483: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { -"use strict"; +Object.defineProperty(exports, "__esModule", ({ value: true })); +const async_1 = __nccwpck_require__(3449); +const provider_1 = __nccwpck_require__(8118); +class ProviderAsync extends provider_1.default { + constructor() { + super(...arguments); + this._reader = new async_1.default(this._settings); + } + async read(task) { + const root = this._getRootDirectory(task); + const options = this._getReaderOptions(task); + const entries = await this.api(root, task, options); + return entries.map((entry) => options.transform(entry)); + } + api(root, task, options) { + if (task.dynamic) { + return this._reader.dynamic(root, options); + } + return this._reader.static(task.patterns, options); + } +} +exports["default"] = ProviderAsync; -const fill = __nccwpck_require__(6017); -const stringify = __nccwpck_require__(2670); -const utils = __nccwpck_require__(9794); -const append = (queue = '', stash = '', enclose = false) => { - const result = []; +/***/ }), - queue = [].concat(queue); - stash = [].concat(stash); +/***/ 165: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - if (!stash.length) return queue; - if (!queue.length) { - return enclose ? utils.flatten(stash).map(ele => `{${ele}}`) : stash; - } - for (const item of queue) { - if (Array.isArray(item)) { - for (const value of item) { - result.push(append(value, stash, enclose)); - } - } else { - for (let ele of stash) { - if (enclose === true && typeof ele === 'string') ele = `{${ele}}`; - result.push(Array.isArray(ele) ? append(item, ele, enclose) : item + ele); - } +Object.defineProperty(exports, "__esModule", ({ value: true })); +const utils = __nccwpck_require__(4184); +const partial_1 = __nccwpck_require__(3702); +class DeepFilter { + constructor(_settings, _micromatchOptions) { + this._settings = _settings; + this._micromatchOptions = _micromatchOptions; } - } - return utils.flatten(result); -}; - -const expand = (ast, options = {}) => { - const rangeLimit = options.rangeLimit === undefined ? 1000 : options.rangeLimit; - - const walk = (node, parent = {}) => { - node.queue = []; - - let p = parent; - let q = parent.queue; - - while (p.type !== 'brace' && p.type !== 'root' && p.parent) { - p = p.parent; - q = p.queue; + getFilter(basePath, positive, negative) { + const matcher = this._getMatcher(positive); + const negativeRe = this._getNegativePatternsRe(negative); + return (entry) => this._filter(basePath, entry, matcher, negativeRe); } - - if (node.invalid || node.dollar) { - q.push(append(q.pop(), stringify(node, options))); - return; + _getMatcher(patterns) { + return new partial_1.default(patterns, this._settings, this._micromatchOptions); } - - if (node.type === 'brace' && node.invalid !== true && node.nodes.length === 2) { - q.push(append(q.pop(), ['{}'])); - return; + _getNegativePatternsRe(patterns) { + const affectDepthOfReadingPatterns = patterns.filter(utils.pattern.isAffectDepthOfReadingPattern); + return utils.pattern.convertPatternsToRe(affectDepthOfReadingPatterns, this._micromatchOptions); } + _filter(basePath, entry, matcher, negativeRe) { + if (this._isSkippedByDeep(basePath, entry.path)) { + return false; + } + if (this._isSkippedSymbolicLink(entry)) { + return false; + } + const filepath = utils.path.removeLeadingDotSegment(entry.path); + if (this._isSkippedByPositivePatterns(filepath, matcher)) { + return false; + } + return this._isSkippedByNegativePatterns(filepath, negativeRe); + } + _isSkippedByDeep(basePath, entryPath) { + /** + * Avoid unnecessary depth calculations when it doesn't matter. + */ + if (this._settings.deep === Infinity) { + return false; + } + return this._getEntryLevel(basePath, entryPath) >= this._settings.deep; + } + _getEntryLevel(basePath, entryPath) { + const entryPathDepth = entryPath.split('/').length; + if (basePath === '') { + return entryPathDepth; + } + const basePathDepth = basePath.split('/').length; + return entryPathDepth - basePathDepth; + } + _isSkippedSymbolicLink(entry) { + return !this._settings.followSymbolicLinks && entry.dirent.isSymbolicLink(); + } + _isSkippedByPositivePatterns(entryPath, matcher) { + return !this._settings.baseNameMatch && !matcher.match(entryPath); + } + _isSkippedByNegativePatterns(entryPath, patternsRe) { + return !utils.pattern.matchAny(entryPath, patternsRe); + } +} +exports["default"] = DeepFilter; - if (node.nodes && node.ranges > 0) { - const args = utils.reduce(node.nodes); - - if (utils.exceedsLimit(...args, options.step, rangeLimit)) { - throw new RangeError('expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.'); - } - let range = fill(...args, options); - if (range.length === 0) { - range = stringify(node, options); - } +/***/ }), - q.push(append(q.pop(), range)); - node.nodes = []; - return; - } +/***/ 4327: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - const enclose = utils.encloseBrace(node); - let queue = node.queue; - let block = node; - while (block.type !== 'brace' && block.type !== 'root' && block.parent) { - block = block.parent; - queue = block.queue; +Object.defineProperty(exports, "__esModule", ({ value: true })); +const utils = __nccwpck_require__(4184); +class EntryFilter { + constructor(_settings, _micromatchOptions) { + this._settings = _settings; + this._micromatchOptions = _micromatchOptions; + this.index = new Map(); + } + getFilter(positive, negative) { + const [absoluteNegative, relativeNegative] = utils.pattern.partitionAbsoluteAndRelative(negative); + const patterns = { + positive: { + all: utils.pattern.convertPatternsToRe(positive, this._micromatchOptions) + }, + negative: { + absolute: utils.pattern.convertPatternsToRe(absoluteNegative, Object.assign(Object.assign({}, this._micromatchOptions), { dot: true })), + relative: utils.pattern.convertPatternsToRe(relativeNegative, Object.assign(Object.assign({}, this._micromatchOptions), { dot: true })) + } + }; + return (entry) => this._filter(entry, patterns); + } + _filter(entry, patterns) { + const filepath = utils.path.removeLeadingDotSegment(entry.path); + if (this._settings.unique && this._isDuplicateEntry(filepath)) { + return false; + } + if (this._onlyFileFilter(entry) || this._onlyDirectoryFilter(entry)) { + return false; + } + const isMatched = this._isMatchToPatternsSet(filepath, patterns, entry.dirent.isDirectory()); + if (this._settings.unique && isMatched) { + this._createIndexRecord(filepath); + } + return isMatched; + } + _isDuplicateEntry(filepath) { + return this.index.has(filepath); + } + _createIndexRecord(filepath) { + this.index.set(filepath, undefined); + } + _onlyFileFilter(entry) { + return this._settings.onlyFiles && !entry.dirent.isFile(); + } + _onlyDirectoryFilter(entry) { + return this._settings.onlyDirectories && !entry.dirent.isDirectory(); + } + _isMatchToPatternsSet(filepath, patterns, isDirectory) { + const isMatched = this._isMatchToPatterns(filepath, patterns.positive.all, isDirectory); + if (!isMatched) { + return false; + } + const isMatchedByRelativeNegative = this._isMatchToPatterns(filepath, patterns.negative.relative, isDirectory); + if (isMatchedByRelativeNegative) { + return false; + } + const isMatchedByAbsoluteNegative = this._isMatchToAbsoluteNegative(filepath, patterns.negative.absolute, isDirectory); + if (isMatchedByAbsoluteNegative) { + return false; + } + return true; + } + _isMatchToAbsoluteNegative(filepath, patternsRe, isDirectory) { + if (patternsRe.length === 0) { + return false; + } + const fullpath = utils.path.makeAbsolute(this._settings.cwd, filepath); + return this._isMatchToPatterns(fullpath, patternsRe, isDirectory); + } + _isMatchToPatterns(filepath, patternsRe, isDirectory) { + if (patternsRe.length === 0) { + return false; + } + // Trying to match files and directories by patterns. + const isMatched = utils.pattern.matchAny(filepath, patternsRe); + // A pattern with a trailling slash can be used for directory matching. + // To apply such pattern, we need to add a tralling slash to the path. + if (!isMatched && isDirectory) { + return utils.pattern.matchAny(filepath + '/', patternsRe); + } + return isMatched; } +} +exports["default"] = EntryFilter; - for (let i = 0; i < node.nodes.length; i++) { - const child = node.nodes[i]; - if (child.type === 'comma' && node.type === 'brace') { - if (i === 1) queue.push(''); - queue.push(''); - continue; - } +/***/ }), - if (child.type === 'close') { - q.push(append(q.pop(), queue, enclose)); - continue; - } +/***/ 4253: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - if (child.value && child.type !== 'open') { - queue.push(append(queue.pop(), child.value)); - continue; - } - if (child.nodes) { - walk(child, node); - } +Object.defineProperty(exports, "__esModule", ({ value: true })); +const utils = __nccwpck_require__(4184); +class ErrorFilter { + constructor(_settings) { + this._settings = _settings; } - - return queue; - }; - - return utils.flatten(walk(ast)); -}; - -module.exports = expand; + getFilter() { + return (error) => this._isNonFatalError(error); + } + _isNonFatalError(error) { + return utils.errno.isEnoentCodeError(error) || this._settings.suppressErrors; + } +} +exports["default"] = ErrorFilter; /***/ }), -/***/ 5920: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -"use strict"; +/***/ 2417: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { -const stringify = __nccwpck_require__(2670); +Object.defineProperty(exports, "__esModule", ({ value: true })); +const utils = __nccwpck_require__(4184); +class Matcher { + constructor(_patterns, _settings, _micromatchOptions) { + this._patterns = _patterns; + this._settings = _settings; + this._micromatchOptions = _micromatchOptions; + this._storage = []; + this._fillStorage(); + } + _fillStorage() { + for (const pattern of this._patterns) { + const segments = this._getPatternSegments(pattern); + const sections = this._splitSegmentsIntoSections(segments); + this._storage.push({ + complete: sections.length <= 1, + pattern, + segments, + sections + }); + } + } + _getPatternSegments(pattern) { + const parts = utils.pattern.getPatternParts(pattern, this._micromatchOptions); + return parts.map((part) => { + const dynamic = utils.pattern.isDynamicPattern(part, this._settings); + if (!dynamic) { + return { + dynamic: false, + pattern: part + }; + } + return { + dynamic: true, + pattern: part, + patternRe: utils.pattern.makeRe(part, this._micromatchOptions) + }; + }); + } + _splitSegmentsIntoSections(segments) { + return utils.array.splitWhen(segments, (segment) => segment.dynamic && utils.pattern.hasGlobStar(segment.pattern)); + } +} +exports["default"] = Matcher; -/** - * Constants - */ -const { - MAX_LENGTH, - CHAR_BACKSLASH, /* \ */ - CHAR_BACKTICK, /* ` */ - CHAR_COMMA, /* , */ - CHAR_DOT, /* . */ - CHAR_LEFT_PARENTHESES, /* ( */ - CHAR_RIGHT_PARENTHESES, /* ) */ - CHAR_LEFT_CURLY_BRACE, /* { */ - CHAR_RIGHT_CURLY_BRACE, /* } */ - CHAR_LEFT_SQUARE_BRACKET, /* [ */ - CHAR_RIGHT_SQUARE_BRACKET, /* ] */ - CHAR_DOUBLE_QUOTE, /* " */ - CHAR_SINGLE_QUOTE, /* ' */ - CHAR_NO_BREAK_SPACE, - CHAR_ZERO_WIDTH_NOBREAK_SPACE -} = __nccwpck_require__(2426); +/***/ }), -/** - * parse - */ +/***/ 3702: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { -const parse = (input, options = {}) => { - if (typeof input !== 'string') { - throw new TypeError('Expected a string'); - } - const opts = options || {}; - const max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH; - if (input.length > max) { - throw new SyntaxError(`Input length (${input.length}), exceeds max characters (${max})`); - } +Object.defineProperty(exports, "__esModule", ({ value: true })); +const matcher_1 = __nccwpck_require__(2417); +class PartialMatcher extends matcher_1.default { + match(filepath) { + const parts = filepath.split('/'); + const levels = parts.length; + const patterns = this._storage.filter((info) => !info.complete || info.segments.length > levels); + for (const pattern of patterns) { + const section = pattern.sections[0]; + /** + * In this case, the pattern has a globstar and we must read all directories unconditionally, + * but only if the level has reached the end of the first group. + * + * fixtures/{a,b}/** + * ^ true/false ^ always true + */ + if (!pattern.complete && levels > section.length) { + return true; + } + const match = parts.every((part, index) => { + const segment = pattern.segments[index]; + if (segment.dynamic && segment.patternRe.test(part)) { + return true; + } + if (!segment.dynamic && segment.pattern === part) { + return true; + } + return false; + }); + if (match) { + return true; + } + } + return false; + } +} +exports["default"] = PartialMatcher; - const ast = { type: 'root', input, nodes: [] }; - const stack = [ast]; - let block = ast; - let prev = ast; - let brackets = 0; - const length = input.length; - let index = 0; - let depth = 0; - let value; - /** - * Helpers - */ +/***/ }), - const advance = () => input[index++]; - const push = node => { - if (node.type === 'text' && prev.type === 'dot') { - prev.type = 'text'; - } +/***/ 8118: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - if (prev && prev.type === 'text' && node.type === 'text') { - prev.value += node.value; - return; - } - block.nodes.push(node); - node.parent = block; - node.prev = prev; - prev = node; - return node; - }; - - push({ type: 'bos' }); - - while (index < length) { - block = stack[stack.length - 1]; - value = advance(); - - /** - * Invalid chars - */ - - if (value === CHAR_ZERO_WIDTH_NOBREAK_SPACE || value === CHAR_NO_BREAK_SPACE) { - continue; +Object.defineProperty(exports, "__esModule", ({ value: true })); +const path = __nccwpck_require__(6928); +const deep_1 = __nccwpck_require__(165); +const entry_1 = __nccwpck_require__(4327); +const error_1 = __nccwpck_require__(4253); +const entry_2 = __nccwpck_require__(9568); +class Provider { + constructor(_settings) { + this._settings = _settings; + this.errorFilter = new error_1.default(this._settings); + this.entryFilter = new entry_1.default(this._settings, this._getMicromatchOptions()); + this.deepFilter = new deep_1.default(this._settings, this._getMicromatchOptions()); + this.entryTransformer = new entry_2.default(this._settings); } - - /** - * Escaped chars - */ - - if (value === CHAR_BACKSLASH) { - push({ type: 'text', value: (options.keepEscaping ? value : '') + advance() }); - continue; + _getRootDirectory(task) { + return path.resolve(this._settings.cwd, task.base); } - - /** - * Right square bracket (literal): ']' - */ - - if (value === CHAR_RIGHT_SQUARE_BRACKET) { - push({ type: 'text', value: '\\' + value }); - continue; + _getReaderOptions(task) { + const basePath = task.base === '.' ? '' : task.base; + return { + basePath, + pathSegmentSeparator: '/', + concurrency: this._settings.concurrency, + deepFilter: this.deepFilter.getFilter(basePath, task.positive, task.negative), + entryFilter: this.entryFilter.getFilter(task.positive, task.negative), + errorFilter: this.errorFilter.getFilter(), + followSymbolicLinks: this._settings.followSymbolicLinks, + fs: this._settings.fs, + stats: this._settings.stats, + throwErrorOnBrokenSymbolicLink: this._settings.throwErrorOnBrokenSymbolicLink, + transform: this.entryTransformer.getTransformer() + }; } + _getMicromatchOptions() { + return { + dot: this._settings.dot, + matchBase: this._settings.baseNameMatch, + nobrace: !this._settings.braceExpansion, + nocase: !this._settings.caseSensitiveMatch, + noext: !this._settings.extglob, + noglobstar: !this._settings.globstar, + posix: true, + strictSlashes: false + }; + } +} +exports["default"] = Provider; - /** - * Left square bracket: '[' - */ - - if (value === CHAR_LEFT_SQUARE_BRACKET) { - brackets++; - - let next; - - while (index < length && (next = advance())) { - value += next; - - if (next === CHAR_LEFT_SQUARE_BRACKET) { - brackets++; - continue; - } - if (next === CHAR_BACKSLASH) { - value += advance(); - continue; - } +/***/ }), - if (next === CHAR_RIGHT_SQUARE_BRACKET) { - brackets--; +/***/ 7183: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - if (brackets === 0) { - break; - } - } - } - push({ type: 'text', value }); - continue; +Object.defineProperty(exports, "__esModule", ({ value: true })); +const stream_1 = __nccwpck_require__(2203); +const stream_2 = __nccwpck_require__(5805); +const provider_1 = __nccwpck_require__(8118); +class ProviderStream extends provider_1.default { + constructor() { + super(...arguments); + this._reader = new stream_2.default(this._settings); } - - /** - * Parentheses - */ - - if (value === CHAR_LEFT_PARENTHESES) { - block = push({ type: 'paren', nodes: [] }); - stack.push(block); - push({ type: 'text', value }); - continue; + read(task) { + const root = this._getRootDirectory(task); + const options = this._getReaderOptions(task); + const source = this.api(root, task, options); + const destination = new stream_1.Readable({ objectMode: true, read: () => { } }); + source + .once('error', (error) => destination.emit('error', error)) + .on('data', (entry) => destination.emit('data', options.transform(entry))) + .once('end', () => destination.emit('end')); + destination + .once('close', () => source.destroy()); + return destination; } - - if (value === CHAR_RIGHT_PARENTHESES) { - if (block.type !== 'paren') { - push({ type: 'text', value }); - continue; - } - block = stack.pop(); - push({ type: 'text', value }); - block = stack[stack.length - 1]; - continue; + api(root, task, options) { + if (task.dynamic) { + return this._reader.dynamic(root, options); + } + return this._reader.static(task.patterns, options); } +} +exports["default"] = ProviderStream; - /** - * Quotes: '|"|` - */ - if (value === CHAR_DOUBLE_QUOTE || value === CHAR_SINGLE_QUOTE || value === CHAR_BACKTICK) { - const open = value; - let next; +/***/ }), - if (options.keepQuotes !== true) { - value = ''; - } +/***/ 7904: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - while (index < length && (next = advance())) { - if (next === CHAR_BACKSLASH) { - value += next + advance(); - continue; - } - if (next === open) { - if (options.keepQuotes === true) value += next; - break; +Object.defineProperty(exports, "__esModule", ({ value: true })); +const sync_1 = __nccwpck_require__(466); +const provider_1 = __nccwpck_require__(8118); +class ProviderSync extends provider_1.default { + constructor() { + super(...arguments); + this._reader = new sync_1.default(this._settings); + } + read(task) { + const root = this._getRootDirectory(task); + const options = this._getReaderOptions(task); + const entries = this.api(root, task, options); + return entries.map(options.transform); + } + api(root, task, options) { + if (task.dynamic) { + return this._reader.dynamic(root, options); } - - value += next; - } - - push({ type: 'text', value }); - continue; + return this._reader.static(task.patterns, options); } +} +exports["default"] = ProviderSync; - /** - * Left curly brace: '{' - */ - if (value === CHAR_LEFT_CURLY_BRACE) { - depth++; +/***/ }), - const dollar = prev.value && prev.value.slice(-1) === '$' || block.dollar === true; - const brace = { - type: 'brace', - open: true, - close: false, - dollar, - depth, - commas: 0, - ranges: 0, - nodes: [] - }; +/***/ 9568: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - block = push(brace); - stack.push(block); - push({ type: 'open', value }); - continue; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +const utils = __nccwpck_require__(4184); +class EntryTransformer { + constructor(_settings) { + this._settings = _settings; + } + getTransformer() { + return (entry) => this._transform(entry); + } + _transform(entry) { + let filepath = entry.path; + if (this._settings.absolute) { + filepath = utils.path.makeAbsolute(this._settings.cwd, filepath); + filepath = utils.path.unixify(filepath); + } + if (this._settings.markDirectories && entry.dirent.isDirectory()) { + filepath += '/'; + } + if (!this._settings.objectMode) { + return filepath; + } + return Object.assign(Object.assign({}, entry), { path: filepath }); } +} +exports["default"] = EntryTransformer; - /** - * Right curly brace: '}' - */ - if (value === CHAR_RIGHT_CURLY_BRACE) { - if (block.type !== 'brace') { - push({ type: 'text', value }); - continue; - } +/***/ }), - const type = 'close'; - block = stack.pop(); - block.close = true; +/***/ 3449: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - push({ type, value }); - depth--; - block = stack[stack.length - 1]; - continue; +Object.defineProperty(exports, "__esModule", ({ value: true })); +const fsWalk = __nccwpck_require__(2552); +const reader_1 = __nccwpck_require__(3502); +const stream_1 = __nccwpck_require__(5805); +class ReaderAsync extends reader_1.default { + constructor() { + super(...arguments); + this._walkAsync = fsWalk.walk; + this._readerStream = new stream_1.default(this._settings); } - - /** - * Comma: ',' - */ - - if (value === CHAR_COMMA && depth > 0) { - if (block.ranges > 0) { - block.ranges = 0; - const open = block.nodes.shift(); - block.nodes = [open, { type: 'text', value: stringify(block) }]; - } - - push({ type: 'comma', value }); - block.commas++; - continue; + dynamic(root, options) { + return new Promise((resolve, reject) => { + this._walkAsync(root, options, (error, entries) => { + if (error === null) { + resolve(entries); + } + else { + reject(error); + } + }); + }); + } + async static(patterns, options) { + const entries = []; + const stream = this._readerStream.static(patterns, options); + // After #235, replace it with an asynchronous iterator. + return new Promise((resolve, reject) => { + stream.once('error', reject); + stream.on('data', (entry) => entries.push(entry)); + stream.once('end', () => resolve(entries)); + }); } +} +exports["default"] = ReaderAsync; - /** - * Dot: '.' - */ - if (value === CHAR_DOT && depth > 0 && block.commas === 0) { - const siblings = block.nodes; +/***/ }), - if (depth === 0 || siblings.length === 0) { - push({ type: 'text', value }); - continue; - } +/***/ 3502: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - if (prev.type === 'dot') { - block.range = []; - prev.value += value; - prev.type = 'range'; - if (block.nodes.length !== 3 && block.nodes.length !== 5) { - block.invalid = true; - block.ranges = 0; - prev.type = 'text'; - continue; +Object.defineProperty(exports, "__esModule", ({ value: true })); +const path = __nccwpck_require__(6928); +const fsStat = __nccwpck_require__(3824); +const utils = __nccwpck_require__(4184); +class Reader { + constructor(_settings) { + this._settings = _settings; + this._fsStatSettings = new fsStat.Settings({ + followSymbolicLink: this._settings.followSymbolicLinks, + fs: this._settings.fs, + throwErrorOnBrokenSymbolicLink: this._settings.followSymbolicLinks + }); + } + _getFullEntryPath(filepath) { + return path.resolve(this._settings.cwd, filepath); + } + _makeEntry(stats, pattern) { + const entry = { + name: pattern, + path: pattern, + dirent: utils.fs.createDirentFromStats(pattern, stats) + }; + if (this._settings.stats) { + entry.stats = stats; } - - block.ranges++; - block.args = []; - continue; - } - - if (prev.type === 'range') { - siblings.pop(); - - const before = siblings[siblings.length - 1]; - before.value += prev.value + value; - prev = before; - block.ranges--; - continue; - } - - push({ type: 'dot', value }); - continue; + return entry; + } + _isFatalError(error) { + return !utils.errno.isEnoentCodeError(error) && !this._settings.suppressErrors; } +} +exports["default"] = Reader; - /** - * Text - */ - push({ type: 'text', value }); - } +/***/ }), - // Mark imbalanced braces and brackets as invalid - do { - block = stack.pop(); +/***/ 5805: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - if (block.type !== 'root') { - block.nodes.forEach(node => { - if (!node.nodes) { - if (node.type === 'open') node.isOpen = true; - if (node.type === 'close') node.isClose = true; - if (!node.nodes) node.type = 'text'; - node.invalid = true; - } - }); - // get the location of the block on parent.nodes (block's siblings) - const parent = stack[stack.length - 1]; - const index = parent.nodes.indexOf(block); - // replace the (invalid) block with it's nodes - parent.nodes.splice(index, 1, ...block.nodes); +Object.defineProperty(exports, "__esModule", ({ value: true })); +const stream_1 = __nccwpck_require__(2203); +const fsStat = __nccwpck_require__(3824); +const fsWalk = __nccwpck_require__(2552); +const reader_1 = __nccwpck_require__(3502); +class ReaderStream extends reader_1.default { + constructor() { + super(...arguments); + this._walkStream = fsWalk.walkStream; + this._stat = fsStat.stat; } - } while (stack.length > 0); - - push({ type: 'eos' }); - return ast; -}; - -module.exports = parse; + dynamic(root, options) { + return this._walkStream(root, options); + } + static(patterns, options) { + const filepaths = patterns.map(this._getFullEntryPath, this); + const stream = new stream_1.PassThrough({ objectMode: true }); + stream._write = (index, _enc, done) => { + return this._getEntry(filepaths[index], patterns[index], options) + .then((entry) => { + if (entry !== null && options.entryFilter(entry)) { + stream.push(entry); + } + if (index === filepaths.length - 1) { + stream.end(); + } + done(); + }) + .catch(done); + }; + for (let i = 0; i < filepaths.length; i++) { + stream.write(i); + } + return stream; + } + _getEntry(filepath, pattern, options) { + return this._getStat(filepath) + .then((stats) => this._makeEntry(stats, pattern)) + .catch((error) => { + if (options.errorFilter(error)) { + return null; + } + throw error; + }); + } + _getStat(filepath) { + return new Promise((resolve, reject) => { + this._stat(filepath, this._fsStatSettings, (error, stats) => { + return error === null ? resolve(stats) : reject(error); + }); + }); + } +} +exports["default"] = ReaderStream; /***/ }), -/***/ 2670: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +/***/ 466: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { -"use strict"; +Object.defineProperty(exports, "__esModule", ({ value: true })); +const fsStat = __nccwpck_require__(3824); +const fsWalk = __nccwpck_require__(2552); +const reader_1 = __nccwpck_require__(3502); +class ReaderSync extends reader_1.default { + constructor() { + super(...arguments); + this._walkSync = fsWalk.walkSync; + this._statSync = fsStat.statSync; + } + dynamic(root, options) { + return this._walkSync(root, options); + } + static(patterns, options) { + const entries = []; + for (const pattern of patterns) { + const filepath = this._getFullEntryPath(pattern); + const entry = this._getEntry(filepath, pattern, options); + if (entry === null || !options.entryFilter(entry)) { + continue; + } + entries.push(entry); + } + return entries; + } + _getEntry(filepath, pattern, options) { + try { + const stats = this._getStat(filepath); + return this._makeEntry(stats, pattern); + } + catch (error) { + if (options.errorFilter(error)) { + return null; + } + throw error; + } + } + _getStat(filepath) { + return this._statSync(filepath, this._fsStatSettings); + } +} +exports["default"] = ReaderSync; -const utils = __nccwpck_require__(9794); -module.exports = (ast, options = {}) => { - const stringify = (node, parent = {}) => { - const invalidBlock = options.escapeInvalid && utils.isInvalidBrace(parent); - const invalidNode = node.invalid === true && options.escapeInvalid === true; - let output = ''; +/***/ }), - if (node.value) { - if ((invalidBlock || invalidNode) && utils.isOpenOrClose(node)) { - return '\\' + node.value; - } - return node.value; - } +/***/ 7861: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - if (node.value) { - return node.value; - } - - if (node.nodes) { - for (const child of node.nodes) { - output += stringify(child); - } - } - return output; - }; - - return stringify(ast); -}; - - - -/***/ }), - -/***/ 9794: -/***/ ((__unused_webpack_module, exports) => { - -"use strict"; - - -exports.isInteger = num => { - if (typeof num === 'number') { - return Number.isInteger(num); - } - if (typeof num === 'string' && num.trim() !== '') { - return Number.isInteger(Number(num)); - } - return false; -}; - -/** - * Find a node of the given type - */ - -exports.find = (node, type) => node.nodes.find(node => node.type === type); +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.DEFAULT_FILE_SYSTEM_ADAPTER = void 0; +const fs = __nccwpck_require__(9896); +const os = __nccwpck_require__(857); /** - * Find a node of the given type + * The `os.cpus` method can return zero. We expect the number of cores to be greater than zero. + * https://github.com/nodejs/node/blob/7faeddf23a98c53896f8b574a6e66589e8fb1eb8/lib/os.js#L106-L107 */ - -exports.exceedsLimit = (min, max, step = 1, limit) => { - if (limit === false) return false; - if (!exports.isInteger(min) || !exports.isInteger(max)) return false; - return ((Number(max) - Number(min)) / Number(step)) >= limit; +const CPU_COUNT = Math.max(os.cpus().length, 1); +exports.DEFAULT_FILE_SYSTEM_ADAPTER = { + lstat: fs.lstat, + lstatSync: fs.lstatSync, + stat: fs.stat, + statSync: fs.statSync, + readdir: fs.readdir, + readdirSync: fs.readdirSync }; - -/** - * Escape the given node with '\\' before node.value - */ - -exports.escapeNode = (block, n = 0, type) => { - const node = block.nodes[n]; - if (!node) return; - - if ((type && node.type === type) || node.type === 'open' || node.type === 'close') { - if (node.escaped !== true) { - node.value = '\\' + node.value; - node.escaped = true; +class Settings { + constructor(_options = {}) { + this._options = _options; + this.absolute = this._getValue(this._options.absolute, false); + this.baseNameMatch = this._getValue(this._options.baseNameMatch, false); + this.braceExpansion = this._getValue(this._options.braceExpansion, true); + this.caseSensitiveMatch = this._getValue(this._options.caseSensitiveMatch, true); + this.concurrency = this._getValue(this._options.concurrency, CPU_COUNT); + this.cwd = this._getValue(this._options.cwd, process.cwd()); + this.deep = this._getValue(this._options.deep, Infinity); + this.dot = this._getValue(this._options.dot, false); + this.extglob = this._getValue(this._options.extglob, true); + this.followSymbolicLinks = this._getValue(this._options.followSymbolicLinks, true); + this.fs = this._getFileSystemMethods(this._options.fs); + this.globstar = this._getValue(this._options.globstar, true); + this.ignore = this._getValue(this._options.ignore, []); + this.markDirectories = this._getValue(this._options.markDirectories, false); + this.objectMode = this._getValue(this._options.objectMode, false); + this.onlyDirectories = this._getValue(this._options.onlyDirectories, false); + this.onlyFiles = this._getValue(this._options.onlyFiles, true); + this.stats = this._getValue(this._options.stats, false); + this.suppressErrors = this._getValue(this._options.suppressErrors, false); + this.throwErrorOnBrokenSymbolicLink = this._getValue(this._options.throwErrorOnBrokenSymbolicLink, false); + this.unique = this._getValue(this._options.unique, true); + if (this.onlyDirectories) { + this.onlyFiles = false; + } + if (this.stats) { + this.objectMode = true; + } + // Remove the cast to the array in the next major (#404). + this.ignore = [].concat(this.ignore); } - } -}; - -/** - * Returns true if the given brace node should be enclosed in literal braces - */ - -exports.encloseBrace = node => { - if (node.type !== 'brace') return false; - if ((node.commas >> 0 + node.ranges >> 0) === 0) { - node.invalid = true; - return true; - } - return false; -}; - -/** - * Returns true if a brace node is invalid. - */ - -exports.isInvalidBrace = block => { - if (block.type !== 'brace') return false; - if (block.invalid === true || block.dollar) return true; - if ((block.commas >> 0 + block.ranges >> 0) === 0) { - block.invalid = true; - return true; - } - if (block.open !== true || block.close !== true) { - block.invalid = true; - return true; - } - return false; -}; - -/** - * Returns true if a node is an open or close node - */ - -exports.isOpenOrClose = node => { - if (node.type === 'open' || node.type === 'close') { - return true; - } - return node.open === true || node.close === true; -}; - -/** - * Reduce an array of text nodes. - */ - -exports.reduce = nodes => nodes.reduce((acc, node) => { - if (node.type === 'text') acc.push(node.value); - if (node.type === 'range') node.type = 'text'; - return acc; -}, []); - -/** - * Flatten an array - */ - -exports.flatten = (...args) => { - const result = []; - - const flat = arr => { - for (let i = 0; i < arr.length; i++) { - const ele = arr[i]; - - if (Array.isArray(ele)) { - flat(ele); - continue; - } - - if (ele !== undefined) { - result.push(ele); - } + _getValue(option, value) { + return option === undefined ? value : option; } - return result; - }; - - flat(args); - return result; -}; + _getFileSystemMethods(methods = {}) { + return Object.assign(Object.assign({}, exports.DEFAULT_FILE_SYSTEM_ADAPTER), methods); + } +} +exports["default"] = Settings; /***/ }), -/***/ 8597: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -"use strict"; - - -const cp = __nccwpck_require__(5317); -const parse = __nccwpck_require__(3698); -const enoent = __nccwpck_require__(1344); - -function spawn(command, args, options) { - // Parse the arguments - const parsed = parse(command, args, options); - - // Spawn the child process - const spawned = cp.spawn(parsed.command, parsed.args, parsed.options); +/***/ 6161: +/***/ ((__unused_webpack_module, exports) => { - // Hook into child process "exit" event to emit an error if the command - // does not exists, see: https://github.com/IndigoUnited/node-cross-spawn/issues/16 - enoent.hookChildProcess(spawned, parsed); - return spawned; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.splitWhen = exports.flatten = void 0; +function flatten(items) { + return items.reduce((collection, item) => [].concat(collection, item), []); } - -function spawnSync(command, args, options) { - // Parse the arguments - const parsed = parse(command, args, options); - - // Spawn the child process - const result = cp.spawnSync(parsed.command, parsed.args, parsed.options); - - // Analyze if the command does not exist, see: https://github.com/IndigoUnited/node-cross-spawn/issues/16 - result.error = result.error || enoent.verifyENOENTSync(result.status, parsed); - +exports.flatten = flatten; +function splitWhen(items, predicate) { + const result = [[]]; + let groupIndex = 0; + for (const item of items) { + if (predicate(item)) { + groupIndex++; + result[groupIndex] = []; + } + else { + result[groupIndex].push(item); + } + } return result; } - -module.exports = spawn; -module.exports.spawn = spawn; -module.exports.sync = spawnSync; - -module.exports._parse = parse; -module.exports._enoent = enoent; +exports.splitWhen = splitWhen; /***/ }), -/***/ 1344: -/***/ ((module) => { - -"use strict"; - +/***/ 5832: +/***/ ((__unused_webpack_module, exports) => { -const isWin = process.platform === 'win32'; -function notFoundError(original, syscall) { - return Object.assign(new Error(`${syscall} ${original.command} ENOENT`), { - code: 'ENOENT', - errno: 'ENOENT', - syscall: `${syscall} ${original.command}`, - path: original.command, - spawnargs: original.args, - }); +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.isEnoentCodeError = void 0; +function isEnoentCodeError(error) { + return error.code === 'ENOENT'; } +exports.isEnoentCodeError = isEnoentCodeError; -function hookChildProcess(cp, parsed) { - if (!isWin) { - return; - } - - const originalEmit = cp.emit; - cp.emit = function (name, arg1) { - // If emitting "exit" event and exit code is 1, we need to check if - // the command exists and emit an "error" instead - // See https://github.com/IndigoUnited/node-cross-spawn/issues/16 - if (name === 'exit') { - const err = verifyENOENT(arg1, parsed); +/***/ }), - if (err) { - return originalEmit.call(cp, 'error', err); - } - } +/***/ 2169: +/***/ ((__unused_webpack_module, exports) => { - return originalEmit.apply(cp, arguments); // eslint-disable-line prefer-rest-params - }; -} -function verifyENOENT(status, parsed) { - if (isWin && status === 1 && !parsed.file) { - return notFoundError(parsed.original, 'spawn'); +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.createDirentFromStats = void 0; +class DirentFromStats { + constructor(name, stats) { + this.name = name; + this.isBlockDevice = stats.isBlockDevice.bind(stats); + this.isCharacterDevice = stats.isCharacterDevice.bind(stats); + this.isDirectory = stats.isDirectory.bind(stats); + this.isFIFO = stats.isFIFO.bind(stats); + this.isFile = stats.isFile.bind(stats); + this.isSocket = stats.isSocket.bind(stats); + this.isSymbolicLink = stats.isSymbolicLink.bind(stats); } - - return null; } - -function verifyENOENTSync(status, parsed) { - if (isWin && status === 1 && !parsed.file) { - return notFoundError(parsed.original, 'spawnSync'); - } - - return null; +function createDirentFromStats(name, stats) { + return new DirentFromStats(name, stats); } - -module.exports = { - hookChildProcess, - verifyENOENT, - verifyENOENTSync, - notFoundError, -}; +exports.createDirentFromStats = createDirentFromStats; /***/ }), -/***/ 3698: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -"use strict"; - +/***/ 4184: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { -const path = __nccwpck_require__(6928); -const resolveCommand = __nccwpck_require__(8881); -const escape = __nccwpck_require__(8847); -const readShebang = __nccwpck_require__(8026); -const isWin = process.platform === 'win32'; -const isExecutableRegExp = /\.(?:com|exe)$/i; -const isCmdShimRegExp = /node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.string = exports.stream = exports.pattern = exports.path = exports.fs = exports.errno = exports.array = void 0; +const array = __nccwpck_require__(6161); +exports.array = array; +const errno = __nccwpck_require__(5832); +exports.errno = errno; +const fs = __nccwpck_require__(2169); +exports.fs = fs; +const path = __nccwpck_require__(6961); +exports.path = path; +const pattern = __nccwpck_require__(6498); +exports.pattern = pattern; +const stream = __nccwpck_require__(4022); +exports.stream = stream; +const string = __nccwpck_require__(7879); +exports.string = string; -function detectShebang(parsed) { - parsed.file = resolveCommand(parsed); - const shebang = parsed.file && readShebang(parsed.file); +/***/ }), - if (shebang) { - parsed.args.unshift(parsed.file); - parsed.command = shebang; +/***/ 6961: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - return resolveCommand(parsed); - } - return parsed.file; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.convertPosixPathToPattern = exports.convertWindowsPathToPattern = exports.convertPathToPattern = exports.escapePosixPath = exports.escapeWindowsPath = exports.escape = exports.removeLeadingDotSegment = exports.makeAbsolute = exports.unixify = void 0; +const os = __nccwpck_require__(857); +const path = __nccwpck_require__(6928); +const IS_WINDOWS_PLATFORM = os.platform() === 'win32'; +const LEADING_DOT_SEGMENT_CHARACTERS_COUNT = 2; // ./ or .\\ +/** + * All non-escaped special characters. + * Posix: ()*?[]{|}, !+@ before (, ! at the beginning, \\ before non-special characters. + * Windows: (){}[], !+@ before (, ! at the beginning. + */ +const POSIX_UNESCAPED_GLOB_SYMBOLS_RE = /(\\?)([()*?[\]{|}]|^!|[!+@](?=\()|\\(?![!()*+?@[\]{|}]))/g; +const WINDOWS_UNESCAPED_GLOB_SYMBOLS_RE = /(\\?)([()[\]{}]|^!|[!+@](?=\())/g; +/** + * The device path (\\.\ or \\?\). + * https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats#dos-device-paths + */ +const DOS_DEVICE_PATH_RE = /^\\\\([.?])/; +/** + * All backslashes except those escaping special characters. + * Windows: !()+@{} + * https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file#naming-conventions + */ +const WINDOWS_BACKSLASHES_RE = /\\(?![!()+@[\]{}])/g; +/** + * Designed to work only with simple paths: `dir\\file`. + */ +function unixify(filepath) { + return filepath.replace(/\\/g, '/'); } - -function parseNonShell(parsed) { - if (!isWin) { - return parsed; - } - - // Detect & add support for shebangs - const commandFile = detectShebang(parsed); - - // We don't need a shell if the command filename is an executable - const needsShell = !isExecutableRegExp.test(commandFile); - - // If a shell is required, use cmd.exe and take care of escaping everything correctly - // Note that `forceShell` is an hidden option used only in tests - if (parsed.options.forceShell || needsShell) { - // Need to double escape meta chars if the command is a cmd-shim located in `node_modules/.bin/` - // The cmd-shim simply calls execute the package bin file with NodeJS, proxying any argument - // Because the escape of metachars with ^ gets interpreted when the cmd.exe is first called, - // we need to double escape them - const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile); - - // Normalize posix paths into OS compatible paths (e.g.: foo/bar -> foo\bar) - // This is necessary otherwise it will always fail with ENOENT in those cases - parsed.command = path.normalize(parsed.command); - - // Escape command & arguments - parsed.command = escape.command(parsed.command); - parsed.args = parsed.args.map((arg) => escape.argument(arg, needsDoubleEscapeMetaChars)); - - const shellCommand = [parsed.command].concat(parsed.args).join(' '); - - parsed.args = ['/d', '/s', '/c', `"${shellCommand}"`]; - parsed.command = process.env.comspec || 'cmd.exe'; - parsed.options.windowsVerbatimArguments = true; // Tell node's spawn that the arguments are already escaped - } - - return parsed; +exports.unixify = unixify; +function makeAbsolute(cwd, filepath) { + return path.resolve(cwd, filepath); } - -function parse(command, args, options) { - // Normalize arguments, similar to nodejs - if (args && !Array.isArray(args)) { - options = args; - args = null; +exports.makeAbsolute = makeAbsolute; +function removeLeadingDotSegment(entry) { + // We do not use `startsWith` because this is 10x slower than current implementation for some cases. + // eslint-disable-next-line @typescript-eslint/prefer-string-starts-ends-with + if (entry.charAt(0) === '.') { + const secondCharactery = entry.charAt(1); + if (secondCharactery === '/' || secondCharactery === '\\') { + return entry.slice(LEADING_DOT_SEGMENT_CHARACTERS_COUNT); + } } - - args = args ? args.slice(0) : []; // Clone array to avoid changing the original - options = Object.assign({}, options); // Clone object to avoid changing the original - - // Build our parsed object - const parsed = { - command, - args, - options, - file: undefined, - original: { - command, - args, - }, - }; - - // Delegate further parsing to shell or non-shell - return options.shell ? parsed : parseNonShell(parsed); + return entry; } - -module.exports = parse; +exports.removeLeadingDotSegment = removeLeadingDotSegment; +exports.escape = IS_WINDOWS_PLATFORM ? escapeWindowsPath : escapePosixPath; +function escapeWindowsPath(pattern) { + return pattern.replace(WINDOWS_UNESCAPED_GLOB_SYMBOLS_RE, '\\$2'); +} +exports.escapeWindowsPath = escapeWindowsPath; +function escapePosixPath(pattern) { + return pattern.replace(POSIX_UNESCAPED_GLOB_SYMBOLS_RE, '\\$2'); +} +exports.escapePosixPath = escapePosixPath; +exports.convertPathToPattern = IS_WINDOWS_PLATFORM ? convertWindowsPathToPattern : convertPosixPathToPattern; +function convertWindowsPathToPattern(filepath) { + return escapeWindowsPath(filepath) + .replace(DOS_DEVICE_PATH_RE, '//$1') + .replace(WINDOWS_BACKSLASHES_RE, '/'); +} +exports.convertWindowsPathToPattern = convertWindowsPathToPattern; +function convertPosixPathToPattern(filepath) { + return escapePosixPath(filepath); +} +exports.convertPosixPathToPattern = convertPosixPathToPattern; /***/ }), -/***/ 8847: -/***/ ((module) => { - -"use strict"; - - -// See http://www.robvanderwoude.com/escapechars.php -const metaCharsRegExp = /([()\][%!^"`<>&|;, *?])/g; +/***/ 6498: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { -function escapeCommand(arg) { - // Escape meta chars - arg = arg.replace(metaCharsRegExp, '^$1'); - return arg; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.isAbsolute = exports.partitionAbsoluteAndRelative = exports.removeDuplicateSlashes = exports.matchAny = exports.convertPatternsToRe = exports.makeRe = exports.getPatternParts = exports.expandBraceExpansion = exports.expandPatternsWithBraceExpansion = exports.isAffectDepthOfReadingPattern = exports.endsWithSlashGlobStar = exports.hasGlobStar = exports.getBaseDirectory = exports.isPatternRelatedToParentDirectory = exports.getPatternsOutsideCurrentDirectory = exports.getPatternsInsideCurrentDirectory = exports.getPositivePatterns = exports.getNegativePatterns = exports.isPositivePattern = exports.isNegativePattern = exports.convertToNegativePattern = exports.convertToPositivePattern = exports.isDynamicPattern = exports.isStaticPattern = void 0; +const path = __nccwpck_require__(6928); +const globParent = __nccwpck_require__(8879); +const micromatch = __nccwpck_require__(1136); +const GLOBSTAR = '**'; +const ESCAPE_SYMBOL = '\\'; +const COMMON_GLOB_SYMBOLS_RE = /[*?]|^!/; +const REGEX_CHARACTER_CLASS_SYMBOLS_RE = /\[[^[]*]/; +const REGEX_GROUP_SYMBOLS_RE = /(?:^|[^!*+?@])\([^(]*\|[^|]*\)/; +const GLOB_EXTENSION_SYMBOLS_RE = /[!*+?@]\([^(]*\)/; +const BRACE_EXPANSION_SEPARATORS_RE = /,|\.\./; +/** + * Matches a sequence of two or more consecutive slashes, excluding the first two slashes at the beginning of the string. + * The latter is due to the presence of the device path at the beginning of the UNC path. + */ +const DOUBLE_SLASH_RE = /(?!^)\/{2,}/g; +function isStaticPattern(pattern, options = {}) { + return !isDynamicPattern(pattern, options); } - -function escapeArgument(arg, doubleEscapeMetaChars) { - // Convert to string - arg = `${arg}`; - - // Algorithm below is based on https://qntm.org/cmd - // It's slightly altered to disable JS backtracking to avoid hanging on specially crafted input - // Please see https://github.com/moxystudio/node-cross-spawn/pull/160 for more information - - // Sequence of backslashes followed by a double quote: - // double up all the backslashes and escape the double quote - arg = arg.replace(/(?=(\\+?)?)\1"/g, '$1$1\\"'); - - // Sequence of backslashes followed by the end of the string - // (which will become a double quote later): - // double up all the backslashes - arg = arg.replace(/(?=(\\+?)?)\1$/, '$1$1'); - - // All other backslashes occur literally - - // Quote the whole thing: - arg = `"${arg}"`; - - // Escape meta chars - arg = arg.replace(metaCharsRegExp, '^$1'); - - // Double escape meta chars if necessary - if (doubleEscapeMetaChars) { - arg = arg.replace(metaCharsRegExp, '^$1'); +exports.isStaticPattern = isStaticPattern; +function isDynamicPattern(pattern, options = {}) { + /** + * A special case with an empty string is necessary for matching patterns that start with a forward slash. + * An empty string cannot be a dynamic pattern. + * For example, the pattern `/lib/*` will be spread into parts: '', 'lib', '*'. + */ + if (pattern === '') { + return false; } - - return arg; + /** + * When the `caseSensitiveMatch` option is disabled, all patterns must be marked as dynamic, because we cannot check + * filepath directly (without read directory). + */ + if (options.caseSensitiveMatch === false || pattern.includes(ESCAPE_SYMBOL)) { + return true; + } + if (COMMON_GLOB_SYMBOLS_RE.test(pattern) || REGEX_CHARACTER_CLASS_SYMBOLS_RE.test(pattern) || REGEX_GROUP_SYMBOLS_RE.test(pattern)) { + return true; + } + if (options.extglob !== false && GLOB_EXTENSION_SYMBOLS_RE.test(pattern)) { + return true; + } + if (options.braceExpansion !== false && hasBraceExpansion(pattern)) { + return true; + } + return false; } - -module.exports.command = escapeCommand; -module.exports.argument = escapeArgument; +exports.isDynamicPattern = isDynamicPattern; +function hasBraceExpansion(pattern) { + const openingBraceIndex = pattern.indexOf('{'); + if (openingBraceIndex === -1) { + return false; + } + const closingBraceIndex = pattern.indexOf('}', openingBraceIndex + 1); + if (closingBraceIndex === -1) { + return false; + } + const braceContent = pattern.slice(openingBraceIndex, closingBraceIndex); + return BRACE_EXPANSION_SEPARATORS_RE.test(braceContent); +} +function convertToPositivePattern(pattern) { + return isNegativePattern(pattern) ? pattern.slice(1) : pattern; +} +exports.convertToPositivePattern = convertToPositivePattern; +function convertToNegativePattern(pattern) { + return '!' + pattern; +} +exports.convertToNegativePattern = convertToNegativePattern; +function isNegativePattern(pattern) { + return pattern.startsWith('!') && pattern[1] !== '('; +} +exports.isNegativePattern = isNegativePattern; +function isPositivePattern(pattern) { + return !isNegativePattern(pattern); +} +exports.isPositivePattern = isPositivePattern; +function getNegativePatterns(patterns) { + return patterns.filter(isNegativePattern); +} +exports.getNegativePatterns = getNegativePatterns; +function getPositivePatterns(patterns) { + return patterns.filter(isPositivePattern); +} +exports.getPositivePatterns = getPositivePatterns; +/** + * Returns patterns that can be applied inside the current directory. + * + * @example + * // ['./*', '*', 'a/*'] + * getPatternsInsideCurrentDirectory(['./*', '*', 'a/*', '../*', './../*']) + */ +function getPatternsInsideCurrentDirectory(patterns) { + return patterns.filter((pattern) => !isPatternRelatedToParentDirectory(pattern)); +} +exports.getPatternsInsideCurrentDirectory = getPatternsInsideCurrentDirectory; +/** + * Returns patterns to be expanded relative to (outside) the current directory. + * + * @example + * // ['../*', './../*'] + * getPatternsInsideCurrentDirectory(['./*', '*', 'a/*', '../*', './../*']) + */ +function getPatternsOutsideCurrentDirectory(patterns) { + return patterns.filter(isPatternRelatedToParentDirectory); +} +exports.getPatternsOutsideCurrentDirectory = getPatternsOutsideCurrentDirectory; +function isPatternRelatedToParentDirectory(pattern) { + return pattern.startsWith('..') || pattern.startsWith('./..'); +} +exports.isPatternRelatedToParentDirectory = isPatternRelatedToParentDirectory; +function getBaseDirectory(pattern) { + return globParent(pattern, { flipBackslashes: false }); +} +exports.getBaseDirectory = getBaseDirectory; +function hasGlobStar(pattern) { + return pattern.includes(GLOBSTAR); +} +exports.hasGlobStar = hasGlobStar; +function endsWithSlashGlobStar(pattern) { + return pattern.endsWith('/' + GLOBSTAR); +} +exports.endsWithSlashGlobStar = endsWithSlashGlobStar; +function isAffectDepthOfReadingPattern(pattern) { + const basename = path.basename(pattern); + return endsWithSlashGlobStar(pattern) || isStaticPattern(basename); +} +exports.isAffectDepthOfReadingPattern = isAffectDepthOfReadingPattern; +function expandPatternsWithBraceExpansion(patterns) { + return patterns.reduce((collection, pattern) => { + return collection.concat(expandBraceExpansion(pattern)); + }, []); +} +exports.expandPatternsWithBraceExpansion = expandPatternsWithBraceExpansion; +function expandBraceExpansion(pattern) { + const patterns = micromatch.braces(pattern, { expand: true, nodupes: true, keepEscaping: true }); + /** + * Sort the patterns by length so that the same depth patterns are processed side by side. + * `a/{b,}/{c,}/*` – `['a///*', 'a/b//*', 'a//c/*', 'a/b/c/*']` + */ + patterns.sort((a, b) => a.length - b.length); + /** + * Micromatch can return an empty string in the case of patterns like `{a,}`. + */ + return patterns.filter((pattern) => pattern !== ''); +} +exports.expandBraceExpansion = expandBraceExpansion; +function getPatternParts(pattern, options) { + let { parts } = micromatch.scan(pattern, Object.assign(Object.assign({}, options), { parts: true })); + /** + * The scan method returns an empty array in some cases. + * See micromatch/picomatch#58 for more details. + */ + if (parts.length === 0) { + parts = [pattern]; + } + /** + * The scan method does not return an empty part for the pattern with a forward slash. + * This is another part of micromatch/picomatch#58. + */ + if (parts[0].startsWith('/')) { + parts[0] = parts[0].slice(1); + parts.unshift(''); + } + return parts; +} +exports.getPatternParts = getPatternParts; +function makeRe(pattern, options) { + return micromatch.makeRe(pattern, options); +} +exports.makeRe = makeRe; +function convertPatternsToRe(patterns, options) { + return patterns.map((pattern) => makeRe(pattern, options)); +} +exports.convertPatternsToRe = convertPatternsToRe; +function matchAny(entry, patternsRe) { + return patternsRe.some((patternRe) => patternRe.test(entry)); +} +exports.matchAny = matchAny; +/** + * This package only works with forward slashes as a path separator. + * Because of this, we cannot use the standard `path.normalize` method, because on Windows platform it will use of backslashes. + */ +function removeDuplicateSlashes(pattern) { + return pattern.replace(DOUBLE_SLASH_RE, '/'); +} +exports.removeDuplicateSlashes = removeDuplicateSlashes; +function partitionAbsoluteAndRelative(patterns) { + const absolute = []; + const relative = []; + for (const pattern of patterns) { + if (isAbsolute(pattern)) { + absolute.push(pattern); + } + else { + relative.push(pattern); + } + } + return [absolute, relative]; +} +exports.partitionAbsoluteAndRelative = partitionAbsoluteAndRelative; +function isAbsolute(pattern) { + return path.isAbsolute(pattern); +} +exports.isAbsolute = isAbsolute; /***/ }), -/***/ 8026: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +/***/ 4022: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { -"use strict"; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.merge = void 0; +const merge2 = __nccwpck_require__(6508); +function merge(streams) { + const mergedStream = merge2(streams); + streams.forEach((stream) => { + stream.once('error', (error) => mergedStream.emit('error', error)); + }); + mergedStream.once('close', () => propagateCloseEventToSources(streams)); + mergedStream.once('end', () => propagateCloseEventToSources(streams)); + return mergedStream; +} +exports.merge = merge; +function propagateCloseEventToSources(streams) { + streams.forEach((stream) => stream.emit('close')); +} -const fs = __nccwpck_require__(9896); -const shebangCommand = __nccwpck_require__(3336); -function readShebang(command) { - // Read the first 150 bytes from the file - const size = 150; - const buffer = Buffer.alloc(size); +/***/ }), - let fd; +/***/ 7879: +/***/ ((__unused_webpack_module, exports) => { - try { - fd = fs.openSync(command, 'r'); - fs.readSync(fd, buffer, 0, size, 0); - fs.closeSync(fd); - } catch (e) { /* Empty */ } - // Attempt to extract shebang (null is returned if not a shebang) - return shebangCommand(buffer.toString()); +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.isEmpty = exports.isString = void 0; +function isString(input) { + return typeof input === 'string'; } - -module.exports = readShebang; +exports.isString = isString; +function isEmpty(input) { + return input === ''; +} +exports.isEmpty = isEmpty; /***/ }), -/***/ 8881: +/***/ 4187: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -const path = __nccwpck_require__(6928); -const which = __nccwpck_require__(4307); -const getPathKey = __nccwpck_require__(5914); +/* eslint-disable no-var */ -function resolveCommandAttempt(parsed, withoutPathExt) { - const env = parsed.options.env || process.env; - const cwd = process.cwd(); - const hasCustomCwd = parsed.options.cwd != null; - // Worker threads do not have process.chdir() - const shouldSwitchCwd = hasCustomCwd && process.chdir !== undefined && !process.chdir.disabled; +var reusify = __nccwpck_require__(7093) - // If a custom `cwd` was specified, we need to change the process cwd - // because `which` will do stat calls but does not support a custom cwd - if (shouldSwitchCwd) { - try { - process.chdir(parsed.options.cwd); - } catch (err) { - /* Empty */ - } - } +function fastqueue (context, worker, _concurrency) { + if (typeof context === 'function') { + _concurrency = worker + worker = context + context = null + } - let resolved; + if (!(_concurrency >= 1)) { + throw new Error('fastqueue concurrency must be equal to or greater than 1') + } - try { - resolved = which.sync(parsed.command, { - path: env[getPathKey({ env })], - pathExt: withoutPathExt ? path.delimiter : undefined, - }); - } catch (e) { - /* Empty */ - } finally { - if (shouldSwitchCwd) { - process.chdir(cwd); - } - } + var cache = reusify(Task) + var queueHead = null + var queueTail = null + var _running = 0 + var errorHandler = null - // If we successfully resolved, ensure that an absolute path is returned - // Note that when a custom `cwd` was used, we need to resolve to an absolute path based on it - if (resolved) { - resolved = path.resolve(hasCustomCwd ? parsed.options.cwd : '', resolved); - } + var self = { + push: push, + drain: noop, + saturated: noop, + pause: pause, + paused: false, - return resolved; -} + get concurrency () { + return _concurrency + }, + set concurrency (value) { + if (!(value >= 1)) { + throw new Error('fastqueue concurrency must be equal to or greater than 1') + } + _concurrency = value -function resolveCommand(parsed) { - return resolveCommandAttempt(parsed) || resolveCommandAttempt(parsed, true); -} + if (self.paused) return + for (; queueHead && _running < _concurrency;) { + _running++ + release() + } + }, -module.exports = resolveCommand; + running: running, + resume: resume, + idle: idle, + length: length, + getQueue: getQueue, + unshift: unshift, + empty: noop, + kill: kill, + killAndDrain: killAndDrain, + error: error + } + return self -/***/ }), + function running () { + return _running + } -/***/ 1677: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + function pause () { + self.paused = true + } -"use strict"; + function length () { + var current = queueHead + var counter = 0 -const path = __nccwpck_require__(6928); -const childProcess = __nccwpck_require__(5317); -const crossSpawn = __nccwpck_require__(8597); -const stripFinalNewline = __nccwpck_require__(3366); -const npmRunPath = __nccwpck_require__(7227); -const onetime = __nccwpck_require__(1907); -const makeError = __nccwpck_require__(3023); -const normalizeStdio = __nccwpck_require__(3004); -const {spawnedKill, spawnedCancel, setupTimeout, validateTimeout, setExitHandler} = __nccwpck_require__(4421); -const {handleInput, getSpawnedResult, makeAllStream, validateInputSync} = __nccwpck_require__(8206); -const {mergePromise, getSpawnedPromise} = __nccwpck_require__(2044); -const {joinCommand, parseCommand, getEscapedCommand} = __nccwpck_require__(2492); + while (current) { + current = current.next + counter++ + } -const DEFAULT_MAX_BUFFER = 1000 * 1000 * 100; + return counter + } -const getEnv = ({env: envOption, extendEnv, preferLocal, localDir, execPath}) => { - const env = extendEnv ? {...process.env, ...envOption} : envOption; + function getQueue () { + var current = queueHead + var tasks = [] - if (preferLocal) { - return npmRunPath.env({env, cwd: localDir, execPath}); - } + while (current) { + tasks.push(current.value) + current = current.next + } - return env; -}; + return tasks + } -const handleArguments = (file, args, options = {}) => { - const parsed = crossSpawn._parse(file, args, options); - file = parsed.command; - args = parsed.args; - options = parsed.options; + function resume () { + if (!self.paused) return + self.paused = false + if (queueHead === null) { + _running++ + release() + return + } + for (; queueHead && _running < _concurrency;) { + _running++ + release() + } + } - options = { - maxBuffer: DEFAULT_MAX_BUFFER, - buffer: true, - stripFinalNewline: true, - extendEnv: true, - preferLocal: false, - localDir: options.cwd || process.cwd(), - execPath: process.execPath, - encoding: 'utf8', - reject: true, - cleanup: true, - all: false, - windowsHide: true, - ...options - }; + function idle () { + return _running === 0 && self.length() === 0 + } - options.env = getEnv(options); + function push (value, done) { + var current = cache.get() - options.stdio = normalizeStdio(options); + current.context = context + current.release = release + current.value = value + current.callback = done || noop + current.errorHandler = errorHandler - if (process.platform === 'win32' && path.basename(file, '.exe') === 'cmd') { - // #116 - args.unshift('/q'); - } + if (_running >= _concurrency || self.paused) { + if (queueTail) { + queueTail.next = current + queueTail = current + } else { + queueHead = current + queueTail = current + self.saturated() + } + } else { + _running++ + worker.call(context, current.value, current.worked) + } + } - return {file, args, options, parsed}; -}; + function unshift (value, done) { + var current = cache.get() -const handleOutput = (options, value, error) => { - if (typeof value !== 'string' && !Buffer.isBuffer(value)) { - // When `execa.sync()` errors, we normalize it to '' to mimic `execa()` - return error === undefined ? undefined : ''; - } + current.context = context + current.release = release + current.value = value + current.callback = done || noop + current.errorHandler = errorHandler - if (options.stripFinalNewline) { - return stripFinalNewline(value); - } + if (_running >= _concurrency || self.paused) { + if (queueHead) { + current.next = queueHead + queueHead = current + } else { + queueHead = current + queueTail = current + self.saturated() + } + } else { + _running++ + worker.call(context, current.value, current.worked) + } + } - return value; -}; + function release (holder) { + if (holder) { + cache.release(holder) + } + var next = queueHead + if (next && _running <= _concurrency) { + if (!self.paused) { + if (queueTail === queueHead) { + queueTail = null + } + queueHead = next.next + next.next = null + worker.call(context, next.value, next.worked) + if (queueTail === null) { + self.empty() + } + } else { + _running-- + } + } else if (--_running === 0) { + self.drain() + } + } -const execa = (file, args, options) => { - const parsed = handleArguments(file, args, options); - const command = joinCommand(file, args); - const escapedCommand = getEscapedCommand(file, args); + function kill () { + queueHead = null + queueTail = null + self.drain = noop + } - validateTimeout(parsed.options); + function killAndDrain () { + queueHead = null + queueTail = null + self.drain() + self.drain = noop + } - let spawned; - try { - spawned = childProcess.spawn(parsed.file, parsed.args, parsed.options); - } catch (error) { - // Ensure the returned error is always both a promise and a child process - const dummySpawned = new childProcess.ChildProcess(); - const errorPromise = Promise.reject(makeError({ - error, - stdout: '', - stderr: '', - all: '', - command, - escapedCommand, - parsed, - timedOut: false, - isCanceled: false, - killed: false - })); - return mergePromise(dummySpawned, errorPromise); - } - - const spawnedPromise = getSpawnedPromise(spawned); - const timedPromise = setupTimeout(spawned, parsed.options, spawnedPromise); - const processDone = setExitHandler(spawned, parsed.options, timedPromise); - - const context = {isCanceled: false}; - - spawned.kill = spawnedKill.bind(null, spawned.kill.bind(spawned)); - spawned.cancel = spawnedCancel.bind(null, spawned, context); - - const handlePromise = async () => { - const [{error, exitCode, signal, timedOut}, stdoutResult, stderrResult, allResult] = await getSpawnedResult(spawned, parsed.options, processDone); - const stdout = handleOutput(parsed.options, stdoutResult); - const stderr = handleOutput(parsed.options, stderrResult); - const all = handleOutput(parsed.options, allResult); - - if (error || exitCode !== 0 || signal !== null) { - const returnedError = makeError({ - error, - exitCode, - signal, - stdout, - stderr, - all, - command, - escapedCommand, - parsed, - timedOut, - isCanceled: context.isCanceled, - killed: spawned.killed - }); - - if (!parsed.options.reject) { - return returnedError; - } - - throw returnedError; - } - - return { - command, - escapedCommand, - exitCode: 0, - stdout, - stderr, - all, - failed: false, - timedOut: false, - isCanceled: false, - killed: false - }; - }; + function error (handler) { + errorHandler = handler + } +} - const handlePromiseOnce = onetime(handlePromise); +function noop () {} - handleInput(spawned, parsed.options.input); +function Task () { + this.value = null + this.callback = noop + this.next = null + this.release = noop + this.context = null + this.errorHandler = null - spawned.all = makeAllStream(spawned, parsed.options); + var self = this - return mergePromise(spawned, handlePromiseOnce); -}; + this.worked = function worked (err, result) { + var callback = self.callback + var errorHandler = self.errorHandler + var val = self.value + self.value = null + self.callback = noop + if (self.errorHandler) { + errorHandler(err, val) + } + callback.call(self.context, err, result) + self.release(self) + } +} -module.exports = execa; +function queueAsPromised (context, worker, _concurrency) { + if (typeof context === 'function') { + _concurrency = worker + worker = context + context = null + } -module.exports.sync = (file, args, options) => { - const parsed = handleArguments(file, args, options); - const command = joinCommand(file, args); - const escapedCommand = getEscapedCommand(file, args); + function asyncWrapper (arg, cb) { + worker.call(this, arg) + .then(function (res) { + cb(null, res) + }, cb) + } - validateInputSync(parsed.options); + var queue = fastqueue(context, asyncWrapper, _concurrency) - let result; - try { - result = childProcess.spawnSync(parsed.file, parsed.args, parsed.options); - } catch (error) { - throw makeError({ - error, - stdout: '', - stderr: '', - all: '', - command, - escapedCommand, - parsed, - timedOut: false, - isCanceled: false, - killed: false - }); - } + var pushCb = queue.push + var unshiftCb = queue.unshift - const stdout = handleOutput(parsed.options, result.stdout, result.error); - const stderr = handleOutput(parsed.options, result.stderr, result.error); + queue.push = push + queue.unshift = unshift + queue.drained = drained - if (result.error || result.status !== 0 || result.signal !== null) { - const error = makeError({ - stdout, - stderr, - error: result.error, - signal: result.signal, - exitCode: result.status, - command, - escapedCommand, - parsed, - timedOut: result.error && result.error.code === 'ETIMEDOUT', - isCanceled: false, - killed: result.signal !== null - }); + return queue - if (!parsed.options.reject) { - return error; - } + function push (value) { + var p = new Promise(function (resolve, reject) { + pushCb(value, function (err, result) { + if (err) { + reject(err) + return + } + resolve(result) + }) + }) - throw error; - } + // Let's fork the promise chain to + // make the error bubble up to the user but + // not lead to a unhandledRejection + p.catch(noop) - return { - command, - escapedCommand, - exitCode: 0, - stdout, - stderr, - failed: false, - timedOut: false, - isCanceled: false, - killed: false - }; -}; + return p + } -module.exports.command = (command, options) => { - const [file, ...args] = parseCommand(command); - return execa(file, args, options); -}; + function unshift (value) { + var p = new Promise(function (resolve, reject) { + unshiftCb(value, function (err, result) { + if (err) { + reject(err) + return + } + resolve(result) + }) + }) -module.exports.commandSync = (command, options) => { - const [file, ...args] = parseCommand(command); - return execa.sync(file, args, options); -}; + // Let's fork the promise chain to + // make the error bubble up to the user but + // not lead to a unhandledRejection + p.catch(noop) -module.exports.node = (scriptPath, args, options = {}) => { - if (args && !Array.isArray(args) && typeof args === 'object') { - options = args; - args = []; - } + return p + } - const stdio = normalizeStdio.node(options); - const defaultExecArgv = process.execArgv.filter(arg => !arg.startsWith('--inspect')); + function drained () { + var p = new Promise(function (resolve) { + process.nextTick(function () { + if (queue.idle()) { + resolve() + } else { + var previousDrain = queue.drain + queue.drain = function () { + if (typeof previousDrain === 'function') previousDrain() + resolve() + queue.drain = previousDrain + } + } + }) + }) - const { - nodePath = process.execPath, - nodeOptions = defaultExecArgv - } = options; + return p + } +} - return execa( - nodePath, - [ - ...nodeOptions, - scriptPath, - ...(Array.isArray(args) ? args : []) - ], - { - ...options, - stdin: undefined, - stdout: undefined, - stderr: undefined, - stdio, - shell: false - } - ); -}; +module.exports = fastqueue +module.exports.promise = queueAsPromised /***/ }), -/***/ 2492: -/***/ ((module) => { +/***/ 5514: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; +/*! + * fill-range + * + * Copyright (c) 2014-present, Jon Schlinkert. + * Licensed under the MIT License. + */ -const normalizeArgs = (file, args = []) => { - if (!Array.isArray(args)) { - return [file]; - } - return [file, ...args]; -}; -const NO_ESCAPE_REGEXP = /^[\w.-]+$/; -const DOUBLE_QUOTES_REGEXP = /"/g; +const util = __nccwpck_require__(9023); +const toRegexRange = __nccwpck_require__(3763); -const escapeArg = arg => { - if (typeof arg !== 'string' || NO_ESCAPE_REGEXP.test(arg)) { - return arg; - } +const isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val); - return `"${arg.replace(DOUBLE_QUOTES_REGEXP, '\\"')}"`; +const transform = toNumber => { + return value => toNumber === true ? Number(value) : String(value); }; -const joinCommand = (file, args) => { - return normalizeArgs(file, args).join(' '); +const isValidValue = value => { + return typeof value === 'number' || (typeof value === 'string' && value !== ''); }; -const getEscapedCommand = (file, args) => { - return normalizeArgs(file, args).map(arg => escapeArg(arg)).join(' '); -}; +const isNumber = num => Number.isInteger(+num); -const SPACES_REGEXP = / +/g; +const zeros = input => { + let value = `${input}`; + let index = -1; + if (value[0] === '-') value = value.slice(1); + if (value === '0') return false; + while (value[++index] === '0'); + return index > 0; +}; -// Handle `execa.command()` -const parseCommand = command => { - const tokens = []; - for (const token of command.trim().split(SPACES_REGEXP)) { - // Allow spaces to be escaped by a backslash if not meant as a delimiter - const previousToken = tokens[tokens.length - 1]; - if (previousToken && previousToken.endsWith('\\')) { - // Merge previous token with current one - tokens[tokens.length - 1] = `${previousToken.slice(0, -1)} ${token}`; - } else { - tokens.push(token); - } - } +const stringify = (start, end, options) => { + if (typeof start === 'string' || typeof end === 'string') { + return true; + } + return options.stringify === true; +}; - return tokens; +const pad = (input, maxLength, toNumber) => { + if (maxLength > 0) { + let dash = input[0] === '-' ? '-' : ''; + if (dash) input = input.slice(1); + input = (dash + input.padStart(dash ? maxLength - 1 : maxLength, '0')); + } + if (toNumber === false) { + return String(input); + } + return input; }; -module.exports = { - joinCommand, - getEscapedCommand, - parseCommand +const toMaxLen = (input, maxLength) => { + let negative = input[0] === '-' ? '-' : ''; + if (negative) { + input = input.slice(1); + maxLength--; + } + while (input.length < maxLength) input = '0' + input; + return negative ? ('-' + input) : input; }; +const toSequence = (parts, options, maxLen) => { + parts.negatives.sort((a, b) => a < b ? -1 : a > b ? 1 : 0); + parts.positives.sort((a, b) => a < b ? -1 : a > b ? 1 : 0); -/***/ }), + let prefix = options.capture ? '' : '?:'; + let positives = ''; + let negatives = ''; + let result; -/***/ 3023: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + if (parts.positives.length) { + positives = parts.positives.map(v => toMaxLen(String(v), maxLen)).join('|'); + } -"use strict"; + if (parts.negatives.length) { + negatives = `-(${prefix}${parts.negatives.map(v => toMaxLen(String(v), maxLen)).join('|')})`; + } -const {signalsByName} = __nccwpck_require__(4549); + if (positives && negatives) { + result = `${positives}|${negatives}`; + } else { + result = positives || negatives; + } -const getErrorPrefix = ({timedOut, timeout, errorCode, signal, signalDescription, exitCode, isCanceled}) => { - if (timedOut) { - return `timed out after ${timeout} milliseconds`; - } + if (options.wrap) { + return `(${prefix}${result})`; + } - if (isCanceled) { - return 'was canceled'; - } + return result; +}; - if (errorCode !== undefined) { - return `failed with ${errorCode}`; - } +const toRange = (a, b, isNumbers, options) => { + if (isNumbers) { + return toRegexRange(a, b, { wrap: false, ...options }); + } - if (signal !== undefined) { - return `was killed with ${signal} (${signalDescription})`; - } + let start = String.fromCharCode(a); + if (a === b) return start; - if (exitCode !== undefined) { - return `failed with exit code ${exitCode}`; - } + let stop = String.fromCharCode(b); + return `[${start}-${stop}]`; +}; - return 'failed'; +const toRegex = (start, end, options) => { + if (Array.isArray(start)) { + let wrap = options.wrap === true; + let prefix = options.capture ? '' : '?:'; + return wrap ? `(${prefix}${start.join('|')})` : start.join('|'); + } + return toRegexRange(start, end, options); }; -const makeError = ({ - stdout, - stderr, - all, - error, - signal, - exitCode, - command, - escapedCommand, - timedOut, - isCanceled, - killed, - parsed: {options: {timeout}} -}) => { - // `signal` and `exitCode` emitted on `spawned.on('exit')` event can be `null`. - // We normalize them to `undefined` - exitCode = exitCode === null ? undefined : exitCode; - signal = signal === null ? undefined : signal; - const signalDescription = signal === undefined ? undefined : signalsByName[signal].description; +const rangeError = (...args) => { + return new RangeError('Invalid range arguments: ' + util.inspect(...args)); +}; - const errorCode = error && error.code; +const invalidRange = (start, end, options) => { + if (options.strictRanges === true) throw rangeError([start, end]); + return []; +}; - const prefix = getErrorPrefix({timedOut, timeout, errorCode, signal, signalDescription, exitCode, isCanceled}); - const execaMessage = `Command ${prefix}: ${command}`; - const isError = Object.prototype.toString.call(error) === '[object Error]'; - const shortMessage = isError ? `${execaMessage}\n${error.message}` : execaMessage; - const message = [shortMessage, stderr, stdout].filter(Boolean).join('\n'); +const invalidStep = (step, options) => { + if (options.strictRanges === true) { + throw new TypeError(`Expected step "${step}" to be a number`); + } + return []; +}; - if (isError) { - error.originalMessage = error.message; - error.message = message; - } else { - error = new Error(message); - } +const fillNumbers = (start, end, step = 1, options = {}) => { + let a = Number(start); + let b = Number(end); - error.shortMessage = shortMessage; - error.command = command; - error.escapedCommand = escapedCommand; - error.exitCode = exitCode; - error.signal = signal; - error.signalDescription = signalDescription; - error.stdout = stdout; - error.stderr = stderr; + if (!Number.isInteger(a) || !Number.isInteger(b)) { + if (options.strictRanges === true) throw rangeError([start, end]); + return []; + } - if (all !== undefined) { - error.all = all; - } + // fix negative zero + if (a === 0) a = 0; + if (b === 0) b = 0; - if ('bufferedData' in error) { - delete error.bufferedData; - } + let descending = a > b; + let startString = String(start); + let endString = String(end); + let stepString = String(step); + step = Math.max(Math.abs(step), 1); - error.failed = true; - error.timedOut = Boolean(timedOut); - error.isCanceled = isCanceled; - error.killed = killed && !timedOut; + let padded = zeros(startString) || zeros(endString) || zeros(stepString); + let maxLen = padded ? Math.max(startString.length, endString.length, stepString.length) : 0; + let toNumber = padded === false && stringify(start, end, options) === false; + let format = options.transform || transform(toNumber); - return error; -}; + if (options.toRegex && step === 1) { + return toRange(toMaxLen(start, maxLen), toMaxLen(end, maxLen), true, options); + } -module.exports = makeError; + let parts = { negatives: [], positives: [] }; + let push = num => parts[num < 0 ? 'negatives' : 'positives'].push(Math.abs(num)); + let range = []; + let index = 0; + while (descending ? a >= b : a <= b) { + if (options.toRegex === true && step > 1) { + push(a); + } else { + range.push(pad(format(a, index), maxLen, toNumber)); + } + a = descending ? a - step : a + step; + index++; + } -/***/ }), + if (options.toRegex === true) { + return step > 1 + ? toSequence(parts, options, maxLen) + : toRegex(range, null, { wrap: false, ...options }); + } -/***/ 4421: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + return range; +}; -"use strict"; +const fillLetters = (start, end, step = 1, options = {}) => { + if ((!isNumber(start) && start.length > 1) || (!isNumber(end) && end.length > 1)) { + return invalidRange(start, end, options); + } -const os = __nccwpck_require__(857); -const onExit = __nccwpck_require__(965); + let format = options.transform || (val => String.fromCharCode(val)); + let a = `${start}`.charCodeAt(0); + let b = `${end}`.charCodeAt(0); -const DEFAULT_FORCE_KILL_TIMEOUT = 1000 * 5; - -// Monkey-patches `childProcess.kill()` to add `forceKillAfterTimeout` behavior -const spawnedKill = (kill, signal = 'SIGTERM', options = {}) => { - const killResult = kill(signal); - setKillTimeout(kill, signal, options, killResult); - return killResult; -}; - -const setKillTimeout = (kill, signal, options, killResult) => { - if (!shouldForceKill(signal, options, killResult)) { - return; - } - - const timeout = getForceKillAfterTimeout(options); - const t = setTimeout(() => { - kill('SIGKILL'); - }, timeout); - - // Guarded because there's no `.unref()` when `execa` is used in the renderer - // process in Electron. This cannot be tested since we don't run tests in - // Electron. - // istanbul ignore else - if (t.unref) { - t.unref(); - } -}; + let descending = a > b; + let min = Math.min(a, b); + let max = Math.max(a, b); -const shouldForceKill = (signal, {forceKillAfterTimeout}, killResult) => { - return isSigterm(signal) && forceKillAfterTimeout !== false && killResult; -}; + if (options.toRegex && step === 1) { + return toRange(min, max, false, options); + } -const isSigterm = signal => { - return signal === os.constants.signals.SIGTERM || - (typeof signal === 'string' && signal.toUpperCase() === 'SIGTERM'); -}; + let range = []; + let index = 0; -const getForceKillAfterTimeout = ({forceKillAfterTimeout = true}) => { - if (forceKillAfterTimeout === true) { - return DEFAULT_FORCE_KILL_TIMEOUT; - } + while (descending ? a >= b : a <= b) { + range.push(format(a, index)); + a = descending ? a - step : a + step; + index++; + } - if (!Number.isFinite(forceKillAfterTimeout) || forceKillAfterTimeout < 0) { - throw new TypeError(`Expected the \`forceKillAfterTimeout\` option to be a non-negative integer, got \`${forceKillAfterTimeout}\` (${typeof forceKillAfterTimeout})`); - } + if (options.toRegex === true) { + return toRegex(range, null, { wrap: false, options }); + } - return forceKillAfterTimeout; + return range; }; -// `childProcess.cancel()` -const spawnedCancel = (spawned, context) => { - const killResult = spawned.kill(); +const fill = (start, end, step, options = {}) => { + if (end == null && isValidValue(start)) { + return [start]; + } - if (killResult) { - context.isCanceled = true; - } -}; + if (!isValidValue(start) || !isValidValue(end)) { + return invalidRange(start, end, options); + } -const timeoutKill = (spawned, signal, reject) => { - spawned.kill(signal); - reject(Object.assign(new Error('Timed out'), {timedOut: true, signal})); -}; + if (typeof step === 'function') { + return fill(start, end, 1, { transform: step }); + } -// `timeout` option handling -const setupTimeout = (spawned, {timeout, killSignal = 'SIGTERM'}, spawnedPromise) => { - if (timeout === 0 || timeout === undefined) { - return spawnedPromise; - } + if (isObject(step)) { + return fill(start, end, 0, step); + } - let timeoutId; - const timeoutPromise = new Promise((resolve, reject) => { - timeoutId = setTimeout(() => { - timeoutKill(spawned, killSignal, reject); - }, timeout); - }); + let opts = { ...options }; + if (opts.capture === true) opts.wrap = true; + step = step || opts.step || 1; - const safeSpawnedPromise = spawnedPromise.finally(() => { - clearTimeout(timeoutId); - }); + if (!isNumber(step)) { + if (step != null && !isObject(step)) return invalidStep(step, opts); + return fill(start, end, 1, step); + } - return Promise.race([timeoutPromise, safeSpawnedPromise]); -}; + if (isNumber(start) && isNumber(end)) { + return fillNumbers(start, end, step, opts); + } -const validateTimeout = ({timeout}) => { - if (timeout !== undefined && (!Number.isFinite(timeout) || timeout < 0)) { - throw new TypeError(`Expected the \`timeout\` option to be a non-negative integer, got \`${timeout}\` (${typeof timeout})`); - } + return fillLetters(start, end, Math.max(Math.abs(step), 1), opts); }; -// `cleanup` option handling -const setExitHandler = async (spawned, {cleanup, detached}, timedPromise) => { - if (!cleanup || detached) { - return timedPromise; - } +module.exports = fill; - const removeExitHandler = onExit(() => { - spawned.kill(); - }); - return timedPromise.finally(() => { - removeExitHandler(); - }); -}; +/***/ }), -module.exports = { - spawnedKill, - spawnedCancel, - setupTimeout, - validateTimeout, - setExitHandler -}; +/***/ 2332: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -/***/ }), +const {PassThrough: PassThroughStream} = __nccwpck_require__(2203); -/***/ 2044: -/***/ ((module) => { +module.exports = options => { + options = {...options}; -"use strict"; + const {array} = options; + let {encoding} = options; + const isBuffer = encoding === 'buffer'; + let objectMode = false; + if (array) { + objectMode = !(encoding || isBuffer); + } else { + encoding = encoding || 'utf8'; + } -const nativePromisePrototype = (async () => {})().constructor.prototype; -const descriptors = ['then', 'catch', 'finally'].map(property => [ - property, - Reflect.getOwnPropertyDescriptor(nativePromisePrototype, property) -]); + if (isBuffer) { + encoding = null; + } -// The return value is a mixin of `childProcess` and `Promise` -const mergePromise = (spawned, promise) => { - for (const [property, descriptor] of descriptors) { - // Starting the main `promise` is deferred to avoid consuming streams - const value = typeof promise === 'function' ? - (...args) => Reflect.apply(descriptor.value, promise(), args) : - descriptor.value.bind(promise); + const stream = new PassThroughStream({objectMode}); - Reflect.defineProperty(spawned, property, {...descriptor, value}); + if (encoding) { + stream.setEncoding(encoding); } - return spawned; -}; - -// Use promises instead of `child_process` events -const getSpawnedPromise = spawned => { - return new Promise((resolve, reject) => { - spawned.on('exit', (exitCode, signal) => { - resolve({exitCode, signal}); - }); + let length = 0; + const chunks = []; - spawned.on('error', error => { - reject(error); - }); + stream.on('data', chunk => { + chunks.push(chunk); - if (spawned.stdin) { - spawned.stdin.on('error', error => { - reject(error); - }); + if (objectMode) { + length = chunks.length; + } else { + length += chunk.length; } }); -}; - -module.exports = { - mergePromise, - getSpawnedPromise -}; + stream.getBufferedValue = () => { + if (array) { + return chunks; + } + return isBuffer ? Buffer.concat(chunks, length) : chunks.join(''); + }; -/***/ }), + stream.getBufferedLength = () => length; -/***/ 3004: -/***/ ((module) => { + return stream; +}; -"use strict"; -const aliases = ['stdin', 'stdout', 'stderr']; +/***/ }), -const hasAlias = options => aliases.some(alias => options[alias] !== undefined); +/***/ 4333: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -const normalizeStdio = options => { - if (!options) { - return; - } - const {stdio} = options; +const {constants: BufferConstants} = __nccwpck_require__(181); +const stream = __nccwpck_require__(2203); +const {promisify} = __nccwpck_require__(9023); +const bufferStream = __nccwpck_require__(2332); - if (stdio === undefined) { - return aliases.map(alias => options[alias]); - } +const streamPipelinePromisified = promisify(stream.pipeline); - if (hasAlias(options)) { - throw new Error(`It's not possible to provide \`stdio\` in combination with one of ${aliases.map(alias => `\`${alias}\``).join(', ')}`); +class MaxBufferError extends Error { + constructor() { + super('maxBuffer exceeded'); + this.name = 'MaxBufferError'; } +} - if (typeof stdio === 'string') { - return stdio; +async function getStream(inputStream, options) { + if (!inputStream) { + throw new Error('Expected a stream'); } - if (!Array.isArray(stdio)) { - throw new TypeError(`Expected \`stdio\` to be of type \`string\` or \`Array\`, got \`${typeof stdio}\``); - } + options = { + maxBuffer: Infinity, + ...options + }; - const length = Math.max(stdio.length, aliases.length); - return Array.from({length}, (value, index) => stdio[index]); -}; + const {maxBuffer} = options; + const stream = bufferStream(options); -module.exports = normalizeStdio; + await new Promise((resolve, reject) => { + const rejectPromise = error => { + // Don't retrieve an oversized buffer. + if (error && stream.getBufferedLength() <= BufferConstants.MAX_LENGTH) { + error.bufferedData = stream.getBufferedValue(); + } -// `ipc` is pushed unless it is already present -module.exports.node = options => { - const stdio = normalizeStdio(options); + reject(error); + }; - if (stdio === 'ipc') { - return 'ipc'; - } + (async () => { + try { + await streamPipelinePromisified(inputStream, stream); + resolve(); + } catch (error) { + rejectPromise(error); + } + })(); - if (stdio === undefined || typeof stdio === 'string') { - return [stdio, stdio, stdio, 'ipc']; - } + stream.on('data', () => { + if (stream.getBufferedLength() > maxBuffer) { + rejectPromise(new MaxBufferError()); + } + }); + }); - if (stdio.includes('ipc')) { - return stdio; - } + return stream.getBufferedValue(); +} - return [...stdio, 'ipc']; -}; +module.exports = getStream; +module.exports.buffer = (stream, options) => getStream(stream, {...options, encoding: 'buffer'}); +module.exports.array = (stream, options) => getStream(stream, {...options, array: true}); +module.exports.MaxBufferError = MaxBufferError; /***/ }), -/***/ 8206: +/***/ 8879: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -const isStream = __nccwpck_require__(9828); -const getStream = __nccwpck_require__(3257); -const mergeStream = __nccwpck_require__(9235); -// `input` option -const handleInput = (spawned, input) => { - // Checking for stdin is workaround for https://github.com/nodejs/node/issues/26852 - // @todo remove `|| spawned.stdin === undefined` once we drop support for Node.js <=12.2.0 - if (input === undefined || spawned.stdin === undefined) { - return; - } +var isGlob = __nccwpck_require__(498); +var pathPosixDirname = (__nccwpck_require__(6928).posix).dirname; +var isWin32 = (__nccwpck_require__(857).platform)() === 'win32'; - if (isStream(input)) { - input.pipe(spawned.stdin); - } else { - spawned.stdin.end(input); - } -}; +var slash = '/'; +var backslash = /\\/g; +var enclosure = /[\{\[].*[\}\]]$/; +var globby = /(^|[^\\])([\{\[]|\([^\)]+$)/; +var escaped = /\\([\!\*\?\|\[\]\(\)\{\}])/g; -// `all` interleaves `stdout` and `stderr` -const makeAllStream = (spawned, {all}) => { - if (!all || (!spawned.stdout && !spawned.stderr)) { - return; - } +/** + * @param {string} str + * @param {Object} opts + * @param {boolean} [opts.flipBackslashes=true] + * @returns {string} + */ +module.exports = function globParent(str, opts) { + var options = Object.assign({ flipBackslashes: true }, opts); - const mixed = mergeStream(); + // flip windows path separators + if (options.flipBackslashes && isWin32 && str.indexOf(slash) < 0) { + str = str.replace(backslash, slash); + } - if (spawned.stdout) { - mixed.add(spawned.stdout); - } + // special case for strings ending in enclosure containing path separator + if (enclosure.test(str)) { + str += slash; + } - if (spawned.stderr) { - mixed.add(spawned.stderr); - } + // preserves full path in case of trailing path separator + str += 'a'; - return mixed; + // remove path parts that are globby + do { + str = pathPosixDirname(str); + } while (isGlob(str) || globby.test(str)); + + // remove escape chars and return result + return str.replace(escaped, '$1'); }; -// On failure, `result.stdout|stderr|all` should contain the currently buffered stream -const getBufferedData = async (stream, streamPromise) => { - if (!stream) { - return; - } - stream.destroy(); +/***/ }), - try { - return await streamPromise; - } catch (error) { - return error.bufferedData; - } -}; +/***/ 5042: +/***/ ((__unused_webpack_module, exports) => { -const getStreamPromise = (stream, {encoding, buffer, maxBuffer}) => { - if (!stream || !buffer) { - return; - } +Object.defineProperty(exports, "__esModule", ({value:true}));exports.SIGNALS=void 0; - if (encoding) { - return getStream(stream, {encoding, maxBuffer}); - } +const SIGNALS=[ +{ +name:"SIGHUP", +number:1, +action:"terminate", +description:"Terminal closed", +standard:"posix"}, - return getStream.buffer(stream, {maxBuffer}); -}; +{ +name:"SIGINT", +number:2, +action:"terminate", +description:"User interruption with CTRL-C", +standard:"ansi"}, -// Retrieve result of child process: exit code, signal, error, streams (stdout/stderr/all) -const getSpawnedResult = async ({stdout, stderr, all}, {encoding, buffer, maxBuffer}, processDone) => { - const stdoutPromise = getStreamPromise(stdout, {encoding, buffer, maxBuffer}); - const stderrPromise = getStreamPromise(stderr, {encoding, buffer, maxBuffer}); - const allPromise = getStreamPromise(all, {encoding, buffer, maxBuffer: maxBuffer * 2}); +{ +name:"SIGQUIT", +number:3, +action:"core", +description:"User interruption with CTRL-\\", +standard:"posix"}, - try { - return await Promise.all([processDone, stdoutPromise, stderrPromise, allPromise]); - } catch (error) { - return Promise.all([ - {error, signal: error.signal, timedOut: error.timedOut}, - getBufferedData(stdout, stdoutPromise), - getBufferedData(stderr, stderrPromise), - getBufferedData(all, allPromise) - ]); - } -}; +{ +name:"SIGILL", +number:4, +action:"core", +description:"Invalid machine instruction", +standard:"ansi"}, -const validateInputSync = ({input}) => { - if (isStream(input)) { - throw new TypeError('The `input` option cannot be a stream in sync mode'); - } -}; +{ +name:"SIGTRAP", +number:5, +action:"core", +description:"Debugger breakpoint", +standard:"posix"}, -module.exports = { - handleInput, - makeAllStream, - getSpawnedResult, - validateInputSync -}; +{ +name:"SIGABRT", +number:6, +action:"core", +description:"Aborted", +standard:"ansi"}, +{ +name:"SIGIOT", +number:6, +action:"core", +description:"Aborted", +standard:"bsd"}, +{ +name:"SIGBUS", +number:7, +action:"core", +description: +"Bus error due to misaligned, non-existing address or paging error", +standard:"bsd"}, -/***/ }), +{ +name:"SIGEMT", +number:7, +action:"terminate", +description:"Command should be emulated but is not implemented", +standard:"other"}, -/***/ 7469: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +{ +name:"SIGFPE", +number:8, +action:"core", +description:"Floating point arithmetic error", +standard:"ansi"}, -"use strict"; +{ +name:"SIGKILL", +number:9, +action:"terminate", +description:"Forced termination", +standard:"posix", +forced:true}, -const taskManager = __nccwpck_require__(8628); -const async_1 = __nccwpck_require__(5308); -const stream_1 = __nccwpck_require__(6654); -const sync_1 = __nccwpck_require__(6661); -const settings_1 = __nccwpck_require__(1392); -const utils = __nccwpck_require__(5439); -async function FastGlob(source, options) { - assertPatternsInput(source); - const works = getWorks(source, async_1.default, options); - const result = await Promise.all(works); - return utils.array.flatten(result); -} -// https://github.com/typescript-eslint/typescript-eslint/issues/60 -// eslint-disable-next-line no-redeclare -(function (FastGlob) { - FastGlob.glob = FastGlob; - FastGlob.globSync = sync; - FastGlob.globStream = stream; - FastGlob.async = FastGlob; - function sync(source, options) { - assertPatternsInput(source); - const works = getWorks(source, sync_1.default, options); - return utils.array.flatten(works); - } - FastGlob.sync = sync; - function stream(source, options) { - assertPatternsInput(source); - const works = getWorks(source, stream_1.default, options); - /** - * The stream returned by the provider cannot work with an asynchronous iterator. - * To support asynchronous iterators, regardless of the number of tasks, we always multiplex streams. - * This affects performance (+25%). I don't see best solution right now. - */ - return utils.stream.merge(works); - } - FastGlob.stream = stream; - function generateTasks(source, options) { - assertPatternsInput(source); - const patterns = [].concat(source); - const settings = new settings_1.default(options); - return taskManager.generate(patterns, settings); - } - FastGlob.generateTasks = generateTasks; - function isDynamicPattern(source, options) { - assertPatternsInput(source); - const settings = new settings_1.default(options); - return utils.pattern.isDynamicPattern(source, settings); - } - FastGlob.isDynamicPattern = isDynamicPattern; - function escapePath(source) { - assertPatternsInput(source); - return utils.path.escape(source); - } - FastGlob.escapePath = escapePath; - function convertPathToPattern(source) { - assertPatternsInput(source); - return utils.path.convertPathToPattern(source); - } - FastGlob.convertPathToPattern = convertPathToPattern; - let posix; - (function (posix) { - function escapePath(source) { - assertPatternsInput(source); - return utils.path.escapePosixPath(source); - } - posix.escapePath = escapePath; - function convertPathToPattern(source) { - assertPatternsInput(source); - return utils.path.convertPosixPathToPattern(source); - } - posix.convertPathToPattern = convertPathToPattern; - })(posix = FastGlob.posix || (FastGlob.posix = {})); - let win32; - (function (win32) { - function escapePath(source) { - assertPatternsInput(source); - return utils.path.escapeWindowsPath(source); - } - win32.escapePath = escapePath; - function convertPathToPattern(source) { - assertPatternsInput(source); - return utils.path.convertWindowsPathToPattern(source); - } - win32.convertPathToPattern = convertPathToPattern; - })(win32 = FastGlob.win32 || (FastGlob.win32 = {})); -})(FastGlob || (FastGlob = {})); -function getWorks(source, _Provider, options) { - const patterns = [].concat(source); - const settings = new settings_1.default(options); - const tasks = taskManager.generate(patterns, settings); - const provider = new _Provider(settings); - return tasks.map(provider.read, provider); -} -function assertPatternsInput(input) { - const source = [].concat(input); - const isValidSource = source.every((item) => utils.string.isString(item) && !utils.string.isEmpty(item)); - if (!isValidSource) { - throw new TypeError('Patterns must be a string (non empty) or an array of strings'); - } -} -module.exports = FastGlob; +{ +name:"SIGUSR1", +number:10, +action:"terminate", +description:"Application-specific signal", +standard:"posix"}, +{ +name:"SIGSEGV", +number:11, +action:"core", +description:"Segmentation fault", +standard:"ansi"}, -/***/ }), +{ +name:"SIGUSR2", +number:12, +action:"terminate", +description:"Application-specific signal", +standard:"posix"}, -/***/ 8628: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { +{ +name:"SIGPIPE", +number:13, +action:"terminate", +description:"Broken pipe or socket", +standard:"posix"}, -"use strict"; +{ +name:"SIGALRM", +number:14, +action:"terminate", +description:"Timeout or timer", +standard:"posix"}, -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.convertPatternGroupToTask = exports.convertPatternGroupsToTasks = exports.groupPatternsByBaseDirectory = exports.getNegativePatternsAsPositive = exports.getPositivePatterns = exports.convertPatternsToTasks = exports.generate = void 0; -const utils = __nccwpck_require__(5439); -function generate(input, settings) { - const patterns = processPatterns(input, settings); - const ignore = processPatterns(settings.ignore, settings); - const positivePatterns = getPositivePatterns(patterns); - const negativePatterns = getNegativePatternsAsPositive(patterns, ignore); - const staticPatterns = positivePatterns.filter((pattern) => utils.pattern.isStaticPattern(pattern, settings)); - const dynamicPatterns = positivePatterns.filter((pattern) => utils.pattern.isDynamicPattern(pattern, settings)); - const staticTasks = convertPatternsToTasks(staticPatterns, negativePatterns, /* dynamic */ false); - const dynamicTasks = convertPatternsToTasks(dynamicPatterns, negativePatterns, /* dynamic */ true); - return staticTasks.concat(dynamicTasks); -} -exports.generate = generate; -function processPatterns(input, settings) { - let patterns = input; - /** - * The original pattern like `{,*,**,a/*}` can lead to problems checking the depth when matching entry - * and some problems with the micromatch package (see fast-glob issues: #365, #394). - * - * To solve this problem, we expand all patterns containing brace expansion. This can lead to a slight slowdown - * in matching in the case of a large set of patterns after expansion. - */ - if (settings.braceExpansion) { - patterns = utils.pattern.expandPatternsWithBraceExpansion(patterns); - } - /** - * If the `baseNameMatch` option is enabled, we must add globstar to patterns, so that they can be used - * at any nesting level. - * - * We do this here, because otherwise we have to complicate the filtering logic. For example, we need to change - * the pattern in the filter before creating a regular expression. There is no need to change the patterns - * in the application. Only on the input. - */ - if (settings.baseNameMatch) { - patterns = patterns.map((pattern) => pattern.includes('/') ? pattern : `**/${pattern}`); - } - /** - * This method also removes duplicate slashes that may have been in the pattern or formed as a result of expansion. - */ - return patterns.map((pattern) => utils.pattern.removeDuplicateSlashes(pattern)); -} -/** - * Returns tasks grouped by basic pattern directories. - * - * Patterns that can be found inside (`./`) and outside (`../`) the current directory are handled separately. - * This is necessary because directory traversal starts at the base directory and goes deeper. - */ -function convertPatternsToTasks(positive, negative, dynamic) { - const tasks = []; - const patternsOutsideCurrentDirectory = utils.pattern.getPatternsOutsideCurrentDirectory(positive); - const patternsInsideCurrentDirectory = utils.pattern.getPatternsInsideCurrentDirectory(positive); - const outsideCurrentDirectoryGroup = groupPatternsByBaseDirectory(patternsOutsideCurrentDirectory); - const insideCurrentDirectoryGroup = groupPatternsByBaseDirectory(patternsInsideCurrentDirectory); - tasks.push(...convertPatternGroupsToTasks(outsideCurrentDirectoryGroup, negative, dynamic)); - /* - * For the sake of reducing future accesses to the file system, we merge all tasks within the current directory - * into a global task, if at least one pattern refers to the root (`.`). In this case, the global task covers the rest. - */ - if ('.' in insideCurrentDirectoryGroup) { - tasks.push(convertPatternGroupToTask('.', patternsInsideCurrentDirectory, negative, dynamic)); - } - else { - tasks.push(...convertPatternGroupsToTasks(insideCurrentDirectoryGroup, negative, dynamic)); - } - return tasks; -} -exports.convertPatternsToTasks = convertPatternsToTasks; -function getPositivePatterns(patterns) { - return utils.pattern.getPositivePatterns(patterns); -} -exports.getPositivePatterns = getPositivePatterns; -function getNegativePatternsAsPositive(patterns, ignore) { - const negative = utils.pattern.getNegativePatterns(patterns).concat(ignore); - const positive = negative.map(utils.pattern.convertToPositivePattern); - return positive; -} -exports.getNegativePatternsAsPositive = getNegativePatternsAsPositive; -function groupPatternsByBaseDirectory(patterns) { - const group = {}; - return patterns.reduce((collection, pattern) => { - const base = utils.pattern.getBaseDirectory(pattern); - if (base in collection) { - collection[base].push(pattern); - } - else { - collection[base] = [pattern]; - } - return collection; - }, group); -} -exports.groupPatternsByBaseDirectory = groupPatternsByBaseDirectory; -function convertPatternGroupsToTasks(positive, negative, dynamic) { - return Object.keys(positive).map((base) => { - return convertPatternGroupToTask(base, positive[base], negative, dynamic); - }); -} -exports.convertPatternGroupsToTasks = convertPatternGroupsToTasks; -function convertPatternGroupToTask(base, positive, negative, dynamic) { - return { - dynamic, - positive, - negative, - base, - patterns: [].concat(positive, negative.map(utils.pattern.convertToNegativePattern)) - }; -} -exports.convertPatternGroupToTask = convertPatternGroupToTask; +{ +name:"SIGTERM", +number:15, +action:"terminate", +description:"Termination", +standard:"ansi"}, +{ +name:"SIGSTKFLT", +number:16, +action:"terminate", +description:"Stack is empty or overflowed", +standard:"other"}, -/***/ }), +{ +name:"SIGCHLD", +number:17, +action:"ignore", +description:"Child process terminated, paused or unpaused", +standard:"posix"}, -/***/ 5308: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { +{ +name:"SIGCLD", +number:17, +action:"ignore", +description:"Child process terminated, paused or unpaused", +standard:"other"}, -"use strict"; +{ +name:"SIGCONT", +number:18, +action:"unpause", +description:"Unpaused", +standard:"posix", +forced:true}, -Object.defineProperty(exports, "__esModule", ({ value: true })); -const async_1 = __nccwpck_require__(54); -const provider_1 = __nccwpck_require__(9059); -class ProviderAsync extends provider_1.default { - constructor() { - super(...arguments); - this._reader = new async_1.default(this._settings); - } - async read(task) { - const root = this._getRootDirectory(task); - const options = this._getReaderOptions(task); - const entries = await this.api(root, task, options); - return entries.map((entry) => options.transform(entry)); - } - api(root, task, options) { - if (task.dynamic) { - return this._reader.dynamic(root, options); - } - return this._reader.static(task.patterns, options); - } -} -exports["default"] = ProviderAsync; +{ +name:"SIGSTOP", +number:19, +action:"pause", +description:"Paused", +standard:"posix", +forced:true}, +{ +name:"SIGTSTP", +number:20, +action:"pause", +description:"Paused using CTRL-Z or \"suspend\"", +standard:"posix"}, -/***/ }), +{ +name:"SIGTTIN", +number:21, +action:"pause", +description:"Background process cannot read terminal input", +standard:"posix"}, -/***/ 1952: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { +{ +name:"SIGBREAK", +number:21, +action:"terminate", +description:"User interruption with CTRL-BREAK", +standard:"other"}, -"use strict"; +{ +name:"SIGTTOU", +number:22, +action:"pause", +description:"Background process cannot write to terminal output", +standard:"posix"}, -Object.defineProperty(exports, "__esModule", ({ value: true })); -const utils = __nccwpck_require__(5439); -const partial_1 = __nccwpck_require__(2183); -class DeepFilter { - constructor(_settings, _micromatchOptions) { - this._settings = _settings; - this._micromatchOptions = _micromatchOptions; - } - getFilter(basePath, positive, negative) { - const matcher = this._getMatcher(positive); - const negativeRe = this._getNegativePatternsRe(negative); - return (entry) => this._filter(basePath, entry, matcher, negativeRe); - } - _getMatcher(patterns) { - return new partial_1.default(patterns, this._settings, this._micromatchOptions); - } - _getNegativePatternsRe(patterns) { - const affectDepthOfReadingPatterns = patterns.filter(utils.pattern.isAffectDepthOfReadingPattern); - return utils.pattern.convertPatternsToRe(affectDepthOfReadingPatterns, this._micromatchOptions); - } - _filter(basePath, entry, matcher, negativeRe) { - if (this._isSkippedByDeep(basePath, entry.path)) { - return false; - } - if (this._isSkippedSymbolicLink(entry)) { - return false; - } - const filepath = utils.path.removeLeadingDotSegment(entry.path); - if (this._isSkippedByPositivePatterns(filepath, matcher)) { - return false; - } - return this._isSkippedByNegativePatterns(filepath, negativeRe); - } - _isSkippedByDeep(basePath, entryPath) { - /** - * Avoid unnecessary depth calculations when it doesn't matter. - */ - if (this._settings.deep === Infinity) { - return false; - } - return this._getEntryLevel(basePath, entryPath) >= this._settings.deep; - } - _getEntryLevel(basePath, entryPath) { - const entryPathDepth = entryPath.split('/').length; - if (basePath === '') { - return entryPathDepth; - } - const basePathDepth = basePath.split('/').length; - return entryPathDepth - basePathDepth; - } - _isSkippedSymbolicLink(entry) { - return !this._settings.followSymbolicLinks && entry.dirent.isSymbolicLink(); - } - _isSkippedByPositivePatterns(entryPath, matcher) { - return !this._settings.baseNameMatch && !matcher.match(entryPath); - } - _isSkippedByNegativePatterns(entryPath, patternsRe) { - return !utils.pattern.matchAny(entryPath, patternsRe); - } -} -exports["default"] = DeepFilter; +{ +name:"SIGURG", +number:23, +action:"ignore", +description:"Socket received out-of-band data", +standard:"bsd"}, +{ +name:"SIGXCPU", +number:24, +action:"core", +description:"Process timed out", +standard:"bsd"}, -/***/ }), +{ +name:"SIGXFSZ", +number:25, +action:"core", +description:"File too big", +standard:"bsd"}, -/***/ 9772: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { +{ +name:"SIGVTALRM", +number:26, +action:"terminate", +description:"Timeout or timer", +standard:"bsd"}, -"use strict"; +{ +name:"SIGPROF", +number:27, +action:"terminate", +description:"Timeout or timer", +standard:"bsd"}, -Object.defineProperty(exports, "__esModule", ({ value: true })); -const utils = __nccwpck_require__(5439); -class EntryFilter { - constructor(_settings, _micromatchOptions) { - this._settings = _settings; - this._micromatchOptions = _micromatchOptions; - this.index = new Map(); - } - getFilter(positive, negative) { - const [absoluteNegative, relativeNegative] = utils.pattern.partitionAbsoluteAndRelative(negative); - const patterns = { - positive: { - all: utils.pattern.convertPatternsToRe(positive, this._micromatchOptions) - }, - negative: { - absolute: utils.pattern.convertPatternsToRe(absoluteNegative, Object.assign(Object.assign({}, this._micromatchOptions), { dot: true })), - relative: utils.pattern.convertPatternsToRe(relativeNegative, Object.assign(Object.assign({}, this._micromatchOptions), { dot: true })) - } - }; - return (entry) => this._filter(entry, patterns); - } - _filter(entry, patterns) { - const filepath = utils.path.removeLeadingDotSegment(entry.path); - if (this._settings.unique && this._isDuplicateEntry(filepath)) { - return false; - } - if (this._onlyFileFilter(entry) || this._onlyDirectoryFilter(entry)) { - return false; - } - const isMatched = this._isMatchToPatternsSet(filepath, patterns, entry.dirent.isDirectory()); - if (this._settings.unique && isMatched) { - this._createIndexRecord(filepath); - } - return isMatched; - } - _isDuplicateEntry(filepath) { - return this.index.has(filepath); - } - _createIndexRecord(filepath) { - this.index.set(filepath, undefined); - } - _onlyFileFilter(entry) { - return this._settings.onlyFiles && !entry.dirent.isFile(); - } - _onlyDirectoryFilter(entry) { - return this._settings.onlyDirectories && !entry.dirent.isDirectory(); - } - _isMatchToPatternsSet(filepath, patterns, isDirectory) { - const isMatched = this._isMatchToPatterns(filepath, patterns.positive.all, isDirectory); - if (!isMatched) { - return false; - } - const isMatchedByRelativeNegative = this._isMatchToPatterns(filepath, patterns.negative.relative, isDirectory); - if (isMatchedByRelativeNegative) { - return false; - } - const isMatchedByAbsoluteNegative = this._isMatchToAbsoluteNegative(filepath, patterns.negative.absolute, isDirectory); - if (isMatchedByAbsoluteNegative) { - return false; - } - return true; - } - _isMatchToAbsoluteNegative(filepath, patternsRe, isDirectory) { - if (patternsRe.length === 0) { - return false; - } - const fullpath = utils.path.makeAbsolute(this._settings.cwd, filepath); - return this._isMatchToPatterns(fullpath, patternsRe, isDirectory); - } - _isMatchToPatterns(filepath, patternsRe, isDirectory) { - if (patternsRe.length === 0) { - return false; - } - // Trying to match files and directories by patterns. - const isMatched = utils.pattern.matchAny(filepath, patternsRe); - // A pattern with a trailling slash can be used for directory matching. - // To apply such pattern, we need to add a tralling slash to the path. - if (!isMatched && isDirectory) { - return utils.pattern.matchAny(filepath + '/', patternsRe); - } - return isMatched; - } -} -exports["default"] = EntryFilter; +{ +name:"SIGWINCH", +number:28, +action:"ignore", +description:"Terminal window size changed", +standard:"bsd"}, + +{ +name:"SIGIO", +number:29, +action:"terminate", +description:"I/O is available", +standard:"other"}, + +{ +name:"SIGPOLL", +number:29, +action:"terminate", +description:"Watched event", +standard:"other"}, + +{ +name:"SIGINFO", +number:29, +action:"ignore", +description:"Request for process information", +standard:"other"}, + +{ +name:"SIGPWR", +number:30, +action:"terminate", +description:"Device running out of power", +standard:"systemv"}, + +{ +name:"SIGSYS", +number:31, +action:"core", +description:"Invalid system call", +standard:"other"}, +{ +name:"SIGUNUSED", +number:31, +action:"terminate", +description:"Invalid system call", +standard:"other"}];exports.SIGNALS=SIGNALS; +//# sourceMappingURL=core.js.map /***/ }), -/***/ 3710: +/***/ 4796: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { -"use strict"; +Object.defineProperty(exports, "__esModule", ({value:true}));exports.signalsByNumber=exports.signalsByName=void 0;var _os=__nccwpck_require__(857); -Object.defineProperty(exports, "__esModule", ({ value: true })); -const utils = __nccwpck_require__(5439); -class ErrorFilter { - constructor(_settings) { - this._settings = _settings; - } - getFilter() { - return (error) => this._isNonFatalError(error); - } - _isNonFatalError(error) { - return utils.errno.isEnoentCodeError(error) || this._settings.suppressErrors; - } -} -exports["default"] = ErrorFilter; +var _signals=__nccwpck_require__(5252); +var _realtime=__nccwpck_require__(388); -/***/ }), -/***/ 9128: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { +const getSignalsByName=function(){ +const signals=(0,_signals.getSignals)(); +return signals.reduce(getSignalByName,{}); +}; -"use strict"; +const getSignalByName=function( +signalByNameMemo, +{name,number,description,supported,action,forced,standard}) +{ +return{ +...signalByNameMemo, +[name]:{name,number,description,supported,action,forced,standard}}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -const utils = __nccwpck_require__(5439); -class Matcher { - constructor(_patterns, _settings, _micromatchOptions) { - this._patterns = _patterns; - this._settings = _settings; - this._micromatchOptions = _micromatchOptions; - this._storage = []; - this._fillStorage(); - } - _fillStorage() { - for (const pattern of this._patterns) { - const segments = this._getPatternSegments(pattern); - const sections = this._splitSegmentsIntoSections(segments); - this._storage.push({ - complete: sections.length <= 1, - pattern, - segments, - sections - }); - } - } - _getPatternSegments(pattern) { - const parts = utils.pattern.getPatternParts(pattern, this._micromatchOptions); - return parts.map((part) => { - const dynamic = utils.pattern.isDynamicPattern(part, this._settings); - if (!dynamic) { - return { - dynamic: false, - pattern: part - }; - } - return { - dynamic: true, - pattern: part, - patternRe: utils.pattern.makeRe(part, this._micromatchOptions) - }; - }); - } - _splitSegmentsIntoSections(segments) { - return utils.array.splitWhen(segments, (segment) => segment.dynamic && utils.pattern.hasGlobStar(segment.pattern)); - } -} -exports["default"] = Matcher; +}; +const signalsByName=getSignalsByName();exports.signalsByName=signalsByName; -/***/ }), -/***/ 2183: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { -"use strict"; -Object.defineProperty(exports, "__esModule", ({ value: true })); -const matcher_1 = __nccwpck_require__(9128); -class PartialMatcher extends matcher_1.default { - match(filepath) { - const parts = filepath.split('/'); - const levels = parts.length; - const patterns = this._storage.filter((info) => !info.complete || info.segments.length > levels); - for (const pattern of patterns) { - const section = pattern.sections[0]; - /** - * In this case, the pattern has a globstar and we must read all directories unconditionally, - * but only if the level has reached the end of the first group. - * - * fixtures/{a,b}/** - * ^ true/false ^ always true - */ - if (!pattern.complete && levels > section.length) { - return true; - } - const match = parts.every((part, index) => { - const segment = pattern.segments[index]; - if (segment.dynamic && segment.patternRe.test(part)) { - return true; - } - if (!segment.dynamic && segment.pattern === part) { - return true; - } - return false; - }); - if (match) { - return true; - } - } - return false; - } -} -exports["default"] = PartialMatcher; +const getSignalsByNumber=function(){ +const signals=(0,_signals.getSignals)(); +const length=_realtime.SIGRTMAX+1; +const signalsA=Array.from({length},(value,number)=> +getSignalByNumber(number,signals)); +return Object.assign({},...signalsA); +}; -/***/ }), +const getSignalByNumber=function(number,signals){ +const signal=findSignalByNumber(number,signals); -/***/ 9059: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { +if(signal===undefined){ +return{}; +} -"use strict"; +const{name,description,supported,action,forced,standard}=signal; +return{ +[number]:{ +name, +number, +description, +supported, +action, +forced, +standard}}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -const path = __nccwpck_require__(6928); -const deep_1 = __nccwpck_require__(1952); -const entry_1 = __nccwpck_require__(9772); -const error_1 = __nccwpck_require__(3710); -const entry_2 = __nccwpck_require__(3173); -class Provider { - constructor(_settings) { - this._settings = _settings; - this.errorFilter = new error_1.default(this._settings); - this.entryFilter = new entry_1.default(this._settings, this._getMicromatchOptions()); - this.deepFilter = new deep_1.default(this._settings, this._getMicromatchOptions()); - this.entryTransformer = new entry_2.default(this._settings); - } - _getRootDirectory(task) { - return path.resolve(this._settings.cwd, task.base); - } - _getReaderOptions(task) { - const basePath = task.base === '.' ? '' : task.base; - return { - basePath, - pathSegmentSeparator: '/', - concurrency: this._settings.concurrency, - deepFilter: this.deepFilter.getFilter(basePath, task.positive, task.negative), - entryFilter: this.entryFilter.getFilter(task.positive, task.negative), - errorFilter: this.errorFilter.getFilter(), - followSymbolicLinks: this._settings.followSymbolicLinks, - fs: this._settings.fs, - stats: this._settings.stats, - throwErrorOnBrokenSymbolicLink: this._settings.throwErrorOnBrokenSymbolicLink, - transform: this.entryTransformer.getTransformer() - }; - } - _getMicromatchOptions() { - return { - dot: this._settings.dot, - matchBase: this._settings.baseNameMatch, - nobrace: !this._settings.braceExpansion, - nocase: !this._settings.caseSensitiveMatch, - noext: !this._settings.extglob, - noglobstar: !this._settings.globstar, - posix: true, - strictSlashes: false - }; - } -} -exports["default"] = Provider; +}; -/***/ }), -/***/ 6654: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { -"use strict"; +const findSignalByNumber=function(number,signals){ +const signal=signals.find(({name})=>_os.constants.signals[name]===number); -Object.defineProperty(exports, "__esModule", ({ value: true })); -const stream_1 = __nccwpck_require__(2203); -const stream_2 = __nccwpck_require__(7720); -const provider_1 = __nccwpck_require__(9059); -class ProviderStream extends provider_1.default { - constructor() { - super(...arguments); - this._reader = new stream_2.default(this._settings); - } - read(task) { - const root = this._getRootDirectory(task); - const options = this._getReaderOptions(task); - const source = this.api(root, task, options); - const destination = new stream_1.Readable({ objectMode: true, read: () => { } }); - source - .once('error', (error) => destination.emit('error', error)) - .on('data', (entry) => destination.emit('data', options.transform(entry))) - .once('end', () => destination.emit('end')); - destination - .once('close', () => source.destroy()); - return destination; - } - api(root, task, options) { - if (task.dynamic) { - return this._reader.dynamic(root, options); - } - return this._reader.static(task.patterns, options); - } +if(signal!==undefined){ +return signal; } -exports["default"] = ProviderStream; +return signals.find(signalA=>signalA.number===number); +}; + +const signalsByNumber=getSignalsByNumber();exports.signalsByNumber=signalsByNumber; +//# sourceMappingURL=main.js.map /***/ }), -/***/ 6661: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { +/***/ 388: +/***/ ((__unused_webpack_module, exports) => { -"use strict"; +Object.defineProperty(exports, "__esModule", ({value:true}));exports.SIGRTMAX=exports.getRealtimeSignals=void 0; +const getRealtimeSignals=function(){ +const length=SIGRTMAX-SIGRTMIN+1; +return Array.from({length},getRealtimeSignal); +};exports.getRealtimeSignals=getRealtimeSignals; -Object.defineProperty(exports, "__esModule", ({ value: true })); -const sync_1 = __nccwpck_require__(5203); -const provider_1 = __nccwpck_require__(9059); -class ProviderSync extends provider_1.default { - constructor() { - super(...arguments); - this._reader = new sync_1.default(this._settings); - } - read(task) { - const root = this._getRootDirectory(task); - const options = this._getReaderOptions(task); - const entries = this.api(root, task, options); - return entries.map(options.transform); - } - api(root, task, options) { - if (task.dynamic) { - return this._reader.dynamic(root, options); - } - return this._reader.static(task.patterns, options); - } -} -exports["default"] = ProviderSync; +const getRealtimeSignal=function(value,index){ +return{ +name:`SIGRT${index+1}`, +number:SIGRTMIN+index, +action:"terminate", +description:"Application-specific signal (realtime)", +standard:"posix"}; +}; + +const SIGRTMIN=34; +const SIGRTMAX=64;exports.SIGRTMAX=SIGRTMAX; +//# sourceMappingURL=realtime.js.map /***/ }), -/***/ 3173: +/***/ 5252: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -const utils = __nccwpck_require__(5439); -class EntryTransformer { - constructor(_settings) { - this._settings = _settings; - } - getTransformer() { - return (entry) => this._transform(entry); - } - _transform(entry) { - let filepath = entry.path; - if (this._settings.absolute) { - filepath = utils.path.makeAbsolute(this._settings.cwd, filepath); - filepath = utils.path.unixify(filepath); - } - if (this._settings.markDirectories && entry.dirent.isDirectory()) { - filepath += '/'; - } - if (!this._settings.objectMode) { - return filepath; - } - return Object.assign(Object.assign({}, entry), { path: filepath }); - } -} -exports["default"] = EntryTransformer; +Object.defineProperty(exports, "__esModule", ({value:true}));exports.getSignals=void 0;var _os=__nccwpck_require__(857); +var _core=__nccwpck_require__(5042); +var _realtime=__nccwpck_require__(388); -/***/ }), -/***/ 54: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { -"use strict"; +const getSignals=function(){ +const realtimeSignals=(0,_realtime.getRealtimeSignals)(); +const signals=[..._core.SIGNALS,...realtimeSignals].map(normalizeSignal); +return signals; +};exports.getSignals=getSignals; -Object.defineProperty(exports, "__esModule", ({ value: true })); -const fsWalk = __nccwpck_require__(2552); -const reader_1 = __nccwpck_require__(6187); -const stream_1 = __nccwpck_require__(7720); -class ReaderAsync extends reader_1.default { - constructor() { - super(...arguments); - this._walkAsync = fsWalk.walk; - this._readerStream = new stream_1.default(this._settings); - } - dynamic(root, options) { - return new Promise((resolve, reject) => { - this._walkAsync(root, options, (error, entries) => { - if (error === null) { - resolve(entries); - } - else { - reject(error); - } - }); - }); - } - async static(patterns, options) { - const entries = []; - const stream = this._readerStream.static(patterns, options); - // After #235, replace it with an asynchronous iterator. - return new Promise((resolve, reject) => { - stream.once('error', reject); - stream.on('data', (entry) => entries.push(entry)); - stream.once('end', () => resolve(entries)); - }); - } -} -exports["default"] = ReaderAsync; -/***/ }), -/***/ 6187: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { -"use strict"; -Object.defineProperty(exports, "__esModule", ({ value: true })); -const path = __nccwpck_require__(6928); -const fsStat = __nccwpck_require__(3824); -const utils = __nccwpck_require__(5439); -class Reader { - constructor(_settings) { - this._settings = _settings; - this._fsStatSettings = new fsStat.Settings({ - followSymbolicLink: this._settings.followSymbolicLinks, - fs: this._settings.fs, - throwErrorOnBrokenSymbolicLink: this._settings.followSymbolicLinks - }); - } - _getFullEntryPath(filepath) { - return path.resolve(this._settings.cwd, filepath); - } - _makeEntry(stats, pattern) { - const entry = { - name: pattern, - path: pattern, - dirent: utils.fs.createDirentFromStats(pattern, stats) - }; - if (this._settings.stats) { - entry.stats = stats; - } - return entry; - } - _isFatalError(error) { - return !utils.errno.isEnoentCodeError(error) && !this._settings.suppressErrors; - } -} -exports["default"] = Reader; +const normalizeSignal=function({ +name, +number:defaultNumber, +description, +action, +forced=false, +standard}) +{ +const{ +signals:{[name]:constantSignal}}= +_os.constants; +const supported=constantSignal!==undefined; +const number=supported?constantSignal:defaultNumber; +return{name,number,description,supported,action,forced,standard}; +}; +//# sourceMappingURL=signals.js.map /***/ }), -/***/ 7720: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; +/***/ 7261: +/***/ ((module) => { -Object.defineProperty(exports, "__esModule", ({ value: true })); -const stream_1 = __nccwpck_require__(2203); -const fsStat = __nccwpck_require__(3824); -const fsWalk = __nccwpck_require__(2552); -const reader_1 = __nccwpck_require__(6187); -class ReaderStream extends reader_1.default { - constructor() { - super(...arguments); - this._walkStream = fsWalk.walkStream; - this._stat = fsStat.stat; - } - dynamic(root, options) { - return this._walkStream(root, options); - } - static(patterns, options) { - const filepaths = patterns.map(this._getFullEntryPath, this); - const stream = new stream_1.PassThrough({ objectMode: true }); - stream._write = (index, _enc, done) => { - return this._getEntry(filepaths[index], patterns[index], options) - .then((entry) => { - if (entry !== null && options.entryFilter(entry)) { - stream.push(entry); - } - if (index === filepaths.length - 1) { - stream.end(); - } - done(); - }) - .catch(done); - }; - for (let i = 0; i < filepaths.length; i++) { - stream.write(i); - } - return stream; - } - _getEntry(filepath, pattern, options) { - return this._getStat(filepath) - .then((stats) => this._makeEntry(stats, pattern)) - .catch((error) => { - if (options.errorFilter(error)) { - return null; - } - throw error; - }); - } - _getStat(filepath) { - return new Promise((resolve, reject) => { - this._stat(filepath, this._fsStatSettings, (error, stats) => { - return error === null ? resolve(stats) : reject(error); - }); - }); - } +// A simple implementation of make-array +function makeArray (subject) { + return Array.isArray(subject) + ? subject + : [subject] } -exports["default"] = ReaderStream; +const UNDEFINED = undefined +const EMPTY = '' +const SPACE = ' ' +const ESCAPE = '\\' +const REGEX_TEST_BLANK_LINE = /^\s+$/ +const REGEX_INVALID_TRAILING_BACKSLASH = /(?:[^\\]|^)\\$/ +const REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION = /^\\!/ +const REGEX_REPLACE_LEADING_EXCAPED_HASH = /^\\#/ +const REGEX_SPLITALL_CRLF = /\r?\n/g -/***/ }), +// Invalid: +// - /foo, +// - ./foo, +// - ../foo, +// - . +// - .. +// Valid: +// - .foo +const REGEX_TEST_INVALID_PATH = /^\.{0,2}\/|^\.{1,2}$/ -/***/ 5203: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { +const REGEX_TEST_TRAILING_SLASH = /\/$/ -"use strict"; +const SLASH = '/' -Object.defineProperty(exports, "__esModule", ({ value: true })); -const fsStat = __nccwpck_require__(3824); -const fsWalk = __nccwpck_require__(2552); -const reader_1 = __nccwpck_require__(6187); -class ReaderSync extends reader_1.default { - constructor() { - super(...arguments); - this._walkSync = fsWalk.walkSync; - this._statSync = fsStat.statSync; - } - dynamic(root, options) { - return this._walkSync(root, options); - } - static(patterns, options) { - const entries = []; - for (const pattern of patterns) { - const filepath = this._getFullEntryPath(pattern); - const entry = this._getEntry(filepath, pattern, options); - if (entry === null || !options.entryFilter(entry)) { - continue; - } - entries.push(entry); - } - return entries; - } - _getEntry(filepath, pattern, options) { - try { - const stats = this._getStat(filepath); - return this._makeEntry(stats, pattern); - } - catch (error) { - if (options.errorFilter(error)) { - return null; - } - throw error; - } - } - _getStat(filepath) { - return this._statSync(filepath, this._fsStatSettings); - } +// Do not use ternary expression here, since "istanbul ignore next" is buggy +let TMP_KEY_IGNORE = 'node-ignore' +/* istanbul ignore else */ +if (typeof Symbol !== 'undefined') { + TMP_KEY_IGNORE = Symbol.for('node-ignore') } -exports["default"] = ReaderSync; +const KEY_IGNORE = TMP_KEY_IGNORE +const define = (object, key, value) => { + Object.defineProperty(object, key, {value}) + return value +} -/***/ }), +const REGEX_REGEXP_RANGE = /([0-z])-([0-z])/g -/***/ 1392: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { +const RETURN_FALSE = () => false -"use strict"; +// Sanitize the range of a regular expression +// The cases are complicated, see test cases for details +const sanitizeRange = range => range.replace( + REGEX_REGEXP_RANGE, + (match, from, to) => from.charCodeAt(0) <= to.charCodeAt(0) + ? match + // Invalid range (out of order) which is ok for gitignore rules but + // fatal for JavaScript regular expression, so eliminate it. + : EMPTY +) -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.DEFAULT_FILE_SYSTEM_ADAPTER = void 0; -const fs = __nccwpck_require__(9896); -const os = __nccwpck_require__(857); -/** - * The `os.cpus` method can return zero. We expect the number of cores to be greater than zero. - * https://github.com/nodejs/node/blob/7faeddf23a98c53896f8b574a6e66589e8fb1eb8/lib/os.js#L106-L107 - */ -const CPU_COUNT = Math.max(os.cpus().length, 1); -exports.DEFAULT_FILE_SYSTEM_ADAPTER = { - lstat: fs.lstat, - lstatSync: fs.lstatSync, - stat: fs.stat, - statSync: fs.statSync, - readdir: fs.readdir, - readdirSync: fs.readdirSync -}; -class Settings { - constructor(_options = {}) { - this._options = _options; - this.absolute = this._getValue(this._options.absolute, false); - this.baseNameMatch = this._getValue(this._options.baseNameMatch, false); - this.braceExpansion = this._getValue(this._options.braceExpansion, true); - this.caseSensitiveMatch = this._getValue(this._options.caseSensitiveMatch, true); - this.concurrency = this._getValue(this._options.concurrency, CPU_COUNT); - this.cwd = this._getValue(this._options.cwd, process.cwd()); - this.deep = this._getValue(this._options.deep, Infinity); - this.dot = this._getValue(this._options.dot, false); - this.extglob = this._getValue(this._options.extglob, true); - this.followSymbolicLinks = this._getValue(this._options.followSymbolicLinks, true); - this.fs = this._getFileSystemMethods(this._options.fs); - this.globstar = this._getValue(this._options.globstar, true); - this.ignore = this._getValue(this._options.ignore, []); - this.markDirectories = this._getValue(this._options.markDirectories, false); - this.objectMode = this._getValue(this._options.objectMode, false); - this.onlyDirectories = this._getValue(this._options.onlyDirectories, false); - this.onlyFiles = this._getValue(this._options.onlyFiles, true); - this.stats = this._getValue(this._options.stats, false); - this.suppressErrors = this._getValue(this._options.suppressErrors, false); - this.throwErrorOnBrokenSymbolicLink = this._getValue(this._options.throwErrorOnBrokenSymbolicLink, false); - this.unique = this._getValue(this._options.unique, true); - if (this.onlyDirectories) { - this.onlyFiles = false; - } - if (this.stats) { - this.objectMode = true; - } - // Remove the cast to the array in the next major (#404). - this.ignore = [].concat(this.ignore); - } - _getValue(option, value) { - return option === undefined ? value : option; - } - _getFileSystemMethods(methods = {}) { - return Object.assign(Object.assign({}, exports.DEFAULT_FILE_SYSTEM_ADAPTER), methods); - } +// See fixtures #59 +const cleanRangeBackSlash = slashes => { + const {length} = slashes + return slashes.slice(0, length - length % 2) } -exports["default"] = Settings; +// > If the pattern ends with a slash, +// > it is removed for the purpose of the following description, +// > but it would only find a match with a directory. +// > In other words, foo/ will match a directory foo and paths underneath it, +// > but will not match a regular file or a symbolic link foo +// > (this is consistent with the way how pathspec works in general in Git). +// '`foo/`' will not match regular file '`foo`' or symbolic link '`foo`' +// -> ignore-rules will not deal with it, because it costs extra `fs.stat` call +// you could use option `mark: true` with `glob` -/***/ }), +// '`foo/`' should not continue with the '`..`' +const REPLACERS = [ -/***/ 9418: -/***/ ((__unused_webpack_module, exports) => { + [ + // Remove BOM + // TODO: + // Other similar zero-width characters? + /^\uFEFF/, + () => EMPTY + ], -"use strict"; + // > Trailing spaces are ignored unless they are quoted with backslash ("\") + [ + // (a\ ) -> (a ) + // (a ) -> (a) + // (a ) -> (a) + // (a \ ) -> (a ) + /((?:\\\\)*?)(\\?\s+)$/, + (_, m1, m2) => m1 + ( + m2.indexOf('\\') === 0 + ? SPACE + : EMPTY + ) + ], -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.splitWhen = exports.flatten = void 0; -function flatten(items) { - return items.reduce((collection, item) => [].concat(collection, item), []); -} -exports.flatten = flatten; -function splitWhen(items, predicate) { - const result = [[]]; - let groupIndex = 0; - for (const item of items) { - if (predicate(item)) { - groupIndex++; - result[groupIndex] = []; - } - else { - result[groupIndex].push(item); - } + // Replace (\ ) with ' ' + // (\ ) -> ' ' + // (\\ ) -> '\\ ' + // (\\\ ) -> '\\ ' + [ + /(\\+?)\s/g, + (_, m1) => { + const {length} = m1 + return m1.slice(0, length - length % 2) + SPACE } - return result; -} -exports.splitWhen = splitWhen; + ], + // Escape metacharacters + // which is written down by users but means special for regular expressions. -/***/ }), + // > There are 12 characters with special meanings: + // > - the backslash \, + // > - the caret ^, + // > - the dollar sign $, + // > - the period or dot ., + // > - the vertical bar or pipe symbol |, + // > - the question mark ?, + // > - the asterisk or star *, + // > - the plus sign +, + // > - the opening parenthesis (, + // > - the closing parenthesis ), + // > - and the opening square bracket [, + // > - the opening curly brace {, + // > These special characters are often called "metacharacters". + [ + /[\\$.|*+(){^]/g, + match => `\\${match}` + ], -/***/ 2903: -/***/ ((__unused_webpack_module, exports) => { + [ + // > a question mark (?) matches a single character + /(?!\\)\?/g, + () => '[^/]' + ], -"use strict"; + // leading slash + [ -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.isEnoentCodeError = void 0; -function isEnoentCodeError(error) { - return error.code === 'ENOENT'; -} -exports.isEnoentCodeError = isEnoentCodeError; + // > A leading slash matches the beginning of the pathname. + // > For example, "/*.c" matches "cat-file.c" but not "mozilla-sha1/sha1.c". + // A leading slash matches the beginning of the pathname + /^\//, + () => '^' + ], + // replace special metacharacter slash after the leading slash + [ + /\//g, + () => '\\/' + ], -/***/ }), + [ + // > A leading "**" followed by a slash means match in all directories. + // > For example, "**/foo" matches file or directory "foo" anywhere, + // > the same as pattern "foo". + // > "**/foo/bar" matches file or directory "bar" anywhere that is directly + // > under directory "foo". + // Notice that the '*'s have been replaced as '\\*' + /^\^*\\\*\\\*\\\//, -/***/ 4148: -/***/ ((__unused_webpack_module, exports) => { + // '**/foo' <-> 'foo' + () => '^(?:.*\\/)?' + ], + + // starting + [ + // there will be no leading '/' + // (which has been replaced by section "leading slash") + // If starts with '**', adding a '^' to the regular expression also works + /^(?=[^^])/, + function startingReplacer () { + // If has a slash `/` at the beginning or middle + return !/\/(?!$)/.test(this) + // > Prior to 2.22.1 + // > If the pattern does not contain a slash /, + // > Git treats it as a shell glob pattern + // Actually, if there is only a trailing slash, + // git also treats it as a shell glob pattern -"use strict"; + // After 2.22.1 (compatible but clearer) + // > If there is a separator at the beginning or middle (or both) + // > of the pattern, then the pattern is relative to the directory + // > level of the particular .gitignore file itself. + // > Otherwise the pattern may also match at any level below + // > the .gitignore level. + ? '(?:^|\\/)' -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.createDirentFromStats = void 0; -class DirentFromStats { - constructor(name, stats) { - this.name = name; - this.isBlockDevice = stats.isBlockDevice.bind(stats); - this.isCharacterDevice = stats.isCharacterDevice.bind(stats); - this.isDirectory = stats.isDirectory.bind(stats); - this.isFIFO = stats.isFIFO.bind(stats); - this.isFile = stats.isFile.bind(stats); - this.isSocket = stats.isSocket.bind(stats); - this.isSymbolicLink = stats.isSymbolicLink.bind(stats); + // > Otherwise, Git treats the pattern as a shell glob suitable for + // > consumption by fnmatch(3) + : '^' } -} -function createDirentFromStats(name, stats) { - return new DirentFromStats(name, stats); -} -exports.createDirentFromStats = createDirentFromStats; - + ], -/***/ }), + // two globstars + [ + // Use lookahead assertions so that we could match more than one `'/**'` + /\\\/\\\*\\\*(?=\\\/|$)/g, -/***/ 5439: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + // Zero, one or several directories + // should not use '*', or it will be replaced by the next replacer -"use strict"; + // Check if it is not the last `'/**'` + (_, index, str) => index + 6 < str.length -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.string = exports.stream = exports.pattern = exports.path = exports.fs = exports.errno = exports.array = void 0; -const array = __nccwpck_require__(9418); -exports.array = array; -const errno = __nccwpck_require__(2903); -exports.errno = errno; -const fs = __nccwpck_require__(4148); -exports.fs = fs; -const path = __nccwpck_require__(2656); -exports.path = path; -const pattern = __nccwpck_require__(3433); -exports.pattern = pattern; -const stream = __nccwpck_require__(2411); -exports.stream = stream; -const string = __nccwpck_require__(4062); -exports.string = string; + // case: /**/ + // > A slash followed by two consecutive asterisks then a slash matches + // > zero or more directories. + // > For example, "a/**/b" matches "a/b", "a/x/b", "a/x/y/b" and so on. + // '/**/' + ? '(?:\\/[^\\/]+)*' + // case: /** + // > A trailing `"/**"` matches everything inside. -/***/ }), + // #21: everything inside but it should not include the current folder + : '\\/.+' + ], -/***/ 2656: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + // normal intermediate wildcards + [ + // Never replace escaped '*' + // ignore rule '\*' will match the path '*' -"use strict"; + // 'abc.*/' -> go + // 'abc.*' -> skip this rule, + // coz trailing single wildcard will be handed by [trailing wildcard] + /(^|[^\\]+)(\\\*)+(?=.+)/g, -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.convertPosixPathToPattern = exports.convertWindowsPathToPattern = exports.convertPathToPattern = exports.escapePosixPath = exports.escapeWindowsPath = exports.escape = exports.removeLeadingDotSegment = exports.makeAbsolute = exports.unixify = void 0; -const os = __nccwpck_require__(857); -const path = __nccwpck_require__(6928); -const IS_WINDOWS_PLATFORM = os.platform() === 'win32'; -const LEADING_DOT_SEGMENT_CHARACTERS_COUNT = 2; // ./ or .\\ -/** - * All non-escaped special characters. - * Posix: ()*?[]{|}, !+@ before (, ! at the beginning, \\ before non-special characters. - * Windows: (){}[], !+@ before (, ! at the beginning. - */ -const POSIX_UNESCAPED_GLOB_SYMBOLS_RE = /(\\?)([()*?[\]{|}]|^!|[!+@](?=\()|\\(?![!()*+?@[\]{|}]))/g; -const WINDOWS_UNESCAPED_GLOB_SYMBOLS_RE = /(\\?)([()[\]{}]|^!|[!+@](?=\())/g; -/** - * The device path (\\.\ or \\?\). - * https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats#dos-device-paths - */ -const DOS_DEVICE_PATH_RE = /^\\\\([.?])/; -/** - * All backslashes except those escaping special characters. - * Windows: !()+@{} - * https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file#naming-conventions - */ -const WINDOWS_BACKSLASHES_RE = /\\(?![!()+@[\]{}])/g; -/** - * Designed to work only with simple paths: `dir\\file`. - */ -function unixify(filepath) { - return filepath.replace(/\\/g, '/'); -} -exports.unixify = unixify; -function makeAbsolute(cwd, filepath) { - return path.resolve(cwd, filepath); -} -exports.makeAbsolute = makeAbsolute; -function removeLeadingDotSegment(entry) { - // We do not use `startsWith` because this is 10x slower than current implementation for some cases. - // eslint-disable-next-line @typescript-eslint/prefer-string-starts-ends-with - if (entry.charAt(0) === '.') { - const secondCharactery = entry.charAt(1); - if (secondCharactery === '/' || secondCharactery === '\\') { - return entry.slice(LEADING_DOT_SEGMENT_CHARACTERS_COUNT); - } + // '*.js' matches '.js' + // '*.js' doesn't match 'abc' + (_, p1, p2) => { + // 1. + // > An asterisk "*" matches anything except a slash. + // 2. + // > Other consecutive asterisks are considered regular asterisks + // > and will match according to the previous rules. + const unescaped = p2.replace(/\\\*/g, '[^\\/]*') + return p1 + unescaped } - return entry; -} -exports.removeLeadingDotSegment = removeLeadingDotSegment; -exports.escape = IS_WINDOWS_PLATFORM ? escapeWindowsPath : escapePosixPath; -function escapeWindowsPath(pattern) { - return pattern.replace(WINDOWS_UNESCAPED_GLOB_SYMBOLS_RE, '\\$2'); -} -exports.escapeWindowsPath = escapeWindowsPath; -function escapePosixPath(pattern) { - return pattern.replace(POSIX_UNESCAPED_GLOB_SYMBOLS_RE, '\\$2'); -} -exports.escapePosixPath = escapePosixPath; -exports.convertPathToPattern = IS_WINDOWS_PLATFORM ? convertWindowsPathToPattern : convertPosixPathToPattern; -function convertWindowsPathToPattern(filepath) { - return escapeWindowsPath(filepath) - .replace(DOS_DEVICE_PATH_RE, '//$1') - .replace(WINDOWS_BACKSLASHES_RE, '/'); -} -exports.convertWindowsPathToPattern = convertWindowsPathToPattern; -function convertPosixPathToPattern(filepath) { - return escapePosixPath(filepath); -} -exports.convertPosixPathToPattern = convertPosixPathToPattern; + ], + [ + // unescape, revert step 3 except for back slash + // For example, if a user escape a '\\*', + // after step 3, the result will be '\\\\\\*' + /\\\\\\(?=[$.|*+(){^])/g, + () => ESCAPE + ], -/***/ }), + [ + // '\\\\' -> '\\' + /\\\\/g, + () => ESCAPE + ], -/***/ 3433: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + [ + // > The range notation, e.g. [a-zA-Z], + // > can be used to match one of the characters in a range. -"use strict"; + // `\` is escaped by step 3 + /(\\)?\[([^\]/]*?)(\\*)($|\])/g, + (match, leadEscape, range, endEscape, close) => leadEscape === ESCAPE + // '\\[bar]' -> '\\\\[bar\\]' + ? `\\[${range}${cleanRangeBackSlash(endEscape)}${close}` + : close === ']' + ? endEscape.length % 2 === 0 + // A normal case, and it is a range notation + // '[bar]' + // '[bar\\\\]' + ? `[${sanitizeRange(range)}${endEscape}]` + // Invalid range notaton + // '[bar\\]' -> '[bar\\\\]' + : '[]' + : '[]' + ], -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.isAbsolute = exports.partitionAbsoluteAndRelative = exports.removeDuplicateSlashes = exports.matchAny = exports.convertPatternsToRe = exports.makeRe = exports.getPatternParts = exports.expandBraceExpansion = exports.expandPatternsWithBraceExpansion = exports.isAffectDepthOfReadingPattern = exports.endsWithSlashGlobStar = exports.hasGlobStar = exports.getBaseDirectory = exports.isPatternRelatedToParentDirectory = exports.getPatternsOutsideCurrentDirectory = exports.getPatternsInsideCurrentDirectory = exports.getPositivePatterns = exports.getNegativePatterns = exports.isPositivePattern = exports.isNegativePattern = exports.convertToNegativePattern = exports.convertToPositivePattern = exports.isDynamicPattern = exports.isStaticPattern = void 0; -const path = __nccwpck_require__(6928); -const globParent = __nccwpck_require__(3648); -const micromatch = __nccwpck_require__(4839); -const GLOBSTAR = '**'; -const ESCAPE_SYMBOL = '\\'; -const COMMON_GLOB_SYMBOLS_RE = /[*?]|^!/; -const REGEX_CHARACTER_CLASS_SYMBOLS_RE = /\[[^[]*]/; -const REGEX_GROUP_SYMBOLS_RE = /(?:^|[^!*+?@])\([^(]*\|[^|]*\)/; -const GLOB_EXTENSION_SYMBOLS_RE = /[!*+?@]\([^(]*\)/; -const BRACE_EXPANSION_SEPARATORS_RE = /,|\.\./; -/** - * Matches a sequence of two or more consecutive slashes, excluding the first two slashes at the beginning of the string. - * The latter is due to the presence of the device path at the beginning of the UNC path. - */ -const DOUBLE_SLASH_RE = /(?!^)\/{2,}/g; -function isStaticPattern(pattern, options = {}) { - return !isDynamicPattern(pattern, options); + // ending + [ + // 'js' will not match 'js.' + // 'ab' will not match 'abc' + /(?:[^*])$/, + + // WTF! + // https://git-scm.com/docs/gitignore + // changes in [2.22.1](https://git-scm.com/docs/gitignore/2.22.1) + // which re-fixes #24, #38 + + // > If there is a separator at the end of the pattern then the pattern + // > will only match directories, otherwise the pattern can match both + // > files and directories. + + // 'js*' will not match 'a.js' + // 'js/' will not match 'a.js' + // 'js' will match 'a.js' and 'a.js/' + match => /\/$/.test(match) + // foo/ will not match 'foo' + ? `${match}$` + // foo matches 'foo' and 'foo/' + : `${match}(?=$|\\/$)` + ] +] + +const REGEX_REPLACE_TRAILING_WILDCARD = /(^|\\\/)?\\\*$/ +const MODE_IGNORE = 'regex' +const MODE_CHECK_IGNORE = 'checkRegex' +const UNDERSCORE = '_' + +const TRAILING_WILD_CARD_REPLACERS = { + [MODE_IGNORE] (_, p1) { + const prefix = p1 + // '\^': + // '/*' does not match EMPTY + // '/*' does not match everything + + // '\\\/': + // 'abc/*' does not match 'abc/' + ? `${p1}[^/]+` + + // 'a*' matches 'a' + // 'a*' matches 'aa' + : '[^/]*' + + return `${prefix}(?=$|\\/$)` + }, + + [MODE_CHECK_IGNORE] (_, p1) { + // When doing `git check-ignore` + const prefix = p1 + // '\\\/': + // 'abc/*' DOES match 'abc/' ! + ? `${p1}[^/]*` + + // 'a*' matches 'a' + // 'a*' matches 'aa' + : '[^/]*' + + return `${prefix}(?=$|\\/$)` + } } -exports.isStaticPattern = isStaticPattern; -function isDynamicPattern(pattern, options = {}) { - /** - * A special case with an empty string is necessary for matching patterns that start with a forward slash. - * An empty string cannot be a dynamic pattern. - * For example, the pattern `/lib/*` will be spread into parts: '', 'lib', '*'. - */ - if (pattern === '') { - return false; + +// @param {pattern} +const makeRegexPrefix = pattern => REPLACERS.reduce( + (prev, [matcher, replacer]) => + prev.replace(matcher, replacer.bind(pattern)), + pattern +) + +const isString = subject => typeof subject === 'string' + +// > A blank line matches no files, so it can serve as a separator for readability. +const checkPattern = pattern => pattern + && isString(pattern) + && !REGEX_TEST_BLANK_LINE.test(pattern) + && !REGEX_INVALID_TRAILING_BACKSLASH.test(pattern) + + // > A line starting with # serves as a comment. + && pattern.indexOf('#') !== 0 + +const splitPattern = pattern => pattern +.split(REGEX_SPLITALL_CRLF) +.filter(Boolean) + +class IgnoreRule { + constructor ( + pattern, + mark, + body, + ignoreCase, + negative, + prefix + ) { + this.pattern = pattern + this.mark = mark + this.negative = negative + + define(this, 'body', body) + define(this, 'ignoreCase', ignoreCase) + define(this, 'regexPrefix', prefix) + } + + get regex () { + const key = UNDERSCORE + MODE_IGNORE + + if (this[key]) { + return this[key] } - /** - * When the `caseSensitiveMatch` option is disabled, all patterns must be marked as dynamic, because we cannot check - * filepath directly (without read directory). - */ - if (options.caseSensitiveMatch === false || pattern.includes(ESCAPE_SYMBOL)) { - return true; - } - if (COMMON_GLOB_SYMBOLS_RE.test(pattern) || REGEX_CHARACTER_CLASS_SYMBOLS_RE.test(pattern) || REGEX_GROUP_SYMBOLS_RE.test(pattern)) { - return true; - } - if (options.extglob !== false && GLOB_EXTENSION_SYMBOLS_RE.test(pattern)) { - return true; - } - if (options.braceExpansion !== false && hasBraceExpansion(pattern)) { - return true; - } - return false; -} -exports.isDynamicPattern = isDynamicPattern; -function hasBraceExpansion(pattern) { - const openingBraceIndex = pattern.indexOf('{'); - if (openingBraceIndex === -1) { - return false; - } - const closingBraceIndex = pattern.indexOf('}', openingBraceIndex + 1); - if (closingBraceIndex === -1) { - return false; - } - const braceContent = pattern.slice(openingBraceIndex, closingBraceIndex); - return BRACE_EXPANSION_SEPARATORS_RE.test(braceContent); -} -function convertToPositivePattern(pattern) { - return isNegativePattern(pattern) ? pattern.slice(1) : pattern; -} -exports.convertToPositivePattern = convertToPositivePattern; -function convertToNegativePattern(pattern) { - return '!' + pattern; -} -exports.convertToNegativePattern = convertToNegativePattern; -function isNegativePattern(pattern) { - return pattern.startsWith('!') && pattern[1] !== '('; -} -exports.isNegativePattern = isNegativePattern; -function isPositivePattern(pattern) { - return !isNegativePattern(pattern); -} -exports.isPositivePattern = isPositivePattern; -function getNegativePatterns(patterns) { - return patterns.filter(isNegativePattern); -} -exports.getNegativePatterns = getNegativePatterns; -function getPositivePatterns(patterns) { - return patterns.filter(isPositivePattern); -} -exports.getPositivePatterns = getPositivePatterns; -/** - * Returns patterns that can be applied inside the current directory. - * - * @example - * // ['./*', '*', 'a/*'] - * getPatternsInsideCurrentDirectory(['./*', '*', 'a/*', '../*', './../*']) - */ -function getPatternsInsideCurrentDirectory(patterns) { - return patterns.filter((pattern) => !isPatternRelatedToParentDirectory(pattern)); -} -exports.getPatternsInsideCurrentDirectory = getPatternsInsideCurrentDirectory; -/** - * Returns patterns to be expanded relative to (outside) the current directory. - * - * @example - * // ['../*', './../*'] - * getPatternsInsideCurrentDirectory(['./*', '*', 'a/*', '../*', './../*']) - */ -function getPatternsOutsideCurrentDirectory(patterns) { - return patterns.filter(isPatternRelatedToParentDirectory); -} -exports.getPatternsOutsideCurrentDirectory = getPatternsOutsideCurrentDirectory; -function isPatternRelatedToParentDirectory(pattern) { - return pattern.startsWith('..') || pattern.startsWith('./..'); -} -exports.isPatternRelatedToParentDirectory = isPatternRelatedToParentDirectory; -function getBaseDirectory(pattern) { - return globParent(pattern, { flipBackslashes: false }); -} -exports.getBaseDirectory = getBaseDirectory; -function hasGlobStar(pattern) { - return pattern.includes(GLOBSTAR); -} -exports.hasGlobStar = hasGlobStar; -function endsWithSlashGlobStar(pattern) { - return pattern.endsWith('/' + GLOBSTAR); -} -exports.endsWithSlashGlobStar = endsWithSlashGlobStar; -function isAffectDepthOfReadingPattern(pattern) { - const basename = path.basename(pattern); - return endsWithSlashGlobStar(pattern) || isStaticPattern(basename); -} -exports.isAffectDepthOfReadingPattern = isAffectDepthOfReadingPattern; -function expandPatternsWithBraceExpansion(patterns) { - return patterns.reduce((collection, pattern) => { - return collection.concat(expandBraceExpansion(pattern)); - }, []); -} -exports.expandPatternsWithBraceExpansion = expandPatternsWithBraceExpansion; -function expandBraceExpansion(pattern) { - const patterns = micromatch.braces(pattern, { expand: true, nodupes: true, keepEscaping: true }); - /** - * Sort the patterns by length so that the same depth patterns are processed side by side. - * `a/{b,}/{c,}/*` – `['a///*', 'a/b//*', 'a//c/*', 'a/b/c/*']` - */ - patterns.sort((a, b) => a.length - b.length); - /** - * Micromatch can return an empty string in the case of patterns like `{a,}`. - */ - return patterns.filter((pattern) => pattern !== ''); -} -exports.expandBraceExpansion = expandBraceExpansion; -function getPatternParts(pattern, options) { - let { parts } = micromatch.scan(pattern, Object.assign(Object.assign({}, options), { parts: true })); - /** - * The scan method returns an empty array in some cases. - * See micromatch/picomatch#58 for more details. - */ - if (parts.length === 0) { - parts = [pattern]; - } - /** - * The scan method does not return an empty part for the pattern with a forward slash. - * This is another part of micromatch/picomatch#58. - */ - if (parts[0].startsWith('/')) { - parts[0] = parts[0].slice(1); - parts.unshift(''); - } - return parts; -} -exports.getPatternParts = getPatternParts; -function makeRe(pattern, options) { - return micromatch.makeRe(pattern, options); -} -exports.makeRe = makeRe; -function convertPatternsToRe(patterns, options) { - return patterns.map((pattern) => makeRe(pattern, options)); -} -exports.convertPatternsToRe = convertPatternsToRe; -function matchAny(entry, patternsRe) { - return patternsRe.some((patternRe) => patternRe.test(entry)); -} -exports.matchAny = matchAny; -/** - * This package only works with forward slashes as a path separator. - * Because of this, we cannot use the standard `path.normalize` method, because on Windows platform it will use of backslashes. - */ -function removeDuplicateSlashes(pattern) { - return pattern.replace(DOUBLE_SLASH_RE, '/'); -} -exports.removeDuplicateSlashes = removeDuplicateSlashes; -function partitionAbsoluteAndRelative(patterns) { - const absolute = []; - const relative = []; - for (const pattern of patterns) { - if (isAbsolute(pattern)) { - absolute.push(pattern); - } - else { - relative.push(pattern); - } + + return this._make(MODE_IGNORE, key) + } + + get checkRegex () { + const key = UNDERSCORE + MODE_CHECK_IGNORE + + if (this[key]) { + return this[key] } - return [absolute, relative]; -} -exports.partitionAbsoluteAndRelative = partitionAbsoluteAndRelative; -function isAbsolute(pattern) { - return path.isAbsolute(pattern); -} -exports.isAbsolute = isAbsolute; + return this._make(MODE_CHECK_IGNORE, key) + } -/***/ }), + _make (mode, key) { + const str = this.regexPrefix.replace( + REGEX_REPLACE_TRAILING_WILDCARD, -/***/ 2411: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + // It does not need to bind pattern + TRAILING_WILD_CARD_REPLACERS[mode] + ) -"use strict"; + const regex = this.ignoreCase + ? new RegExp(str, 'i') + : new RegExp(str) -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.merge = void 0; -const merge2 = __nccwpck_require__(5775); -function merge(streams) { - const mergedStream = merge2(streams); - streams.forEach((stream) => { - stream.once('error', (error) => mergedStream.emit('error', error)); - }); - mergedStream.once('close', () => propagateCloseEventToSources(streams)); - mergedStream.once('end', () => propagateCloseEventToSources(streams)); - return mergedStream; -} -exports.merge = merge; -function propagateCloseEventToSources(streams) { - streams.forEach((stream) => stream.emit('close')); + return define(this, key, regex) + } } +const createRule = ({ + pattern, + mark +}, ignoreCase) => { + let negative = false + let body = pattern -/***/ }), + // > An optional prefix "!" which negates the pattern; + if (body.indexOf('!') === 0) { + negative = true + body = body.substr(1) + } -/***/ 4062: -/***/ ((__unused_webpack_module, exports) => { + body = body + // > Put a backslash ("\") in front of the first "!" for patterns that + // > begin with a literal "!", for example, `"\!important!.txt"`. + .replace(REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION, '!') + // > Put a backslash ("\") in front of the first hash for patterns that + // > begin with a hash. + .replace(REGEX_REPLACE_LEADING_EXCAPED_HASH, '#') -"use strict"; + const regexPrefix = makeRegexPrefix(body) -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.isEmpty = exports.isString = void 0; -function isString(input) { - return typeof input === 'string'; -} -exports.isString = isString; -function isEmpty(input) { - return input === ''; + return new IgnoreRule( + pattern, + mark, + body, + ignoreCase, + negative, + regexPrefix + ) } -exports.isEmpty = isEmpty; +class RuleManager { + constructor (ignoreCase) { + this._ignoreCase = ignoreCase + this._rules = [] + } -/***/ }), - -/***/ 1014: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + _add (pattern) { + // #32 + if (pattern && pattern[KEY_IGNORE]) { + this._rules = this._rules.concat(pattern._rules._rules) + this._added = true + return + } -"use strict"; + if (isString(pattern)) { + pattern = { + pattern + } + } + if (checkPattern(pattern.pattern)) { + const rule = createRule(pattern, this._ignoreCase) + this._added = true + this._rules.push(rule) + } + } -/* eslint-disable no-var */ + // @param {Array | string | Ignore} pattern + add (pattern) { + this._added = false -var reusify = __nccwpck_require__(3070) + makeArray( + isString(pattern) + ? splitPattern(pattern) + : pattern + ).forEach(this._add, this) -function fastqueue (context, worker, _concurrency) { - if (typeof context === 'function') { - _concurrency = worker - worker = context - context = null + return this._added } - if (!(_concurrency >= 1)) { - throw new Error('fastqueue concurrency must be equal to or greater than 1') - } + // Test one single path without recursively checking parent directories + // + // - checkUnignored `boolean` whether should check if the path is unignored, + // setting `checkUnignored` to `false` could reduce additional + // path matching. + // - check `string` either `MODE_IGNORE` or `MODE_CHECK_IGNORE` - var cache = reusify(Task) - var queueHead = null - var queueTail = null - var _running = 0 - var errorHandler = null + // @returns {TestResult} true if a file is ignored + test (path, checkUnignored, mode) { + let ignored = false + let unignored = false + let matchedRule - var self = { - push: push, - drain: noop, - saturated: noop, - pause: pause, - paused: false, + this._rules.forEach(rule => { + const {negative} = rule - get concurrency () { - return _concurrency - }, - set concurrency (value) { - if (!(value >= 1)) { - throw new Error('fastqueue concurrency must be equal to or greater than 1') - } - _concurrency = value + // | ignored : unignored + // -------- | --------------------------------------- + // negative | 0:0 | 0:1 | 1:0 | 1:1 + // -------- | ------- | ------- | ------- | -------- + // 0 | TEST | TEST | SKIP | X + // 1 | TESTIF | SKIP | TEST | X - if (self.paused) return - for (; queueHead && _running < _concurrency;) { - _running++ - release() + // - SKIP: always skip + // - TEST: always test + // - TESTIF: only test if checkUnignored + // - X: that never happen + if ( + unignored === negative && ignored !== unignored + || negative && !ignored && !unignored && !checkUnignored + ) { + return } - }, - running: running, - resume: resume, - idle: idle, - length: length, - getQueue: getQueue, - unshift: unshift, - empty: noop, - kill: kill, - killAndDrain: killAndDrain, - error: error - } + const matched = rule[mode].test(path) - return self + if (!matched) { + return + } - function running () { - return _running - } + ignored = !negative + unignored = negative - function pause () { - self.paused = true - } + matchedRule = negative + ? UNDEFINED + : rule + }) - function length () { - var current = queueHead - var counter = 0 + const ret = { + ignored, + unignored + } - while (current) { - current = current.next - counter++ + if (matchedRule) { + ret.rule = matchedRule } - return counter + return ret } +} - function getQueue () { - var current = queueHead - var tasks = [] - - while (current) { - tasks.push(current.value) - current = current.next - } +const throwError = (message, Ctor) => { + throw new Ctor(message) +} - return tasks +const checkPath = (path, originalPath, doThrow) => { + if (!isString(path)) { + return doThrow( + `path must be a string, but got \`${originalPath}\``, + TypeError + ) } - function resume () { - if (!self.paused) return - self.paused = false - if (queueHead === null) { - _running++ - release() - return - } - for (; queueHead && _running < _concurrency;) { - _running++ - release() - } + // We don't know if we should ignore EMPTY, so throw + if (!path) { + return doThrow(`path must not be empty`, TypeError) } - function idle () { - return _running === 0 && self.length() === 0 + // Check if it is a relative path + if (checkPath.isNotRelative(path)) { + const r = '`path.relative()`d' + return doThrow( + `path should be a ${r} string, but got "${originalPath}"`, + RangeError + ) } - function push (value, done) { - var current = cache.get() + return true +} - current.context = context - current.release = release - current.value = value - current.callback = done || noop - current.errorHandler = errorHandler +const isNotRelative = path => REGEX_TEST_INVALID_PATH.test(path) - if (_running >= _concurrency || self.paused) { - if (queueTail) { - queueTail.next = current - queueTail = current - } else { - queueHead = current - queueTail = current - self.saturated() - } - } else { - _running++ - worker.call(context, current.value, current.worked) - } +checkPath.isNotRelative = isNotRelative + +// On windows, the following function will be replaced +/* istanbul ignore next */ +checkPath.convert = p => p + + +class Ignore { + constructor ({ + ignorecase = true, + ignoreCase = ignorecase, + allowRelativePaths = false + } = {}) { + define(this, KEY_IGNORE, true) + + this._rules = new RuleManager(ignoreCase) + this._strictPathCheck = !allowRelativePaths + this._initCache() } - function unshift (value, done) { - var current = cache.get() + _initCache () { + // A cache for the result of `.ignores()` + this._ignoreCache = Object.create(null) - current.context = context - current.release = release - current.value = value - current.callback = done || noop - current.errorHandler = errorHandler + // A cache for the result of `.test()` + this._testCache = Object.create(null) + } - if (_running >= _concurrency || self.paused) { - if (queueHead) { - current.next = queueHead - queueHead = current - } else { - queueHead = current - queueTail = current - self.saturated() - } - } else { - _running++ - worker.call(context, current.value, current.worked) + add (pattern) { + if (this._rules.add(pattern)) { + // Some rules have just added to the ignore, + // making the behavior changed, + // so we need to re-initialize the result cache + this._initCache() } + + return this } - function release (holder) { - if (holder) { - cache.release(holder) - } - var next = queueHead - if (next && _running <= _concurrency) { - if (!self.paused) { - if (queueTail === queueHead) { - queueTail = null - } - queueHead = next.next - next.next = null - worker.call(context, next.value, next.worked) - if (queueTail === null) { - self.empty() - } - } else { - _running-- - } - } else if (--_running === 0) { - self.drain() - } + // legacy + addPattern (pattern) { + return this.add(pattern) } - function kill () { - queueHead = null - queueTail = null - self.drain = noop - } + // @returns {TestResult} + _test (originalPath, cache, checkUnignored, slices) { + const path = originalPath + // Supports nullable path + && checkPath.convert(originalPath) - function killAndDrain () { - queueHead = null - queueTail = null - self.drain() - self.drain = noop - } + checkPath( + path, + originalPath, + this._strictPathCheck + ? throwError + : RETURN_FALSE + ) - function error (handler) { - errorHandler = handler + return this._t(path, cache, checkUnignored, slices) } -} -function noop () {} + checkIgnore (path) { + // If the path doest not end with a slash, `.ignores()` is much equivalent + // to `git check-ignore` + if (!REGEX_TEST_TRAILING_SLASH.test(path)) { + return this.test(path) + } -function Task () { - this.value = null - this.callback = noop - this.next = null - this.release = noop - this.context = null - this.errorHandler = null + const slices = path.split(SLASH).filter(Boolean) + slices.pop() - var self = this + if (slices.length) { + const parent = this._t( + slices.join(SLASH) + SLASH, + this._testCache, + true, + slices + ) - this.worked = function worked (err, result) { - var callback = self.callback - var errorHandler = self.errorHandler - var val = self.value - self.value = null - self.callback = noop - if (self.errorHandler) { - errorHandler(err, val) + if (parent.ignored) { + return parent + } } - callback.call(self.context, err, result) - self.release(self) - } -} -function queueAsPromised (context, worker, _concurrency) { - if (typeof context === 'function') { - _concurrency = worker - worker = context - context = null + return this._rules.test(path, false, MODE_CHECK_IGNORE) } - function asyncWrapper (arg, cb) { - worker.call(this, arg) - .then(function (res) { - cb(null, res) - }, cb) - } + _t ( + // The path to be tested + path, - var queue = fastqueue(context, asyncWrapper, _concurrency) + // The cache for the result of a certain checking + cache, - var pushCb = queue.push - var unshiftCb = queue.unshift + // Whether should check if the path is unignored + checkUnignored, - queue.push = push - queue.unshift = unshift - queue.drained = drained + // The path slices + slices + ) { + if (path in cache) { + return cache[path] + } - return queue + if (!slices) { + // path/to/a.js + // ['path', 'to', 'a.js'] + slices = path.split(SLASH).filter(Boolean) + } - function push (value) { - var p = new Promise(function (resolve, reject) { - pushCb(value, function (err, result) { - if (err) { - reject(err) - return - } - resolve(result) - }) - }) + slices.pop() - // Let's fork the promise chain to - // make the error bubble up to the user but - // not lead to a unhandledRejection - p.catch(noop) + // If the path has no parent directory, just test it + if (!slices.length) { + return cache[path] = this._rules.test(path, checkUnignored, MODE_IGNORE) + } - return p - } + const parent = this._t( + slices.join(SLASH) + SLASH, + cache, + checkUnignored, + slices + ) - function unshift (value) { - var p = new Promise(function (resolve, reject) { - unshiftCb(value, function (err, result) { - if (err) { - reject(err) - return - } - resolve(result) - }) - }) + // If the path contains a parent directory, check the parent first + return cache[path] = parent.ignored + // > It is not possible to re-include a file if a parent directory of + // > that file is excluded. + ? parent + : this._rules.test(path, checkUnignored, MODE_IGNORE) + } - // Let's fork the promise chain to - // make the error bubble up to the user but - // not lead to a unhandledRejection - p.catch(noop) + ignores (path) { + return this._test(path, this._ignoreCache, false).ignored + } - return p + createFilter () { + return path => !this.ignores(path) } - function drained () { - var p = new Promise(function (resolve) { - process.nextTick(function () { - if (queue.idle()) { - resolve() - } else { - var previousDrain = queue.drain - queue.drain = function () { - if (typeof previousDrain === 'function') previousDrain() - resolve() - queue.drain = previousDrain - } - } - }) - }) + filter (paths) { + return makeArray(paths).filter(this.createFilter()) + } - return p + // @returns {TestResult} + test (path) { + return this._test(path, this._testCache, true) } } -module.exports = fastqueue -module.exports.promise = queueAsPromised +const factory = options => new Ignore(options) + +const isPathValid = path => + checkPath(path && checkPath.convert(path), path, RETURN_FALSE) + +/* istanbul ignore next */ +const setupWindows = () => { + /* eslint no-control-regex: "off" */ + const makePosix = str => /^\\\\\?\\/.test(str) + || /["<>|\u0000-\u001F]+/u.test(str) + ? str + : str.replace(/\\/g, '/') + + checkPath.convert = makePosix + + // 'C:\\foo' <- 'C:\\foo' has been converted to 'C:/' + // 'd:\\foo' + const REGEX_TEST_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i + checkPath.isNotRelative = path => + REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path) + || isNotRelative(path) +} + + +// Windows +// -------------------------------------------------------------- +/* istanbul ignore next */ +if ( + // Detect `process` so that it can run in browsers. + typeof process !== 'undefined' + && process.platform === 'win32' +) { + setupWindows() +} + +// COMMONJS_EXPORTS //////////////////////////////////////////////////////////// + +module.exports = factory + +// Although it is an anti-pattern, +// it is still widely misused by a lot of libraries in github +// Ref: https://github.com/search?q=ignore.default%28%29&type=code +factory.default = factory + +module.exports.isPathValid = isPathValid + +// For testing purposes +define(module.exports, Symbol.for('setupWindows'), setupWindows) /***/ }), -/***/ 6017: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +/***/ 2190: +/***/ ((module) => { -"use strict"; /*! - * fill-range + * is-extglob * - * Copyright (c) 2014-present, Jon Schlinkert. + * Copyright (c) 2014-2016, Jon Schlinkert. * Licensed under the MIT License. */ +module.exports = function isExtglob(str) { + if (typeof str !== 'string' || str === '') { + return false; + } + var match; + while ((match = /(\\).|([@?!+*]\(.*\))/g.exec(str))) { + if (match[2]) return true; + str = str.slice(match.index + match[0].length); + } -const util = __nccwpck_require__(9023); -const toRegexRange = __nccwpck_require__(1512); - -const isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val); - -const transform = toNumber => { - return value => toNumber === true ? Number(value) : String(value); + return false; }; -const isValidValue = value => { - return typeof value === 'number' || (typeof value === 'string' && value !== ''); -}; -const isNumber = num => Number.isInteger(+num); +/***/ }), -const zeros = input => { - let value = `${input}`; - let index = -1; - if (value[0] === '-') value = value.slice(1); - if (value === '0') return false; - while (value[++index] === '0'); - return index > 0; -}; +/***/ 498: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -const stringify = (start, end, options) => { - if (typeof start === 'string' || typeof end === 'string') { +/*! + * is-glob + * + * Copyright (c) 2014-2017, Jon Schlinkert. + * Released under the MIT License. + */ + +var isExtglob = __nccwpck_require__(2190); +var chars = { '{': '}', '(': ')', '[': ']'}; +var strictCheck = function(str) { + if (str[0] === '!') { return true; } - return options.stringify === true; -}; + var index = 0; + var pipeIndex = -2; + var closeSquareIndex = -2; + var closeCurlyIndex = -2; + var closeParenIndex = -2; + var backSlashIndex = -2; + while (index < str.length) { + if (str[index] === '*') { + return true; + } -const pad = (input, maxLength, toNumber) => { - if (maxLength > 0) { - let dash = input[0] === '-' ? '-' : ''; - if (dash) input = input.slice(1); - input = (dash + input.padStart(dash ? maxLength - 1 : maxLength, '0')); - } - if (toNumber === false) { - return String(input); + if (str[index + 1] === '?' && /[\].+)]/.test(str[index])) { + return true; + } + + if (closeSquareIndex !== -1 && str[index] === '[' && str[index + 1] !== ']') { + if (closeSquareIndex < index) { + closeSquareIndex = str.indexOf(']', index); + } + if (closeSquareIndex > index) { + if (backSlashIndex === -1 || backSlashIndex > closeSquareIndex) { + return true; + } + backSlashIndex = str.indexOf('\\', index); + if (backSlashIndex === -1 || backSlashIndex > closeSquareIndex) { + return true; + } + } + } + + if (closeCurlyIndex !== -1 && str[index] === '{' && str[index + 1] !== '}') { + closeCurlyIndex = str.indexOf('}', index); + if (closeCurlyIndex > index) { + backSlashIndex = str.indexOf('\\', index); + if (backSlashIndex === -1 || backSlashIndex > closeCurlyIndex) { + return true; + } + } + } + + if (closeParenIndex !== -1 && str[index] === '(' && str[index + 1] === '?' && /[:!=]/.test(str[index + 2]) && str[index + 3] !== ')') { + closeParenIndex = str.indexOf(')', index); + if (closeParenIndex > index) { + backSlashIndex = str.indexOf('\\', index); + if (backSlashIndex === -1 || backSlashIndex > closeParenIndex) { + return true; + } + } + } + + if (pipeIndex !== -1 && str[index] === '(' && str[index + 1] !== '|') { + if (pipeIndex < index) { + pipeIndex = str.indexOf('|', index); + } + if (pipeIndex !== -1 && str[pipeIndex + 1] !== ')') { + closeParenIndex = str.indexOf(')', pipeIndex); + if (closeParenIndex > pipeIndex) { + backSlashIndex = str.indexOf('\\', pipeIndex); + if (backSlashIndex === -1 || backSlashIndex > closeParenIndex) { + return true; + } + } + } + } + + if (str[index] === '\\') { + var open = str[index + 1]; + index += 2; + var close = chars[open]; + + if (close) { + var n = str.indexOf(close, index); + if (n !== -1) { + index = n + 1; + } + } + + if (str[index] === '!') { + return true; + } + } else { + index++; + } } - return input; + return false; }; -const toMaxLen = (input, maxLength) => { - let negative = input[0] === '-' ? '-' : ''; - if (negative) { - input = input.slice(1); - maxLength--; +var relaxedCheck = function(str) { + if (str[0] === '!') { + return true; } - while (input.length < maxLength) input = '0' + input; - return negative ? ('-' + input) : input; -}; + var index = 0; + while (index < str.length) { + if (/[*?{}()[\]]/.test(str[index])) { + return true; + } -const toSequence = (parts, options, maxLen) => { - parts.negatives.sort((a, b) => a < b ? -1 : a > b ? 1 : 0); - parts.positives.sort((a, b) => a < b ? -1 : a > b ? 1 : 0); + if (str[index] === '\\') { + var open = str[index + 1]; + index += 2; + var close = chars[open]; - let prefix = options.capture ? '' : '?:'; - let positives = ''; - let negatives = ''; - let result; + if (close) { + var n = str.indexOf(close, index); + if (n !== -1) { + index = n + 1; + } + } - if (parts.positives.length) { - positives = parts.positives.map(v => toMaxLen(String(v), maxLen)).join('|'); + if (str[index] === '!') { + return true; + } + } else { + index++; + } } + return false; +}; - if (parts.negatives.length) { - negatives = `-(${prefix}${parts.negatives.map(v => toMaxLen(String(v), maxLen)).join('|')})`; +module.exports = function isGlob(str, options) { + if (typeof str !== 'string' || str === '') { + return false; } - if (positives && negatives) { - result = `${positives}|${negatives}`; - } else { - result = positives || negatives; + if (isExtglob(str)) { + return true; } - if (options.wrap) { - return `(${prefix}${result})`; + var check = strictCheck; + + // optionally relax check + if (options && options.strict === false) { + check = relaxedCheck; } - return result; + return check(str); }; -const toRange = (a, b, isNumbers, options) => { - if (isNumbers) { - return toRegexRange(a, b, { wrap: false, ...options }); - } - let start = String.fromCharCode(a); - if (a === b) return start; +/***/ }), - let stop = String.fromCharCode(b); - return `[${start}-${stop}]`; -}; +/***/ 6176: +/***/ ((module) => { -const toRegex = (start, end, options) => { - if (Array.isArray(start)) { - let wrap = options.wrap === true; - let prefix = options.capture ? '' : '?:'; - return wrap ? `(${prefix}${start.join('|')})` : start.join('|'); - } - return toRegexRange(start, end, options); -}; +/*! + * is-number + * + * Copyright (c) 2014-present, Jon Schlinkert. + * Released under the MIT License. + */ -const rangeError = (...args) => { - return new RangeError('Invalid range arguments: ' + util.inspect(...args)); -}; -const invalidRange = (start, end, options) => { - if (options.strictRanges === true) throw rangeError([start, end]); - return []; -}; -const invalidStep = (step, options) => { - if (options.strictRanges === true) { - throw new TypeError(`Expected step "${step}" to be a number`); +module.exports = function(num) { + if (typeof num === 'number') { + return num - num === 0; } - return []; + if (typeof num === 'string' && num.trim() !== '') { + return Number.isFinite ? Number.isFinite(+num) : isFinite(+num); + } + return false; }; -const fillNumbers = (start, end, step = 1, options = {}) => { - let a = Number(start); - let b = Number(end); - if (!Number.isInteger(a) || !Number.isInteger(b)) { - if (options.strictRanges === true) throw rangeError([start, end]); - return []; - } +/***/ }), - // fix negative zero - if (a === 0) a = 0; - if (b === 0) b = 0; +/***/ 3783: +/***/ ((module) => { - let descending = a > b; - let startString = String(start); - let endString = String(end); - let stepString = String(step); - step = Math.max(Math.abs(step), 1); - let padded = zeros(startString) || zeros(endString) || zeros(stepString); - let maxLen = padded ? Math.max(startString.length, endString.length, stepString.length) : 0; - let toNumber = padded === false && stringify(start, end, options) === false; - let format = options.transform || transform(toNumber); - if (options.toRegex && step === 1) { - return toRange(toMaxLen(start, maxLen), toMaxLen(end, maxLen), true, options); - } +const isStream = stream => + stream !== null && + typeof stream === 'object' && + typeof stream.pipe === 'function'; - let parts = { negatives: [], positives: [] }; - let push = num => parts[num < 0 ? 'negatives' : 'positives'].push(Math.abs(num)); - let range = []; - let index = 0; +isStream.writable = stream => + isStream(stream) && + stream.writable !== false && + typeof stream._write === 'function' && + typeof stream._writableState === 'object'; - while (descending ? a >= b : a <= b) { - if (options.toRegex === true && step > 1) { - push(a); - } else { - range.push(pad(format(a, index), maxLen, toNumber)); - } - a = descending ? a - step : a + step; - index++; - } +isStream.readable = stream => + isStream(stream) && + stream.readable !== false && + typeof stream._read === 'function' && + typeof stream._readableState === 'object'; - if (options.toRegex === true) { - return step > 1 - ? toSequence(parts, options, maxLen) - : toRegex(range, null, { wrap: false, ...options }); - } +isStream.duplex = stream => + isStream.writable(stream) && + isStream.readable(stream); - return range; -}; +isStream.transform = stream => + isStream.duplex(stream) && + typeof stream._transform === 'function'; -const fillLetters = (start, end, step = 1, options = {}) => { - if ((!isNumber(start) && start.length > 1) || (!isNumber(end) && end.length > 1)) { - return invalidRange(start, end, options); - } +module.exports = isStream; - let format = options.transform || (val => String.fromCharCode(val)); - let a = `${start}`.charCodeAt(0); - let b = `${end}`.charCodeAt(0); - let descending = a > b; - let min = Math.min(a, b); - let max = Math.max(a, b); +/***/ }), - if (options.toRegex && step === 1) { - return toRange(min, max, false, options); - } +/***/ 3494: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - let range = []; - let index = 0; +var fs = __nccwpck_require__(9896) +var core +if (process.platform === 'win32' || global.TESTING_WINDOWS) { + core = __nccwpck_require__(2027) +} else { + core = __nccwpck_require__(2135) +} - while (descending ? a >= b : a <= b) { - range.push(format(a, index)); - a = descending ? a - step : a + step; - index++; - } +module.exports = isexe +isexe.sync = sync - if (options.toRegex === true) { - return toRegex(range, null, { wrap: false, options }); +function isexe (path, options, cb) { + if (typeof options === 'function') { + cb = options + options = {} } - return range; -}; + if (!cb) { + if (typeof Promise !== 'function') { + throw new TypeError('callback not provided') + } -const fill = (start, end, step, options = {}) => { - if (end == null && isValidValue(start)) { - return [start]; + return new Promise(function (resolve, reject) { + isexe(path, options || {}, function (er, is) { + if (er) { + reject(er) + } else { + resolve(is) + } + }) + }) } - if (!isValidValue(start) || !isValidValue(end)) { - return invalidRange(start, end, options); - } + core(path, options || {}, function (er, is) { + // ignore EACCES because that just means we aren't allowed to run it + if (er) { + if (er.code === 'EACCES' || options && options.ignoreErrors) { + er = null + is = false + } + } + cb(er, is) + }) +} - if (typeof step === 'function') { - return fill(start, end, 1, { transform: step }); +function sync (path, options) { + // my kingdom for a filtered catch + try { + return core.sync(path, options || {}) + } catch (er) { + if (options && options.ignoreErrors || er.code === 'EACCES') { + return false + } else { + throw er + } } +} - if (isObject(step)) { - return fill(start, end, 0, step); - } - let opts = { ...options }; - if (opts.capture === true) opts.wrap = true; - step = step || opts.step || 1; +/***/ }), - if (!isNumber(step)) { - if (step != null && !isObject(step)) return invalidStep(step, opts); - return fill(start, end, 1, step); - } +/***/ 2135: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - if (isNumber(start) && isNumber(end)) { - return fillNumbers(start, end, step, opts); - } +module.exports = isexe +isexe.sync = sync - return fillLetters(start, end, Math.max(Math.abs(step), 1), opts); -}; +var fs = __nccwpck_require__(9896) -module.exports = fill; +function isexe (path, options, cb) { + fs.stat(path, function (er, stat) { + cb(er, er ? false : checkStat(stat, options)) + }) +} +function sync (path, options) { + return checkStat(fs.statSync(path), options) +} -/***/ }), +function checkStat (stat, options) { + return stat.isFile() && checkMode(stat, options) +} -/***/ 9807: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +function checkMode (stat, options) { + var mod = stat.mode + var uid = stat.uid + var gid = stat.gid -"use strict"; + var myUid = options.uid !== undefined ? + options.uid : process.getuid && process.getuid() + var myGid = options.gid !== undefined ? + options.gid : process.getgid && process.getgid() -const {PassThrough: PassThroughStream} = __nccwpck_require__(2203); + var u = parseInt('100', 8) + var g = parseInt('010', 8) + var o = parseInt('001', 8) + var ug = u | g -module.exports = options => { - options = {...options}; + var ret = (mod & o) || + (mod & g) && gid === myGid || + (mod & u) && uid === myUid || + (mod & ug) && myUid === 0 - const {array} = options; - let {encoding} = options; - const isBuffer = encoding === 'buffer'; - let objectMode = false; + return ret +} - if (array) { - objectMode = !(encoding || isBuffer); - } else { - encoding = encoding || 'utf8'; - } - if (isBuffer) { - encoding = null; - } +/***/ }), - const stream = new PassThroughStream({objectMode}); +/***/ 2027: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - if (encoding) { - stream.setEncoding(encoding); - } +module.exports = isexe +isexe.sync = sync - let length = 0; - const chunks = []; +var fs = __nccwpck_require__(9896) - stream.on('data', chunk => { - chunks.push(chunk); +function checkPathExt (path, options) { + var pathext = options.pathExt !== undefined ? + options.pathExt : process.env.PATHEXT - if (objectMode) { - length = chunks.length; - } else { - length += chunk.length; - } - }); + if (!pathext) { + return true + } - stream.getBufferedValue = () => { - if (array) { - return chunks; - } + pathext = pathext.split(';') + if (pathext.indexOf('') !== -1) { + return true + } + for (var i = 0; i < pathext.length; i++) { + var p = pathext[i].toLowerCase() + if (p && path.substr(-p.length).toLowerCase() === p) { + return true + } + } + return false +} - return isBuffer ? Buffer.concat(chunks, length) : chunks.join(''); - }; +function checkStat (stat, path, options) { + if (!stat.isSymbolicLink() && !stat.isFile()) { + return false + } + return checkPathExt(path, options) +} - stream.getBufferedLength = () => length; +function isexe (path, options, cb) { + fs.stat(path, function (er, stat) { + cb(er, er ? false : checkStat(stat, path, options)) + }) +} - return stream; -}; +function sync (path, options) { + return checkStat(fs.statSync(path), path, options) +} /***/ }), -/***/ 3257: +/***/ 1340: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -const {constants: BufferConstants} = __nccwpck_require__(181); -const stream = __nccwpck_require__(2203); -const {promisify} = __nccwpck_require__(9023); -const bufferStream = __nccwpck_require__(9807); -const streamPipelinePromisified = promisify(stream.pipeline); +const { PassThrough } = __nccwpck_require__(2203); -class MaxBufferError extends Error { - constructor() { - super('maxBuffer exceeded'); - this.name = 'MaxBufferError'; - } -} +module.exports = function (/*streams...*/) { + var sources = [] + var output = new PassThrough({objectMode: true}) -async function getStream(inputStream, options) { - if (!inputStream) { - throw new Error('Expected a stream'); - } + output.setMaxListeners(0) - options = { - maxBuffer: Infinity, - ...options - }; + output.add = add + output.isEmpty = isEmpty - const {maxBuffer} = options; - const stream = bufferStream(options); + output.on('unpipe', remove) - await new Promise((resolve, reject) => { - const rejectPromise = error => { - // Don't retrieve an oversized buffer. - if (error && stream.getBufferedLength() <= BufferConstants.MAX_LENGTH) { - error.bufferedData = stream.getBufferedValue(); - } + Array.prototype.slice.call(arguments).forEach(add) - reject(error); - }; + return output - (async () => { - try { - await streamPipelinePromisified(inputStream, stream); - resolve(); - } catch (error) { - rejectPromise(error); - } - })(); + function add (source) { + if (Array.isArray(source)) { + source.forEach(add) + return this + } - stream.on('data', () => { - if (stream.getBufferedLength() > maxBuffer) { - rejectPromise(new MaxBufferError()); - } - }); - }); + sources.push(source); + source.once('end', remove.bind(null, source)) + source.once('error', output.emit.bind(output, 'error')) + source.pipe(output, {end: false}) + return this + } - return stream.getBufferedValue(); -} + function isEmpty () { + return sources.length == 0; + } -module.exports = getStream; -module.exports.buffer = (stream, options) => getStream(stream, {...options, encoding: 'buffer'}); -module.exports.array = (stream, options) => getStream(stream, {...options, array: true}); -module.exports.MaxBufferError = MaxBufferError; + function remove (source) { + sources = sources.filter(function (it) { return it !== source }) + if (!sources.length && output.readable) { output.end() } + } +} /***/ }), -/***/ 3648: +/***/ 6508: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; - -var isGlob = __nccwpck_require__(6689); -var pathPosixDirname = (__nccwpck_require__(6928).posix).dirname; -var isWin32 = (__nccwpck_require__(857).platform)() === 'win32'; +/* + * merge2 + * https://github.com/teambition/merge2 + * + * Copyright (c) 2014-2020 Teambition + * Licensed under the MIT license. + */ +const Stream = __nccwpck_require__(2203) +const PassThrough = Stream.PassThrough +const slice = Array.prototype.slice -var slash = '/'; -var backslash = /\\/g; -var enclosure = /[\{\[].*[\}\]]$/; -var globby = /(^|[^\\])([\{\[]|\([^\)]+$)/; -var escaped = /\\([\!\*\?\|\[\]\(\)\{\}])/g; +module.exports = merge2 -/** - * @param {string} str - * @param {Object} opts - * @param {boolean} [opts.flipBackslashes=true] - * @returns {string} - */ -module.exports = function globParent(str, opts) { - var options = Object.assign({ flipBackslashes: true }, opts); +function merge2 () { + const streamsQueue = [] + const args = slice.call(arguments) + let merging = false + let options = args[args.length - 1] - // flip windows path separators - if (options.flipBackslashes && isWin32 && str.indexOf(slash) < 0) { - str = str.replace(backslash, slash); + if (options && !Array.isArray(options) && options.pipe == null) { + args.pop() + } else { + options = {} } - // special case for strings ending in enclosure containing path separator - if (enclosure.test(str)) { - str += slash; + const doEnd = options.end !== false + const doPipeError = options.pipeError === true + if (options.objectMode == null) { + options.objectMode = true + } + if (options.highWaterMark == null) { + options.highWaterMark = 64 * 1024 } + const mergedStream = PassThrough(options) - // preserves full path in case of trailing path separator - str += 'a'; + function addStream () { + for (let i = 0, len = arguments.length; i < len; i++) { + streamsQueue.push(pauseStreams(arguments[i], options)) + } + mergeStream() + return this + } - // remove path parts that are globby - do { - str = pathPosixDirname(str); - } while (isGlob(str) || globby.test(str)); + function mergeStream () { + if (merging) { + return + } + merging = true - // remove escape chars and return result - return str.replace(escaped, '$1'); -}; + let streams = streamsQueue.shift() + if (!streams) { + process.nextTick(endStream) + return + } + if (!Array.isArray(streams)) { + streams = [streams] + } + let pipesCount = streams.length + 1 -/***/ }), + function next () { + if (--pipesCount > 0) { + return + } + merging = false + mergeStream() + } -/***/ 6503: -/***/ ((__unused_webpack_module, exports) => { + function pipe (stream) { + function onend () { + stream.removeListener('merge2UnpipeEnd', onend) + stream.removeListener('end', onend) + if (doPipeError) { + stream.removeListener('error', onerror) + } + next() + } + function onerror (err) { + mergedStream.emit('error', err) + } + // skip ended stream + if (stream._readableState.endEmitted) { + return next() + } -"use strict"; -Object.defineProperty(exports, "__esModule", ({value:true}));exports.SIGNALS=void 0; + stream.on('merge2UnpipeEnd', onend) + stream.on('end', onend) -const SIGNALS=[ -{ -name:"SIGHUP", -number:1, -action:"terminate", -description:"Terminal closed", -standard:"posix"}, + if (doPipeError) { + stream.on('error', onerror) + } -{ -name:"SIGINT", -number:2, -action:"terminate", -description:"User interruption with CTRL-C", -standard:"ansi"}, + stream.pipe(mergedStream, { end: false }) + // compatible for old stream + stream.resume() + } -{ -name:"SIGQUIT", -number:3, -action:"core", -description:"User interruption with CTRL-\\", -standard:"posix"}, + for (let i = 0; i < streams.length; i++) { + pipe(streams[i]) + } -{ -name:"SIGILL", -number:4, -action:"core", -description:"Invalid machine instruction", -standard:"ansi"}, + next() + } -{ -name:"SIGTRAP", -number:5, -action:"core", -description:"Debugger breakpoint", -standard:"posix"}, + function endStream () { + merging = false + // emit 'queueDrain' when all streams merged. + mergedStream.emit('queueDrain') + if (doEnd) { + mergedStream.end() + } + } -{ -name:"SIGABRT", -number:6, -action:"core", -description:"Aborted", -standard:"ansi"}, + mergedStream.setMaxListeners(0) + mergedStream.add = addStream + mergedStream.on('unpipe', function (stream) { + stream.emit('merge2UnpipeEnd') + }) -{ -name:"SIGIOT", -number:6, -action:"core", -description:"Aborted", -standard:"bsd"}, + if (args.length) { + addStream.apply(null, args) + } + return mergedStream +} -{ -name:"SIGBUS", -number:7, -action:"core", -description: -"Bus error due to misaligned, non-existing address or paging error", -standard:"bsd"}, - -{ -name:"SIGEMT", -number:7, -action:"terminate", -description:"Command should be emulated but is not implemented", -standard:"other"}, +// check and pause streams for pipe. +function pauseStreams (streams, options) { + if (!Array.isArray(streams)) { + // Backwards-compat with old-style streams + if (!streams._readableState && streams.pipe) { + streams = streams.pipe(PassThrough(options)) + } + if (!streams._readableState || !streams.pause || !streams.pipe) { + throw new Error('Only readable stream can be merged.') + } + streams.pause() + } else { + for (let i = 0, len = streams.length; i < len; i++) { + streams[i] = pauseStreams(streams[i], options) + } + } + return streams +} -{ -name:"SIGFPE", -number:8, -action:"core", -description:"Floating point arithmetic error", -standard:"ansi"}, -{ -name:"SIGKILL", -number:9, -action:"terminate", -description:"Forced termination", -standard:"posix", -forced:true}, +/***/ }), -{ -name:"SIGUSR1", -number:10, -action:"terminate", -description:"Application-specific signal", -standard:"posix"}, +/***/ 1136: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -{ -name:"SIGSEGV", -number:11, -action:"core", -description:"Segmentation fault", -standard:"ansi"}, -{ -name:"SIGUSR2", -number:12, -action:"terminate", -description:"Application-specific signal", -standard:"posix"}, -{ -name:"SIGPIPE", -number:13, -action:"terminate", -description:"Broken pipe or socket", -standard:"posix"}, +const util = __nccwpck_require__(9023); +const braces = __nccwpck_require__(6420); +const picomatch = __nccwpck_require__(7774); +const utils = __nccwpck_require__(7379); -{ -name:"SIGALRM", -number:14, -action:"terminate", -description:"Timeout or timer", -standard:"posix"}, +const isEmptyString = v => v === '' || v === './'; +const hasBraces = v => { + const index = v.indexOf('{'); + return index > -1 && v.indexOf('}', index) > -1; +}; -{ -name:"SIGTERM", -number:15, -action:"terminate", -description:"Termination", -standard:"ansi"}, +/** + * Returns an array of strings that match one or more glob patterns. + * + * ```js + * const mm = require('micromatch'); + * // mm(list, patterns[, options]); + * + * console.log(mm(['a.js', 'a.txt'], ['*.js'])); + * //=> [ 'a.js' ] + * ``` + * @param {String|Array} `list` List of strings to match. + * @param {String|Array} `patterns` One or more glob patterns to use for matching. + * @param {Object} `options` See available [options](#options) + * @return {Array} Returns an array of matches + * @summary false + * @api public + */ -{ -name:"SIGSTKFLT", -number:16, -action:"terminate", -description:"Stack is empty or overflowed", -standard:"other"}, +const micromatch = (list, patterns, options) => { + patterns = [].concat(patterns); + list = [].concat(list); -{ -name:"SIGCHLD", -number:17, -action:"ignore", -description:"Child process terminated, paused or unpaused", -standard:"posix"}, + let omit = new Set(); + let keep = new Set(); + let items = new Set(); + let negatives = 0; -{ -name:"SIGCLD", -number:17, -action:"ignore", -description:"Child process terminated, paused or unpaused", -standard:"other"}, + let onResult = state => { + items.add(state.output); + if (options && options.onResult) { + options.onResult(state); + } + }; -{ -name:"SIGCONT", -number:18, -action:"unpause", -description:"Unpaused", -standard:"posix", -forced:true}, + for (let i = 0; i < patterns.length; i++) { + let isMatch = picomatch(String(patterns[i]), { ...options, onResult }, true); + let negated = isMatch.state.negated || isMatch.state.negatedExtglob; + if (negated) negatives++; -{ -name:"SIGSTOP", -number:19, -action:"pause", -description:"Paused", -standard:"posix", -forced:true}, + for (let item of list) { + let matched = isMatch(item, true); -{ -name:"SIGTSTP", -number:20, -action:"pause", -description:"Paused using CTRL-Z or \"suspend\"", -standard:"posix"}, + let match = negated ? !matched.isMatch : matched.isMatch; + if (!match) continue; -{ -name:"SIGTTIN", -number:21, -action:"pause", -description:"Background process cannot read terminal input", -standard:"posix"}, + if (negated) { + omit.add(matched.output); + } else { + omit.delete(matched.output); + keep.add(matched.output); + } + } + } -{ -name:"SIGBREAK", -number:21, -action:"terminate", -description:"User interruption with CTRL-BREAK", -standard:"other"}, + let result = negatives === patterns.length ? [...items] : [...keep]; + let matches = result.filter(item => !omit.has(item)); -{ -name:"SIGTTOU", -number:22, -action:"pause", -description:"Background process cannot write to terminal output", -standard:"posix"}, + if (options && matches.length === 0) { + if (options.failglob === true) { + throw new Error(`No matches found for "${patterns.join(', ')}"`); + } -{ -name:"SIGURG", -number:23, -action:"ignore", -description:"Socket received out-of-band data", -standard:"bsd"}, + if (options.nonull === true || options.nullglob === true) { + return options.unescape ? patterns.map(p => p.replace(/\\/g, '')) : patterns; + } + } -{ -name:"SIGXCPU", -number:24, -action:"core", -description:"Process timed out", -standard:"bsd"}, + return matches; +}; -{ -name:"SIGXFSZ", -number:25, -action:"core", -description:"File too big", -standard:"bsd"}, +/** + * Backwards compatibility + */ -{ -name:"SIGVTALRM", -number:26, -action:"terminate", -description:"Timeout or timer", -standard:"bsd"}, +micromatch.match = micromatch; -{ -name:"SIGPROF", -number:27, -action:"terminate", -description:"Timeout or timer", -standard:"bsd"}, +/** + * Returns a matcher function from the given glob `pattern` and `options`. + * The returned function takes a string to match as its only argument and returns + * true if the string is a match. + * + * ```js + * const mm = require('micromatch'); + * // mm.matcher(pattern[, options]); + * + * const isMatch = mm.matcher('*.!(*a)'); + * console.log(isMatch('a.a')); //=> false + * console.log(isMatch('a.b')); //=> true + * ``` + * @param {String} `pattern` Glob pattern + * @param {Object} `options` + * @return {Function} Returns a matcher function. + * @api public + */ -{ -name:"SIGWINCH", -number:28, -action:"ignore", -description:"Terminal window size changed", -standard:"bsd"}, +micromatch.matcher = (pattern, options) => picomatch(pattern, options); -{ -name:"SIGIO", -number:29, -action:"terminate", -description:"I/O is available", -standard:"other"}, +/** + * Returns true if **any** of the given glob `patterns` match the specified `string`. + * + * ```js + * const mm = require('micromatch'); + * // mm.isMatch(string, patterns[, options]); + * + * console.log(mm.isMatch('a.a', ['b.*', '*.a'])); //=> true + * console.log(mm.isMatch('a.a', 'b.*')); //=> false + * ``` + * @param {String} `str` The string to test. + * @param {String|Array} `patterns` One or more glob patterns to use for matching. + * @param {Object} `[options]` See available [options](#options). + * @return {Boolean} Returns true if any patterns match `str` + * @api public + */ -{ -name:"SIGPOLL", -number:29, -action:"terminate", -description:"Watched event", -standard:"other"}, +micromatch.isMatch = (str, patterns, options) => picomatch(patterns, options)(str); -{ -name:"SIGINFO", -number:29, -action:"ignore", -description:"Request for process information", -standard:"other"}, +/** + * Backwards compatibility + */ -{ -name:"SIGPWR", -number:30, -action:"terminate", -description:"Device running out of power", -standard:"systemv"}, +micromatch.any = micromatch.isMatch; -{ -name:"SIGSYS", -number:31, -action:"core", -description:"Invalid system call", -standard:"other"}, +/** + * Returns a list of strings that _**do not match any**_ of the given `patterns`. + * + * ```js + * const mm = require('micromatch'); + * // mm.not(list, patterns[, options]); + * + * console.log(mm.not(['a.a', 'b.b', 'c.c'], '*.a')); + * //=> ['b.b', 'c.c'] + * ``` + * @param {Array} `list` Array of strings to match. + * @param {String|Array} `patterns` One or more glob pattern to use for matching. + * @param {Object} `options` See available [options](#options) for changing how matches are performed + * @return {Array} Returns an array of strings that **do not match** the given patterns. + * @api public + */ -{ -name:"SIGUNUSED", -number:31, -action:"terminate", -description:"Invalid system call", -standard:"other"}];exports.SIGNALS=SIGNALS; -//# sourceMappingURL=core.js.map +micromatch.not = (list, patterns, options = {}) => { + patterns = [].concat(patterns).map(String); + let result = new Set(); + let items = []; -/***/ }), + let onResult = state => { + if (options.onResult) options.onResult(state); + items.push(state.output); + }; -/***/ 4549: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + let matches = new Set(micromatch(list, patterns, { ...options, onResult })); -"use strict"; -Object.defineProperty(exports, "__esModule", ({value:true}));exports.signalsByNumber=exports.signalsByName=void 0;var _os=__nccwpck_require__(857); + for (let item of items) { + if (!matches.has(item)) { + result.add(item); + } + } + return [...result]; +}; -var _signals=__nccwpck_require__(1039); -var _realtime=__nccwpck_require__(5825); +/** + * Returns true if the given `string` contains the given pattern. Similar + * to [.isMatch](#isMatch) but the pattern can match any part of the string. + * + * ```js + * var mm = require('micromatch'); + * // mm.contains(string, pattern[, options]); + * + * console.log(mm.contains('aa/bb/cc', '*b')); + * //=> true + * console.log(mm.contains('aa/bb/cc', '*d')); + * //=> false + * ``` + * @param {String} `str` The string to match. + * @param {String|Array} `patterns` Glob pattern to use for matching. + * @param {Object} `options` See available [options](#options) for changing how matches are performed + * @return {Boolean} Returns true if any of the patterns matches any part of `str`. + * @api public + */ +micromatch.contains = (str, pattern, options) => { + if (typeof str !== 'string') { + throw new TypeError(`Expected a string: "${util.inspect(str)}"`); + } + if (Array.isArray(pattern)) { + return pattern.some(p => micromatch.contains(str, p, options)); + } -const getSignalsByName=function(){ -const signals=(0,_signals.getSignals)(); -return signals.reduce(getSignalByName,{}); -}; + if (typeof pattern === 'string') { + if (isEmptyString(str) || isEmptyString(pattern)) { + return false; + } -const getSignalByName=function( -signalByNameMemo, -{name,number,description,supported,action,forced,standard}) -{ -return{ -...signalByNameMemo, -[name]:{name,number,description,supported,action,forced,standard}}; + if (str.includes(pattern) || (str.startsWith('./') && str.slice(2).includes(pattern))) { + return true; + } + } + return micromatch.isMatch(str, pattern, { ...options, contains: true }); }; -const signalsByName=getSignalsByName();exports.signalsByName=signalsByName; - +/** + * Filter the keys of the given object with the given `glob` pattern + * and `options`. Does not attempt to match nested keys. If you need this feature, + * use [glob-object][] instead. + * + * ```js + * const mm = require('micromatch'); + * // mm.matchKeys(object, patterns[, options]); + * + * const obj = { aa: 'a', ab: 'b', ac: 'c' }; + * console.log(mm.matchKeys(obj, '*b')); + * //=> { ab: 'b' } + * ``` + * @param {Object} `object` The object with keys to filter. + * @param {String|Array} `patterns` One or more glob patterns to use for matching. + * @param {Object} `options` See available [options](#options) for changing how matches are performed + * @return {Object} Returns an object with only keys that match the given patterns. + * @api public + */ +micromatch.matchKeys = (obj, patterns, options) => { + if (!utils.isObject(obj)) { + throw new TypeError('Expected the first argument to be an object'); + } + let keys = micromatch(Object.keys(obj), patterns, options); + let res = {}; + for (let key of keys) res[key] = obj[key]; + return res; +}; +/** + * Returns true if some of the strings in the given `list` match any of the given glob `patterns`. + * + * ```js + * const mm = require('micromatch'); + * // mm.some(list, patterns[, options]); + * + * console.log(mm.some(['foo.js', 'bar.js'], ['*.js', '!foo.js'])); + * // true + * console.log(mm.some(['foo.js'], ['*.js', '!foo.js'])); + * // false + * ``` + * @param {String|Array} `list` The string or array of strings to test. Returns as soon as the first match is found. + * @param {String|Array} `patterns` One or more glob patterns to use for matching. + * @param {Object} `options` See available [options](#options) for changing how matches are performed + * @return {Boolean} Returns true if any `patterns` matches any of the strings in `list` + * @api public + */ -const getSignalsByNumber=function(){ -const signals=(0,_signals.getSignals)(); -const length=_realtime.SIGRTMAX+1; -const signalsA=Array.from({length},(value,number)=> -getSignalByNumber(number,signals)); +micromatch.some = (list, patterns, options) => { + let items = [].concat(list); -return Object.assign({},...signalsA); + for (let pattern of [].concat(patterns)) { + let isMatch = picomatch(String(pattern), options); + if (items.some(item => isMatch(item))) { + return true; + } + } + return false; }; -const getSignalByNumber=function(number,signals){ -const signal=findSignalByNumber(number,signals); - -if(signal===undefined){ -return{}; -} - -const{name,description,supported,action,forced,standard}=signal; -return{ -[number]:{ -name, -number, -description, -supported, -action, -forced, -standard}}; +/** + * Returns true if every string in the given `list` matches + * any of the given glob `patterns`. + * + * ```js + * const mm = require('micromatch'); + * // mm.every(list, patterns[, options]); + * + * console.log(mm.every('foo.js', ['foo.js'])); + * // true + * console.log(mm.every(['foo.js', 'bar.js'], ['*.js'])); + * // true + * console.log(mm.every(['foo.js', 'bar.js'], ['*.js', '!foo.js'])); + * // false + * console.log(mm.every(['foo.js'], ['*.js', '!foo.js'])); + * // false + * ``` + * @param {String|Array} `list` The string or array of strings to test. + * @param {String|Array} `patterns` One or more glob patterns to use for matching. + * @param {Object} `options` See available [options](#options) for changing how matches are performed + * @return {Boolean} Returns true if all `patterns` matches all of the strings in `list` + * @api public + */ +micromatch.every = (list, patterns, options) => { + let items = [].concat(list); + for (let pattern of [].concat(patterns)) { + let isMatch = picomatch(String(pattern), options); + if (!items.every(item => isMatch(item))) { + return false; + } + } + return true; }; +/** + * Returns true if **all** of the given `patterns` match + * the specified string. + * + * ```js + * const mm = require('micromatch'); + * // mm.all(string, patterns[, options]); + * + * console.log(mm.all('foo.js', ['foo.js'])); + * // true + * + * console.log(mm.all('foo.js', ['*.js', '!foo.js'])); + * // false + * + * console.log(mm.all('foo.js', ['*.js', 'foo.js'])); + * // true + * + * console.log(mm.all('foo.js', ['*.js', 'f*', '*o*', '*o.js'])); + * // true + * ``` + * @param {String|Array} `str` The string to test. + * @param {String|Array} `patterns` One or more glob patterns to use for matching. + * @param {Object} `options` See available [options](#options) for changing how matches are performed + * @return {Boolean} Returns true if any patterns match `str` + * @api public + */ +micromatch.all = (str, patterns, options) => { + if (typeof str !== 'string') { + throw new TypeError(`Expected a string: "${util.inspect(str)}"`); + } -const findSignalByNumber=function(number,signals){ -const signal=signals.find(({name})=>_os.constants.signals[name]===number); - -if(signal!==undefined){ -return signal; -} + return [].concat(patterns).every(p => picomatch(p, options)(str)); +}; -return signals.find(signalA=>signalA.number===number); +/** + * Returns an array of matches captured by `pattern` in `string, or `null` if the pattern did not match. + * + * ```js + * const mm = require('micromatch'); + * // mm.capture(pattern, string[, options]); + * + * console.log(mm.capture('test/*.js', 'test/foo.js')); + * //=> ['foo'] + * console.log(mm.capture('test/*.js', 'foo/bar.css')); + * //=> null + * ``` + * @param {String} `glob` Glob pattern to use for matching. + * @param {String} `input` String to match + * @param {Object} `options` See available [options](#options) for changing how matches are performed + * @return {Array|null} Returns an array of captures if the input matches the glob pattern, otherwise `null`. + * @api public + */ + +micromatch.capture = (glob, input, options) => { + let posix = utils.isWindows(options); + let regex = picomatch.makeRe(String(glob), { ...options, capture: true }); + let match = regex.exec(posix ? utils.toPosixSlashes(input) : input); + + if (match) { + return match.slice(1).map(v => v === void 0 ? '' : v); + } }; -const signalsByNumber=getSignalsByNumber();exports.signalsByNumber=signalsByNumber; -//# sourceMappingURL=main.js.map +/** + * Create a regular expression from the given glob `pattern`. + * + * ```js + * const mm = require('micromatch'); + * // mm.makeRe(pattern[, options]); + * + * console.log(mm.makeRe('*.js')); + * //=> /^(?:(\.[\\\/])?(?!\.)(?=.)[^\/]*?\.js)$/ + * ``` + * @param {String} `pattern` A glob pattern to convert to regex. + * @param {Object} `options` + * @return {RegExp} Returns a regex created from the given pattern. + * @api public + */ -/***/ }), +micromatch.makeRe = (...args) => picomatch.makeRe(...args); -/***/ 5825: -/***/ ((__unused_webpack_module, exports) => { +/** + * Scan a glob pattern to separate the pattern into segments. Used + * by the [split](#split) method. + * + * ```js + * const mm = require('micromatch'); + * const state = mm.scan(pattern[, options]); + * ``` + * @param {String} `pattern` + * @param {Object} `options` + * @return {Object} Returns an object with + * @api public + */ -"use strict"; -Object.defineProperty(exports, "__esModule", ({value:true}));exports.SIGRTMAX=exports.getRealtimeSignals=void 0; -const getRealtimeSignals=function(){ -const length=SIGRTMAX-SIGRTMIN+1; -return Array.from({length},getRealtimeSignal); -};exports.getRealtimeSignals=getRealtimeSignals; +micromatch.scan = (...args) => picomatch.scan(...args); -const getRealtimeSignal=function(value,index){ -return{ -name:`SIGRT${index+1}`, -number:SIGRTMIN+index, -action:"terminate", -description:"Application-specific signal (realtime)", -standard:"posix"}; +/** + * Parse a glob pattern to create the source string for a regular + * expression. + * + * ```js + * const mm = require('micromatch'); + * const state = mm.parse(pattern[, options]); + * ``` + * @param {String} `glob` + * @param {Object} `options` + * @return {Object} Returns an object with useful properties and output to be used as regex source string. + * @api public + */ +micromatch.parse = (patterns, options) => { + let res = []; + for (let pattern of [].concat(patterns || [])) { + for (let str of braces(String(pattern), options)) { + res.push(picomatch.parse(str, options)); + } + } + return res; }; -const SIGRTMIN=34; -const SIGRTMAX=64;exports.SIGRTMAX=SIGRTMAX; -//# sourceMappingURL=realtime.js.map +/** + * Process the given brace `pattern`. + * + * ```js + * const { braces } = require('micromatch'); + * console.log(braces('foo/{a,b,c}/bar')); + * //=> [ 'foo/(a|b|c)/bar' ] + * + * console.log(braces('foo/{a,b,c}/bar', { expand: true })); + * //=> [ 'foo/a/bar', 'foo/b/bar', 'foo/c/bar' ] + * ``` + * @param {String} `pattern` String with brace pattern to process. + * @param {Object} `options` Any [options](#options) to change how expansion is performed. See the [braces][] library for all available options. + * @return {Array} + * @api public + */ -/***/ }), +micromatch.braces = (pattern, options) => { + if (typeof pattern !== 'string') throw new TypeError('Expected a string'); + if ((options && options.nobrace === true) || !hasBraces(pattern)) { + return [pattern]; + } + return braces(pattern, options); +}; -/***/ 1039: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { +/** + * Expand braces + */ -"use strict"; -Object.defineProperty(exports, "__esModule", ({value:true}));exports.getSignals=void 0;var _os=__nccwpck_require__(857); +micromatch.braceExpand = (pattern, options) => { + if (typeof pattern !== 'string') throw new TypeError('Expected a string'); + return micromatch.braces(pattern, { ...options, expand: true }); +}; -var _core=__nccwpck_require__(6503); -var _realtime=__nccwpck_require__(5825); +/** + * Expose micromatch + */ +// exposed for tests +micromatch.hasBraces = hasBraces; +module.exports = micromatch; -const getSignals=function(){ -const realtimeSignals=(0,_realtime.getRealtimeSignals)(); -const signals=[..._core.SIGNALS,...realtimeSignals].map(normalizeSignal); -return signals; -};exports.getSignals=getSignals; +/***/ }), +/***/ 9382: +/***/ ((module) => { +const mimicFn = (to, from) => { + for (const prop of Reflect.ownKeys(from)) { + Object.defineProperty(to, prop, Object.getOwnPropertyDescriptor(from, prop)); + } + return to; +}; +module.exports = mimicFn; +// TODO: Remove this for the next major release +module.exports["default"] = mimicFn; -const normalizeSignal=function({ -name, -number:defaultNumber, -description, -action, -forced=false, -standard}) -{ -const{ -signals:{[name]:constantSignal}}= -_os.constants; -const supported=constantSignal!==undefined; -const number=supported?constantSignal:defaultNumber; -return{name,number,description,supported,action,forced,standard}; -}; -//# sourceMappingURL=signals.js.map /***/ }), -/***/ 842: -/***/ ((module) => { +/***/ 9584: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -// A simple implementation of make-array -function makeArray (subject) { - return Array.isArray(subject) - ? subject - : [subject] -} -const UNDEFINED = undefined -const EMPTY = '' -const SPACE = ' ' -const ESCAPE = '\\' -const REGEX_TEST_BLANK_LINE = /^\s+$/ -const REGEX_INVALID_TRAILING_BACKSLASH = /(?:[^\\]|^)\\$/ -const REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION = /^\\!/ -const REGEX_REPLACE_LEADING_EXCAPED_HASH = /^\\#/ -const REGEX_SPLITALL_CRLF = /\r?\n/g +const path = __nccwpck_require__(6928); +const pathKey = __nccwpck_require__(449); -// Invalid: -// - /foo, -// - ./foo, -// - ../foo, -// - . -// - .. -// Valid: -// - .foo -const REGEX_TEST_INVALID_PATH = /^\.{0,2}\/|^\.{1,2}$/ +const npmRunPath = options => { + options = { + cwd: process.cwd(), + path: process.env[pathKey()], + execPath: process.execPath, + ...options + }; -const REGEX_TEST_TRAILING_SLASH = /\/$/ + let previous; + let cwdPath = path.resolve(options.cwd); + const result = []; -const SLASH = '/' + while (previous !== cwdPath) { + result.push(path.join(cwdPath, 'node_modules/.bin')); + previous = cwdPath; + cwdPath = path.resolve(cwdPath, '..'); + } -// Do not use ternary expression here, since "istanbul ignore next" is buggy -let TMP_KEY_IGNORE = 'node-ignore' -/* istanbul ignore else */ -if (typeof Symbol !== 'undefined') { - TMP_KEY_IGNORE = Symbol.for('node-ignore') -} -const KEY_IGNORE = TMP_KEY_IGNORE + // Ensure the running `node` binary is used + const execPathDir = path.resolve(options.cwd, options.execPath, '..'); + result.push(execPathDir); -const define = (object, key, value) => { - Object.defineProperty(object, key, {value}) - return value -} + return result.concat(options.path).join(path.delimiter); +}; -const REGEX_REGEXP_RANGE = /([0-z])-([0-z])/g +module.exports = npmRunPath; +// TODO: Remove this for the next major release +module.exports["default"] = npmRunPath; -const RETURN_FALSE = () => false +module.exports.env = options => { + options = { + env: process.env, + ...options + }; -// Sanitize the range of a regular expression -// The cases are complicated, see test cases for details -const sanitizeRange = range => range.replace( - REGEX_REGEXP_RANGE, - (match, from, to) => from.charCodeAt(0) <= to.charCodeAt(0) - ? match - // Invalid range (out of order) which is ok for gitignore rules but - // fatal for JavaScript regular expression, so eliminate it. - : EMPTY -) + const env = {...options.env}; + const path = pathKey({env}); -// See fixtures #59 -const cleanRangeBackSlash = slashes => { - const {length} = slashes - return slashes.slice(0, length - length % 2) -} + options.path = env[path]; + env[path] = module.exports(options); -// > If the pattern ends with a slash, -// > it is removed for the purpose of the following description, -// > but it would only find a match with a directory. -// > In other words, foo/ will match a directory foo and paths underneath it, -// > but will not match a regular file or a symbolic link foo -// > (this is consistent with the way how pathspec works in general in Git). -// '`foo/`' will not match regular file '`foo`' or symbolic link '`foo`' -// -> ignore-rules will not deal with it, because it costs extra `fs.stat` call -// you could use option `mark: true` with `glob` + return env; +}; -// '`foo/`' should not continue with the '`..`' -const REPLACERS = [ - [ - // Remove BOM - // TODO: - // Other similar zero-width characters? - /^\uFEFF/, - () => EMPTY - ], +/***/ }), - // > Trailing spaces are ignored unless they are quoted with backslash ("\") - [ - // (a\ ) -> (a ) - // (a ) -> (a) - // (a ) -> (a) - // (a \ ) -> (a ) - /((?:\\\\)*?)(\\?\s+)$/, - (_, m1, m2) => m1 + ( - m2.indexOf('\\') === 0 - ? SPACE - : EMPTY - ) - ], +/***/ 5816: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - // Replace (\ ) with ' ' - // (\ ) -> ' ' - // (\\ ) -> '\\ ' - // (\\\ ) -> '\\ ' - [ - /(\\+?)\s/g, - (_, m1) => { - const {length} = m1 - return m1.slice(0, length - length % 2) + SPACE - } - ], - // Escape metacharacters - // which is written down by users but means special for regular expressions. +const mimicFn = __nccwpck_require__(9382); - // > There are 12 characters with special meanings: - // > - the backslash \, - // > - the caret ^, - // > - the dollar sign $, - // > - the period or dot ., - // > - the vertical bar or pipe symbol |, - // > - the question mark ?, - // > - the asterisk or star *, - // > - the plus sign +, - // > - the opening parenthesis (, - // > - the closing parenthesis ), - // > - and the opening square bracket [, - // > - the opening curly brace {, - // > These special characters are often called "metacharacters". - [ - /[\\$.|*+(){^]/g, - match => `\\${match}` - ], +const calledFunctions = new WeakMap(); - [ - // > a question mark (?) matches a single character - /(?!\\)\?/g, - () => '[^/]' - ], +const onetime = (function_, options = {}) => { + if (typeof function_ !== 'function') { + throw new TypeError('Expected a function'); + } - // leading slash - [ + let returnValue; + let callCount = 0; + const functionName = function_.displayName || function_.name || ''; - // > A leading slash matches the beginning of the pathname. - // > For example, "/*.c" matches "cat-file.c" but not "mozilla-sha1/sha1.c". - // A leading slash matches the beginning of the pathname - /^\//, - () => '^' - ], + const onetime = function (...arguments_) { + calledFunctions.set(onetime, ++callCount); - // replace special metacharacter slash after the leading slash - [ - /\//g, - () => '\\/' - ], + if (callCount === 1) { + returnValue = function_.apply(this, arguments_); + function_ = null; + } else if (options.throw === true) { + throw new Error(`Function \`${functionName}\` can only be called once`); + } - [ - // > A leading "**" followed by a slash means match in all directories. - // > For example, "**/foo" matches file or directory "foo" anywhere, - // > the same as pattern "foo". - // > "**/foo/bar" matches file or directory "bar" anywhere that is directly - // > under directory "foo". - // Notice that the '*'s have been replaced as '\\*' - /^\^*\\\*\\\*\\\//, + return returnValue; + }; - // '**/foo' <-> 'foo' - () => '^(?:.*\\/)?' - ], + mimicFn(onetime, function_); + calledFunctions.set(onetime, callCount); - // starting - [ - // there will be no leading '/' - // (which has been replaced by section "leading slash") - // If starts with '**', adding a '^' to the regular expression also works - /^(?=[^^])/, - function startingReplacer () { - // If has a slash `/` at the beginning or middle - return !/\/(?!$)/.test(this) - // > Prior to 2.22.1 - // > If the pattern does not contain a slash /, - // > Git treats it as a shell glob pattern - // Actually, if there is only a trailing slash, - // git also treats it as a shell glob pattern + return onetime; +}; - // After 2.22.1 (compatible but clearer) - // > If there is a separator at the beginning or middle (or both) - // > of the pattern, then the pattern is relative to the directory - // > level of the particular .gitignore file itself. - // > Otherwise the pattern may also match at any level below - // > the .gitignore level. - ? '(?:^|\\/)' +module.exports = onetime; +// TODO: Remove this for the next major release +module.exports["default"] = onetime; - // > Otherwise, Git treats the pattern as a shell glob suitable for - // > consumption by fnmatch(3) - : '^' - } - ], +module.exports.callCount = function_ => { + if (!calledFunctions.has(function_)) { + throw new Error(`The given function \`${function_.name}\` is not wrapped by the \`onetime\` package`); + } - // two globstars - [ - // Use lookahead assertions so that we could match more than one `'/**'` - /\\\/\\\*\\\*(?=\\\/|$)/g, + return calledFunctions.get(function_); +}; - // Zero, one or several directories - // should not use '*', or it will be replaced by the next replacer - // Check if it is not the last `'/**'` - (_, index, str) => index + 6 < str.length +/***/ }), - // case: /**/ - // > A slash followed by two consecutive asterisks then a slash matches - // > zero or more directories. - // > For example, "a/**/b" matches "a/b", "a/x/b", "a/x/y/b" and so on. - // '/**/' - ? '(?:\\/[^\\/]+)*' +/***/ 449: +/***/ ((module) => { - // case: /** - // > A trailing `"/**"` matches everything inside. - // #21: everything inside but it should not include the current folder - : '\\/.+' - ], - // normal intermediate wildcards - [ - // Never replace escaped '*' - // ignore rule '\*' will match the path '*' +const pathKey = (options = {}) => { + const environment = options.env || process.env; + const platform = options.platform || process.platform; - // 'abc.*/' -> go - // 'abc.*' -> skip this rule, - // coz trailing single wildcard will be handed by [trailing wildcard] - /(^|[^\\]+)(\\\*)+(?=.+)/g, + if (platform !== 'win32') { + return 'PATH'; + } - // '*.js' matches '.js' - // '*.js' doesn't match 'abc' - (_, p1, p2) => { - // 1. - // > An asterisk "*" matches anything except a slash. - // 2. - // > Other consecutive asterisks are considered regular asterisks - // > and will match according to the previous rules. - const unescaped = p2.replace(/\\\*/g, '[^\\/]*') - return p1 + unescaped - } - ], + return Object.keys(environment).reverse().find(key => key.toUpperCase() === 'PATH') || 'Path'; +}; - [ - // unescape, revert step 3 except for back slash - // For example, if a user escape a '\\*', - // after step 3, the result will be '\\\\\\*' - /\\\\\\(?=[$.|*+(){^])/g, - () => ESCAPE - ], +module.exports = pathKey; +// TODO: Remove this for the next major release +module.exports["default"] = pathKey; - [ - // '\\\\' -> '\\' - /\\\\/g, - () => ESCAPE - ], - [ - // > The range notation, e.g. [a-zA-Z], - // > can be used to match one of the characters in a range. - - // `\` is escaped by step 3 - /(\\)?\[([^\]/]*?)(\\*)($|\])/g, - (match, leadEscape, range, endEscape, close) => leadEscape === ESCAPE - // '\\[bar]' -> '\\\\[bar\\]' - ? `\\[${range}${cleanRangeBackSlash(endEscape)}${close}` - : close === ']' - ? endEscape.length % 2 === 0 - // A normal case, and it is a range notation - // '[bar]' - // '[bar\\\\]' - ? `[${sanitizeRange(range)}${endEscape}]` - // Invalid range notaton - // '[bar\\]' -> '[bar\\\\]' - : '[]' - : '[]' - ], +/***/ }), - // ending - [ - // 'js' will not match 'js.' - // 'ab' will not match 'abc' - /(?:[^*])$/, +/***/ 7774: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - // WTF! - // https://git-scm.com/docs/gitignore - // changes in [2.22.1](https://git-scm.com/docs/gitignore/2.22.1) - // which re-fixes #24, #38 - // > If there is a separator at the end of the pattern then the pattern - // > will only match directories, otherwise the pattern can match both - // > files and directories. - // 'js*' will not match 'a.js' - // 'js/' will not match 'a.js' - // 'js' will match 'a.js' and 'a.js/' - match => /\/$/.test(match) - // foo/ will not match 'foo' - ? `${match}$` - // foo matches 'foo' and 'foo/' - : `${match}(?=$|\\/$)` - ] -] +module.exports = __nccwpck_require__(3848); -const REGEX_REPLACE_TRAILING_WILDCARD = /(^|\\\/)?\\\*$/ -const MODE_IGNORE = 'regex' -const MODE_CHECK_IGNORE = 'checkRegex' -const UNDERSCORE = '_' -const TRAILING_WILD_CARD_REPLACERS = { - [MODE_IGNORE] (_, p1) { - const prefix = p1 - // '\^': - // '/*' does not match EMPTY - // '/*' does not match everything +/***/ }), - // '\\\/': - // 'abc/*' does not match 'abc/' - ? `${p1}[^/]+` +/***/ 435: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - // 'a*' matches 'a' - // 'a*' matches 'aa' - : '[^/]*' - return `${prefix}(?=$|\\/$)` - }, - [MODE_CHECK_IGNORE] (_, p1) { - // When doing `git check-ignore` - const prefix = p1 - // '\\\/': - // 'abc/*' DOES match 'abc/' ! - ? `${p1}[^/]*` +const path = __nccwpck_require__(6928); +const WIN_SLASH = '\\\\/'; +const WIN_NO_SLASH = `[^${WIN_SLASH}]`; - // 'a*' matches 'a' - // 'a*' matches 'aa' - : '[^/]*' +/** + * Posix glob regex + */ - return `${prefix}(?=$|\\/$)` - } -} +const DOT_LITERAL = '\\.'; +const PLUS_LITERAL = '\\+'; +const QMARK_LITERAL = '\\?'; +const SLASH_LITERAL = '\\/'; +const ONE_CHAR = '(?=.)'; +const QMARK = '[^/]'; +const END_ANCHOR = `(?:${SLASH_LITERAL}|$)`; +const START_ANCHOR = `(?:^|${SLASH_LITERAL})`; +const DOTS_SLASH = `${DOT_LITERAL}{1,2}${END_ANCHOR}`; +const NO_DOT = `(?!${DOT_LITERAL})`; +const NO_DOTS = `(?!${START_ANCHOR}${DOTS_SLASH})`; +const NO_DOT_SLASH = `(?!${DOT_LITERAL}{0,1}${END_ANCHOR})`; +const NO_DOTS_SLASH = `(?!${DOTS_SLASH})`; +const QMARK_NO_DOT = `[^.${SLASH_LITERAL}]`; +const STAR = `${QMARK}*?`; -// @param {pattern} -const makeRegexPrefix = pattern => REPLACERS.reduce( - (prev, [matcher, replacer]) => - prev.replace(matcher, replacer.bind(pattern)), - pattern -) +const POSIX_CHARS = { + DOT_LITERAL, + PLUS_LITERAL, + QMARK_LITERAL, + SLASH_LITERAL, + ONE_CHAR, + QMARK, + END_ANCHOR, + DOTS_SLASH, + NO_DOT, + NO_DOTS, + NO_DOT_SLASH, + NO_DOTS_SLASH, + QMARK_NO_DOT, + STAR, + START_ANCHOR +}; -const isString = subject => typeof subject === 'string' +/** + * Windows glob regex + */ -// > A blank line matches no files, so it can serve as a separator for readability. -const checkPattern = pattern => pattern - && isString(pattern) - && !REGEX_TEST_BLANK_LINE.test(pattern) - && !REGEX_INVALID_TRAILING_BACKSLASH.test(pattern) +const WINDOWS_CHARS = { + ...POSIX_CHARS, - // > A line starting with # serves as a comment. - && pattern.indexOf('#') !== 0 + SLASH_LITERAL: `[${WIN_SLASH}]`, + QMARK: WIN_NO_SLASH, + STAR: `${WIN_NO_SLASH}*?`, + DOTS_SLASH: `${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$)`, + NO_DOT: `(?!${DOT_LITERAL})`, + NO_DOTS: `(?!(?:^|[${WIN_SLASH}])${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$))`, + NO_DOT_SLASH: `(?!${DOT_LITERAL}{0,1}(?:[${WIN_SLASH}]|$))`, + NO_DOTS_SLASH: `(?!${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$))`, + QMARK_NO_DOT: `[^.${WIN_SLASH}]`, + START_ANCHOR: `(?:^|[${WIN_SLASH}])`, + END_ANCHOR: `(?:[${WIN_SLASH}]|$)` +}; -const splitPattern = pattern => pattern -.split(REGEX_SPLITALL_CRLF) -.filter(Boolean) +/** + * POSIX Bracket Regex + */ -class IgnoreRule { - constructor ( - pattern, - mark, - body, - ignoreCase, - negative, - prefix - ) { - this.pattern = pattern - this.mark = mark - this.negative = negative +const POSIX_REGEX_SOURCE = { + alnum: 'a-zA-Z0-9', + alpha: 'a-zA-Z', + ascii: '\\x00-\\x7F', + blank: ' \\t', + cntrl: '\\x00-\\x1F\\x7F', + digit: '0-9', + graph: '\\x21-\\x7E', + lower: 'a-z', + print: '\\x20-\\x7E ', + punct: '\\-!"#$%&\'()\\*+,./:;<=>?@[\\]^_`{|}~', + space: ' \\t\\r\\n\\v\\f', + upper: 'A-Z', + word: 'A-Za-z0-9_', + xdigit: 'A-Fa-f0-9' +}; - define(this, 'body', body) - define(this, 'ignoreCase', ignoreCase) - define(this, 'regexPrefix', prefix) - } +module.exports = { + MAX_LENGTH: 1024 * 64, + POSIX_REGEX_SOURCE, - get regex () { - const key = UNDERSCORE + MODE_IGNORE + // regular expressions + REGEX_BACKSLASH: /\\(?![*+?^${}(|)[\]])/g, + REGEX_NON_SPECIAL_CHARS: /^[^@![\].,$*+?^{}()|\\/]+/, + REGEX_SPECIAL_CHARS: /[-*+?.^${}(|)[\]]/, + REGEX_SPECIAL_CHARS_BACKREF: /(\\?)((\W)(\3*))/g, + REGEX_SPECIAL_CHARS_GLOBAL: /([-*+?.^${}(|)[\]])/g, + REGEX_REMOVE_BACKSLASH: /(?:\[.*?[^\\]\]|\\(?=.))/g, - if (this[key]) { - return this[key] - } + // Replace globs with equivalent patterns to reduce parsing time. + REPLACEMENTS: { + '***': '*', + '**/**': '**', + '**/**/**': '**' + }, - return this._make(MODE_IGNORE, key) - } + // Digits + CHAR_0: 48, /* 0 */ + CHAR_9: 57, /* 9 */ - get checkRegex () { - const key = UNDERSCORE + MODE_CHECK_IGNORE + // Alphabet chars. + CHAR_UPPERCASE_A: 65, /* A */ + CHAR_LOWERCASE_A: 97, /* a */ + CHAR_UPPERCASE_Z: 90, /* Z */ + CHAR_LOWERCASE_Z: 122, /* z */ - if (this[key]) { - return this[key] - } + CHAR_LEFT_PARENTHESES: 40, /* ( */ + CHAR_RIGHT_PARENTHESES: 41, /* ) */ - return this._make(MODE_CHECK_IGNORE, key) - } + CHAR_ASTERISK: 42, /* * */ - _make (mode, key) { - const str = this.regexPrefix.replace( - REGEX_REPLACE_TRAILING_WILDCARD, + // Non-alphabetic chars. + CHAR_AMPERSAND: 38, /* & */ + CHAR_AT: 64, /* @ */ + CHAR_BACKWARD_SLASH: 92, /* \ */ + CHAR_CARRIAGE_RETURN: 13, /* \r */ + CHAR_CIRCUMFLEX_ACCENT: 94, /* ^ */ + CHAR_COLON: 58, /* : */ + CHAR_COMMA: 44, /* , */ + CHAR_DOT: 46, /* . */ + CHAR_DOUBLE_QUOTE: 34, /* " */ + CHAR_EQUAL: 61, /* = */ + CHAR_EXCLAMATION_MARK: 33, /* ! */ + CHAR_FORM_FEED: 12, /* \f */ + CHAR_FORWARD_SLASH: 47, /* / */ + CHAR_GRAVE_ACCENT: 96, /* ` */ + CHAR_HASH: 35, /* # */ + CHAR_HYPHEN_MINUS: 45, /* - */ + CHAR_LEFT_ANGLE_BRACKET: 60, /* < */ + CHAR_LEFT_CURLY_BRACE: 123, /* { */ + CHAR_LEFT_SQUARE_BRACKET: 91, /* [ */ + CHAR_LINE_FEED: 10, /* \n */ + CHAR_NO_BREAK_SPACE: 160, /* \u00A0 */ + CHAR_PERCENT: 37, /* % */ + CHAR_PLUS: 43, /* + */ + CHAR_QUESTION_MARK: 63, /* ? */ + CHAR_RIGHT_ANGLE_BRACKET: 62, /* > */ + CHAR_RIGHT_CURLY_BRACE: 125, /* } */ + CHAR_RIGHT_SQUARE_BRACKET: 93, /* ] */ + CHAR_SEMICOLON: 59, /* ; */ + CHAR_SINGLE_QUOTE: 39, /* ' */ + CHAR_SPACE: 32, /* */ + CHAR_TAB: 9, /* \t */ + CHAR_UNDERSCORE: 95, /* _ */ + CHAR_VERTICAL_LINE: 124, /* | */ + CHAR_ZERO_WIDTH_NOBREAK_SPACE: 65279, /* \uFEFF */ - // It does not need to bind pattern - TRAILING_WILD_CARD_REPLACERS[mode] - ) + SEP: path.sep, - const regex = this.ignoreCase - ? new RegExp(str, 'i') - : new RegExp(str) + /** + * Create EXTGLOB_CHARS + */ - return define(this, key, regex) - } -} + extglobChars(chars) { + return { + '!': { type: 'negate', open: '(?:(?!(?:', close: `))${chars.STAR})` }, + '?': { type: 'qmark', open: '(?:', close: ')?' }, + '+': { type: 'plus', open: '(?:', close: ')+' }, + '*': { type: 'star', open: '(?:', close: ')*' }, + '@': { type: 'at', open: '(?:', close: ')' } + }; + }, -const createRule = ({ - pattern, - mark -}, ignoreCase) => { - let negative = false - let body = pattern + /** + * Create GLOB_CHARS + */ - // > An optional prefix "!" which negates the pattern; - if (body.indexOf('!') === 0) { - negative = true - body = body.substr(1) + globChars(win32) { + return win32 === true ? WINDOWS_CHARS : POSIX_CHARS; } +}; - body = body - // > Put a backslash ("\") in front of the first "!" for patterns that - // > begin with a literal "!", for example, `"\!important!.txt"`. - .replace(REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION, '!') - // > Put a backslash ("\") in front of the first hash for patterns that - // > begin with a hash. - .replace(REGEX_REPLACE_LEADING_EXCAPED_HASH, '#') - const regexPrefix = makeRegexPrefix(body) +/***/ }), - return new IgnoreRule( - pattern, - mark, - body, - ignoreCase, - negative, - regexPrefix - ) -} +/***/ 9153: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -class RuleManager { - constructor (ignoreCase) { - this._ignoreCase = ignoreCase - this._rules = [] - } - _add (pattern) { - // #32 - if (pattern && pattern[KEY_IGNORE]) { - this._rules = this._rules.concat(pattern._rules._rules) - this._added = true - return - } - if (isString(pattern)) { - pattern = { - pattern - } - } +const constants = __nccwpck_require__(435); +const utils = __nccwpck_require__(7379); - if (checkPattern(pattern.pattern)) { - const rule = createRule(pattern, this._ignoreCase) - this._added = true - this._rules.push(rule) - } - } +/** + * Constants + */ - // @param {Array | string | Ignore} pattern - add (pattern) { - this._added = false +const { + MAX_LENGTH, + POSIX_REGEX_SOURCE, + REGEX_NON_SPECIAL_CHARS, + REGEX_SPECIAL_CHARS_BACKREF, + REPLACEMENTS +} = constants; - makeArray( - isString(pattern) - ? splitPattern(pattern) - : pattern - ).forEach(this._add, this) +/** + * Helpers + */ - return this._added +const expandRange = (args, options) => { + if (typeof options.expandRange === 'function') { + return options.expandRange(...args, options); } - // Test one single path without recursively checking parent directories - // - // - checkUnignored `boolean` whether should check if the path is unignored, - // setting `checkUnignored` to `false` could reduce additional - // path matching. - // - check `string` either `MODE_IGNORE` or `MODE_CHECK_IGNORE` - - // @returns {TestResult} true if a file is ignored - test (path, checkUnignored, mode) { - let ignored = false - let unignored = false - let matchedRule - - this._rules.forEach(rule => { - const {negative} = rule + args.sort(); + const value = `[${args.join('-')}]`; - // | ignored : unignored - // -------- | --------------------------------------- - // negative | 0:0 | 0:1 | 1:0 | 1:1 - // -------- | ------- | ------- | ------- | -------- - // 0 | TEST | TEST | SKIP | X - // 1 | TESTIF | SKIP | TEST | X + try { + /* eslint-disable-next-line no-new */ + new RegExp(value); + } catch (ex) { + return args.map(v => utils.escapeRegex(v)).join('..'); + } - // - SKIP: always skip - // - TEST: always test - // - TESTIF: only test if checkUnignored - // - X: that never happen - if ( - unignored === negative && ignored !== unignored - || negative && !ignored && !unignored && !checkUnignored - ) { - return - } + return value; +}; - const matched = rule[mode].test(path) +/** + * Create the message for a syntax error + */ - if (!matched) { - return - } +const syntaxError = (type, char) => { + return `Missing ${type}: "${char}" - use "\\\\${char}" to match literal characters`; +}; - ignored = !negative - unignored = negative +/** + * Parse the given input string. + * @param {String} input + * @param {Object} options + * @return {Object} + */ - matchedRule = negative - ? UNDEFINED - : rule - }) +const parse = (input, options) => { + if (typeof input !== 'string') { + throw new TypeError('Expected a string'); + } - const ret = { - ignored, - unignored - } + input = REPLACEMENTS[input] || input; - if (matchedRule) { - ret.rule = matchedRule - } + const opts = { ...options }; + const max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH; - return ret + let len = input.length; + if (len > max) { + throw new SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`); } -} -const throwError = (message, Ctor) => { - throw new Ctor(message) -} + const bos = { type: 'bos', value: '', output: opts.prepend || '' }; + const tokens = [bos]; -const checkPath = (path, originalPath, doThrow) => { - if (!isString(path)) { - return doThrow( - `path must be a string, but got \`${originalPath}\``, - TypeError - ) - } + const capture = opts.capture ? '' : '?:'; + const win32 = utils.isWindows(options); - // We don't know if we should ignore EMPTY, so throw - if (!path) { - return doThrow(`path must not be empty`, TypeError) - } + // create constants based on platform, for windows or posix + const PLATFORM_CHARS = constants.globChars(win32); + const EXTGLOB_CHARS = constants.extglobChars(PLATFORM_CHARS); - // Check if it is a relative path - if (checkPath.isNotRelative(path)) { - const r = '`path.relative()`d' - return doThrow( - `path should be a ${r} string, but got "${originalPath}"`, - RangeError - ) - } + const { + DOT_LITERAL, + PLUS_LITERAL, + SLASH_LITERAL, + ONE_CHAR, + DOTS_SLASH, + NO_DOT, + NO_DOT_SLASH, + NO_DOTS_SLASH, + QMARK, + QMARK_NO_DOT, + STAR, + START_ANCHOR + } = PLATFORM_CHARS; - return true -} + const globstar = opts => { + return `(${capture}(?:(?!${START_ANCHOR}${opts.dot ? DOTS_SLASH : DOT_LITERAL}).)*?)`; + }; -const isNotRelative = path => REGEX_TEST_INVALID_PATH.test(path) + const nodot = opts.dot ? '' : NO_DOT; + const qmarkNoDot = opts.dot ? QMARK : QMARK_NO_DOT; + let star = opts.bash === true ? globstar(opts) : STAR; -checkPath.isNotRelative = isNotRelative + if (opts.capture) { + star = `(${star})`; + } -// On windows, the following function will be replaced -/* istanbul ignore next */ -checkPath.convert = p => p + // minimatch options support + if (typeof opts.noext === 'boolean') { + opts.noextglob = opts.noext; + } + const state = { + input, + index: -1, + start: 0, + dot: opts.dot === true, + consumed: '', + output: '', + prefix: '', + backtrack: false, + negated: false, + brackets: 0, + braces: 0, + parens: 0, + quotes: 0, + globstar: false, + tokens + }; -class Ignore { - constructor ({ - ignorecase = true, - ignoreCase = ignorecase, - allowRelativePaths = false - } = {}) { - define(this, KEY_IGNORE, true) - - this._rules = new RuleManager(ignoreCase) - this._strictPathCheck = !allowRelativePaths - this._initCache() - } - - _initCache () { - // A cache for the result of `.ignores()` - this._ignoreCache = Object.create(null) - - // A cache for the result of `.test()` - this._testCache = Object.create(null) - } - - add (pattern) { - if (this._rules.add(pattern)) { - // Some rules have just added to the ignore, - // making the behavior changed, - // so we need to re-initialize the result cache - this._initCache() - } + input = utils.removePrefix(input, state); + len = input.length; - return this - } + const extglobs = []; + const braces = []; + const stack = []; + let prev = bos; + let value; - // legacy - addPattern (pattern) { - return this.add(pattern) - } + /** + * Tokenizing helpers + */ - // @returns {TestResult} - _test (originalPath, cache, checkUnignored, slices) { - const path = originalPath - // Supports nullable path - && checkPath.convert(originalPath) + const eos = () => state.index === len - 1; + const peek = state.peek = (n = 1) => input[state.index + n]; + const advance = state.advance = () => input[++state.index] || ''; + const remaining = () => input.slice(state.index + 1); + const consume = (value = '', num = 0) => { + state.consumed += value; + state.index += num; + }; - checkPath( - path, - originalPath, - this._strictPathCheck - ? throwError - : RETURN_FALSE - ) + const append = token => { + state.output += token.output != null ? token.output : token.value; + consume(token.value); + }; - return this._t(path, cache, checkUnignored, slices) - } + const negate = () => { + let count = 1; - checkIgnore (path) { - // If the path doest not end with a slash, `.ignores()` is much equivalent - // to `git check-ignore` - if (!REGEX_TEST_TRAILING_SLASH.test(path)) { - return this.test(path) + while (peek() === '!' && (peek(2) !== '(' || peek(3) === '?')) { + advance(); + state.start++; + count++; } - const slices = path.split(SLASH).filter(Boolean) - slices.pop() - - if (slices.length) { - const parent = this._t( - slices.join(SLASH) + SLASH, - this._testCache, - true, - slices - ) - - if (parent.ignored) { - return parent - } + if (count % 2 === 0) { + return false; } - return this._rules.test(path, false, MODE_CHECK_IGNORE) - } + state.negated = true; + state.start++; + return true; + }; - _t ( - // The path to be tested - path, + const increment = type => { + state[type]++; + stack.push(type); + }; - // The cache for the result of a certain checking - cache, + const decrement = type => { + state[type]--; + stack.pop(); + }; - // Whether should check if the path is unignored - checkUnignored, + /** + * Push tokens onto the tokens array. This helper speeds up + * tokenizing by 1) helping us avoid backtracking as much as possible, + * and 2) helping us avoid creating extra tokens when consecutive + * characters are plain text. This improves performance and simplifies + * lookbehinds. + */ - // The path slices - slices - ) { - if (path in cache) { - return cache[path] - } + const push = tok => { + if (prev.type === 'globstar') { + const isBrace = state.braces > 0 && (tok.type === 'comma' || tok.type === 'brace'); + const isExtglob = tok.extglob === true || (extglobs.length && (tok.type === 'pipe' || tok.type === 'paren')); - if (!slices) { - // path/to/a.js - // ['path', 'to', 'a.js'] - slices = path.split(SLASH).filter(Boolean) + if (tok.type !== 'slash' && tok.type !== 'paren' && !isBrace && !isExtglob) { + state.output = state.output.slice(0, -prev.output.length); + prev.type = 'star'; + prev.value = '*'; + prev.output = star; + state.output += prev.output; + } } - slices.pop() - - // If the path has no parent directory, just test it - if (!slices.length) { - return cache[path] = this._rules.test(path, checkUnignored, MODE_IGNORE) + if (extglobs.length && tok.type !== 'paren') { + extglobs[extglobs.length - 1].inner += tok.value; } - const parent = this._t( - slices.join(SLASH) + SLASH, - cache, - checkUnignored, - slices - ) - - // If the path contains a parent directory, check the parent first - return cache[path] = parent.ignored - // > It is not possible to re-include a file if a parent directory of - // > that file is excluded. - ? parent - : this._rules.test(path, checkUnignored, MODE_IGNORE) - } - - ignores (path) { - return this._test(path, this._ignoreCache, false).ignored - } + if (tok.value || tok.output) append(tok); + if (prev && prev.type === 'text' && tok.type === 'text') { + prev.value += tok.value; + prev.output = (prev.output || '') + tok.value; + return; + } - createFilter () { - return path => !this.ignores(path) - } + tok.prev = prev; + tokens.push(tok); + prev = tok; + }; - filter (paths) { - return makeArray(paths).filter(this.createFilter()) - } + const extglobOpen = (type, value) => { + const token = { ...EXTGLOB_CHARS[value], conditions: 1, inner: '' }; - // @returns {TestResult} - test (path) { - return this._test(path, this._testCache, true) - } -} + token.prev = prev; + token.parens = state.parens; + token.output = state.output; + const output = (opts.capture ? '(' : '') + token.open; -const factory = options => new Ignore(options) + increment('parens'); + push({ type, value, output: state.output ? '' : ONE_CHAR }); + push({ type: 'paren', extglob: true, value: advance(), output }); + extglobs.push(token); + }; -const isPathValid = path => - checkPath(path && checkPath.convert(path), path, RETURN_FALSE) + const extglobClose = token => { + let output = token.close + (opts.capture ? ')' : ''); + let rest; -/* istanbul ignore next */ -const setupWindows = () => { - /* eslint no-control-regex: "off" */ - const makePosix = str => /^\\\\\?\\/.test(str) - || /["<>|\u0000-\u001F]+/u.test(str) - ? str - : str.replace(/\\/g, '/') + if (token.type === 'negate') { + let extglobStar = star; - checkPath.convert = makePosix + if (token.inner && token.inner.length > 1 && token.inner.includes('/')) { + extglobStar = globstar(opts); + } - // 'C:\\foo' <- 'C:\\foo' has been converted to 'C:/' - // 'd:\\foo' - const REGEX_TEST_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i - checkPath.isNotRelative = path => - REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path) - || isNotRelative(path) -} + if (extglobStar !== star || eos() || /^\)+$/.test(remaining())) { + output = token.close = `)$))${extglobStar}`; + } + if (token.inner.includes('*') && (rest = remaining()) && /^\.[^\\/.]+$/.test(rest)) { + // Any non-magical string (`.ts`) or even nested expression (`.{ts,tsx}`) can follow after the closing parenthesis. + // In this case, we need to parse the string and use it in the output of the original pattern. + // Suitable patterns: `/!(*.d).ts`, `/!(*.d).{ts,tsx}`, `**/!(*-dbg).@(js)`. + // + // Disabling the `fastpaths` option due to a problem with parsing strings as `.ts` in the pattern like `**/!(*.d).ts`. + const expression = parse(rest, { ...options, fastpaths: false }).output; -// Windows -// -------------------------------------------------------------- -/* istanbul ignore next */ -if ( - // Detect `process` so that it can run in browsers. - typeof process !== 'undefined' - && process.platform === 'win32' -) { - setupWindows() -} + output = token.close = `)${expression})${extglobStar})`; + } -// COMMONJS_EXPORTS //////////////////////////////////////////////////////////// + if (token.prev.type === 'bos') { + state.negatedExtglob = true; + } + } -module.exports = factory + push({ type: 'paren', extglob: true, value, output }); + decrement('parens'); + }; -// Although it is an anti-pattern, -// it is still widely misused by a lot of libraries in github -// Ref: https://github.com/search?q=ignore.default%28%29&type=code -factory.default = factory + /** + * Fast paths + */ -module.exports.isPathValid = isPathValid + if (opts.fastpaths !== false && !/(^[*!]|[/()[\]{}"])/.test(input)) { + let backslashes = false; -// For testing purposes -define(module.exports, Symbol.for('setupWindows'), setupWindows) + let output = input.replace(REGEX_SPECIAL_CHARS_BACKREF, (m, esc, chars, first, rest, index) => { + if (first === '\\') { + backslashes = true; + return m; + } + if (first === '?') { + if (esc) { + return esc + first + (rest ? QMARK.repeat(rest.length) : ''); + } + if (index === 0) { + return qmarkNoDot + (rest ? QMARK.repeat(rest.length) : ''); + } + return QMARK.repeat(chars.length); + } -/***/ }), + if (first === '.') { + return DOT_LITERAL.repeat(chars.length); + } -/***/ 729: -/***/ ((module) => { + if (first === '*') { + if (esc) { + return esc + first + (rest ? star : ''); + } + return star; + } + return esc ? m : `\\${m}`; + }); -/*! - * is-extglob - * - * Copyright (c) 2014-2016, Jon Schlinkert. - * Licensed under the MIT License. - */ + if (backslashes === true) { + if (opts.unescape === true) { + output = output.replace(/\\/g, ''); + } else { + output = output.replace(/\\+/g, m => { + return m.length % 2 === 0 ? '\\\\' : (m ? '\\' : ''); + }); + } + } -module.exports = function isExtglob(str) { - if (typeof str !== 'string' || str === '') { - return false; - } + if (output === input && opts.contains === true) { + state.output = input; + return state; + } - var match; - while ((match = /(\\).|([@?!+*]\(.*\))/g.exec(str))) { - if (match[2]) return true; - str = str.slice(match.index + match[0].length); + state.output = utils.wrapOutput(output, state, options); + return state; } - return false; -}; + /** + * Tokenize input until we reach end-of-string + */ + while (!eos()) { + value = advance(); -/***/ }), + if (value === '\u0000') { + continue; + } -/***/ 6689: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + /** + * Escaped characters + */ -/*! - * is-glob - * - * Copyright (c) 2014-2017, Jon Schlinkert. - * Released under the MIT License. - */ + if (value === '\\') { + const next = peek(); -var isExtglob = __nccwpck_require__(729); -var chars = { '{': '}', '(': ')', '[': ']'}; -var strictCheck = function(str) { - if (str[0] === '!') { - return true; - } - var index = 0; - var pipeIndex = -2; - var closeSquareIndex = -2; - var closeCurlyIndex = -2; - var closeParenIndex = -2; - var backSlashIndex = -2; - while (index < str.length) { - if (str[index] === '*') { - return true; - } + if (next === '/' && opts.bash !== true) { + continue; + } - if (str[index + 1] === '?' && /[\].+)]/.test(str[index])) { - return true; - } + if (next === '.' || next === ';') { + continue; + } - if (closeSquareIndex !== -1 && str[index] === '[' && str[index + 1] !== ']') { - if (closeSquareIndex < index) { - closeSquareIndex = str.indexOf(']', index); + if (!next) { + value += '\\'; + push({ type: 'text', value }); + continue; } - if (closeSquareIndex > index) { - if (backSlashIndex === -1 || backSlashIndex > closeSquareIndex) { - return true; - } - backSlashIndex = str.indexOf('\\', index); - if (backSlashIndex === -1 || backSlashIndex > closeSquareIndex) { - return true; + + // collapse slashes to reduce potential for exploits + const match = /^\\+/.exec(remaining()); + let slashes = 0; + + if (match && match[0].length > 2) { + slashes = match[0].length; + state.index += slashes; + if (slashes % 2 !== 0) { + value += '\\'; } } - } - if (closeCurlyIndex !== -1 && str[index] === '{' && str[index + 1] !== '}') { - closeCurlyIndex = str.indexOf('}', index); - if (closeCurlyIndex > index) { - backSlashIndex = str.indexOf('\\', index); - if (backSlashIndex === -1 || backSlashIndex > closeCurlyIndex) { - return true; - } + if (opts.unescape === true) { + value = advance(); + } else { + value += advance(); } - } - if (closeParenIndex !== -1 && str[index] === '(' && str[index + 1] === '?' && /[:!=]/.test(str[index + 2]) && str[index + 3] !== ')') { - closeParenIndex = str.indexOf(')', index); - if (closeParenIndex > index) { - backSlashIndex = str.indexOf('\\', index); - if (backSlashIndex === -1 || backSlashIndex > closeParenIndex) { - return true; - } + if (state.brackets === 0) { + push({ type: 'text', value }); + continue; } } - if (pipeIndex !== -1 && str[index] === '(' && str[index + 1] !== '|') { - if (pipeIndex < index) { - pipeIndex = str.indexOf('|', index); - } - if (pipeIndex !== -1 && str[pipeIndex + 1] !== ')') { - closeParenIndex = str.indexOf(')', pipeIndex); - if (closeParenIndex > pipeIndex) { - backSlashIndex = str.indexOf('\\', pipeIndex); - if (backSlashIndex === -1 || backSlashIndex > closeParenIndex) { - return true; + /** + * If we're inside a regex character class, continue + * until we reach the closing bracket. + */ + + if (state.brackets > 0 && (value !== ']' || prev.value === '[' || prev.value === '[^')) { + if (opts.posix !== false && value === ':') { + const inner = prev.value.slice(1); + if (inner.includes('[')) { + prev.posix = true; + + if (inner.includes(':')) { + const idx = prev.value.lastIndexOf('['); + const pre = prev.value.slice(0, idx); + const rest = prev.value.slice(idx + 2); + const posix = POSIX_REGEX_SOURCE[rest]; + if (posix) { + prev.value = pre + posix; + state.backtrack = true; + advance(); + + if (!bos.output && tokens.indexOf(prev) === 1) { + bos.output = ONE_CHAR; + } + continue; + } } } } - } - if (str[index] === '\\') { - var open = str[index + 1]; - index += 2; - var close = chars[open]; + if ((value === '[' && peek() !== ':') || (value === '-' && peek() === ']')) { + value = `\\${value}`; + } - if (close) { - var n = str.indexOf(close, index); - if (n !== -1) { - index = n + 1; - } + if (value === ']' && (prev.value === '[' || prev.value === '[^')) { + value = `\\${value}`; } - if (str[index] === '!') { - return true; + if (opts.posix === true && value === '!' && prev.value === '[') { + value = '^'; } - } else { - index++; - } - } - return false; -}; -var relaxedCheck = function(str) { - if (str[0] === '!') { - return true; - } - var index = 0; - while (index < str.length) { - if (/[*?{}()[\]]/.test(str[index])) { - return true; + prev.value += value; + append({ value }); + continue; } - if (str[index] === '\\') { - var open = str[index + 1]; - index += 2; - var close = chars[open]; + /** + * If we're inside a quoted string, continue + * until we reach the closing double quote. + */ - if (close) { - var n = str.indexOf(close, index); - if (n !== -1) { - index = n + 1; - } - } + if (state.quotes === 1 && value !== '"') { + value = utils.escapeRegex(value); + prev.value += value; + append({ value }); + continue; + } - if (str[index] === '!') { - return true; + /** + * Double quotes + */ + + if (value === '"') { + state.quotes = state.quotes === 1 ? 0 : 1; + if (opts.keepQuotes === true) { + push({ type: 'text', value }); } - } else { - index++; + continue; } - } - return false; -}; - -module.exports = function isGlob(str, options) { - if (typeof str !== 'string' || str === '') { - return false; - } - if (isExtglob(str)) { - return true; - } + /** + * Parentheses + */ - var check = strictCheck; + if (value === '(') { + increment('parens'); + push({ type: 'paren', value }); + continue; + } - // optionally relax check - if (options && options.strict === false) { - check = relaxedCheck; - } + if (value === ')') { + if (state.parens === 0 && opts.strictBrackets === true) { + throw new SyntaxError(syntaxError('opening', '(')); + } - return check(str); -}; + const extglob = extglobs[extglobs.length - 1]; + if (extglob && state.parens === extglob.parens + 1) { + extglobClose(extglobs.pop()); + continue; + } + push({ type: 'paren', value, output: state.parens ? ')' : '\\)' }); + decrement('parens'); + continue; + } -/***/ }), + /** + * Square brackets + */ -/***/ 3491: -/***/ ((module) => { + if (value === '[') { + if (opts.nobracket === true || !remaining().includes(']')) { + if (opts.nobracket !== true && opts.strictBrackets === true) { + throw new SyntaxError(syntaxError('closing', ']')); + } -"use strict"; -/*! - * is-number - * - * Copyright (c) 2014-present, Jon Schlinkert. - * Released under the MIT License. - */ + value = `\\${value}`; + } else { + increment('brackets'); + } + push({ type: 'bracket', value }); + continue; + } + if (value === ']') { + if (opts.nobracket === true || (prev && prev.type === 'bracket' && prev.value.length === 1)) { + push({ type: 'text', value, output: `\\${value}` }); + continue; + } -module.exports = function(num) { - if (typeof num === 'number') { - return num - num === 0; - } - if (typeof num === 'string' && num.trim() !== '') { - return Number.isFinite ? Number.isFinite(+num) : isFinite(+num); - } - return false; -}; + if (state.brackets === 0) { + if (opts.strictBrackets === true) { + throw new SyntaxError(syntaxError('opening', '[')); + } + push({ type: 'text', value, output: `\\${value}` }); + continue; + } -/***/ }), + decrement('brackets'); -/***/ 9828: -/***/ ((module) => { + const prevValue = prev.value.slice(1); + if (prev.posix !== true && prevValue[0] === '^' && !prevValue.includes('/')) { + value = `/${value}`; + } -"use strict"; + prev.value += value; + append({ value }); + // when literal brackets are explicitly disabled + // assume we should match with a regex character class + if (opts.literalBrackets === false || utils.hasRegexChars(prevValue)) { + continue; + } -const isStream = stream => - stream !== null && - typeof stream === 'object' && - typeof stream.pipe === 'function'; + const escaped = utils.escapeRegex(prev.value); + state.output = state.output.slice(0, -prev.value.length); -isStream.writable = stream => - isStream(stream) && - stream.writable !== false && - typeof stream._write === 'function' && - typeof stream._writableState === 'object'; + // when literal brackets are explicitly enabled + // assume we should escape the brackets to match literal characters + if (opts.literalBrackets === true) { + state.output += escaped; + prev.value = escaped; + continue; + } -isStream.readable = stream => - isStream(stream) && - stream.readable !== false && - typeof stream._read === 'function' && - typeof stream._readableState === 'object'; + // when the user specifies nothing, try to match both + prev.value = `(${capture}${escaped}|${prev.value})`; + state.output += prev.value; + continue; + } -isStream.duplex = stream => - isStream.writable(stream) && - isStream.readable(stream); + /** + * Braces + */ -isStream.transform = stream => - isStream.duplex(stream) && - typeof stream._transform === 'function'; + if (value === '{' && opts.nobrace !== true) { + increment('braces'); -module.exports = isStream; + const open = { + type: 'brace', + value, + output: '(', + outputIndex: state.output.length, + tokensIndex: state.tokens.length + }; + braces.push(open); + push(open); + continue; + } -/***/ }), + if (value === '}') { + const brace = braces[braces.length - 1]; -/***/ 1485: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + if (opts.nobrace === true || !brace) { + push({ type: 'text', value, output: value }); + continue; + } -var fs = __nccwpck_require__(9896) -var core -if (process.platform === 'win32' || global.TESTING_WINDOWS) { - core = __nccwpck_require__(5680) -} else { - core = __nccwpck_require__(7262) -} + let output = ')'; -module.exports = isexe -isexe.sync = sync + if (brace.dots === true) { + const arr = tokens.slice(); + const range = []; -function isexe (path, options, cb) { - if (typeof options === 'function') { - cb = options - options = {} - } + for (let i = arr.length - 1; i >= 0; i--) { + tokens.pop(); + if (arr[i].type === 'brace') { + break; + } + if (arr[i].type !== 'dots') { + range.unshift(arr[i].value); + } + } - if (!cb) { - if (typeof Promise !== 'function') { - throw new TypeError('callback not provided') - } + output = expandRange(range, opts); + state.backtrack = true; + } - return new Promise(function (resolve, reject) { - isexe(path, options || {}, function (er, is) { - if (er) { - reject(er) - } else { - resolve(is) + if (brace.comma !== true && brace.dots !== true) { + const out = state.output.slice(0, brace.outputIndex); + const toks = state.tokens.slice(brace.tokensIndex); + brace.value = brace.output = '\\{'; + value = output = '\\}'; + state.output = out; + for (const t of toks) { + state.output += (t.output || t.value); } - }) - }) - } - - core(path, options || {}, function (er, is) { - // ignore EACCES because that just means we aren't allowed to run it - if (er) { - if (er.code === 'EACCES' || options && options.ignoreErrors) { - er = null - is = false } - } - cb(er, is) - }) -} -function sync (path, options) { - // my kingdom for a filtered catch - try { - return core.sync(path, options || {}) - } catch (er) { - if (options && options.ignoreErrors || er.code === 'EACCES') { - return false - } else { - throw er + push({ type: 'brace', value, output }); + decrement('braces'); + braces.pop(); + continue; } - } -} + /** + * Pipes + */ -/***/ }), + if (value === '|') { + if (extglobs.length > 0) { + extglobs[extglobs.length - 1].conditions++; + } + push({ type: 'text', value }); + continue; + } -/***/ 7262: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + /** + * Commas + */ -module.exports = isexe -isexe.sync = sync + if (value === ',') { + let output = value; -var fs = __nccwpck_require__(9896) + const brace = braces[braces.length - 1]; + if (brace && stack[stack.length - 1] === 'braces') { + brace.comma = true; + output = '|'; + } -function isexe (path, options, cb) { - fs.stat(path, function (er, stat) { - cb(er, er ? false : checkStat(stat, options)) - }) -} + push({ type: 'comma', value, output }); + continue; + } -function sync (path, options) { - return checkStat(fs.statSync(path), options) -} + /** + * Slashes + */ -function checkStat (stat, options) { - return stat.isFile() && checkMode(stat, options) -} + if (value === '/') { + // if the beginning of the glob is "./", advance the start + // to the current index, and don't add the "./" characters + // to the state. This greatly simplifies lookbehinds when + // checking for BOS characters like "!" and "." (not "./") + if (prev.type === 'dot' && state.index === state.start + 1) { + state.start = state.index + 1; + state.consumed = ''; + state.output = ''; + tokens.pop(); + prev = bos; // reset "prev" to the first token + continue; + } -function checkMode (stat, options) { - var mod = stat.mode - var uid = stat.uid - var gid = stat.gid + push({ type: 'slash', value, output: SLASH_LITERAL }); + continue; + } - var myUid = options.uid !== undefined ? - options.uid : process.getuid && process.getuid() - var myGid = options.gid !== undefined ? - options.gid : process.getgid && process.getgid() + /** + * Dots + */ - var u = parseInt('100', 8) - var g = parseInt('010', 8) - var o = parseInt('001', 8) - var ug = u | g + if (value === '.') { + if (state.braces > 0 && prev.type === 'dot') { + if (prev.value === '.') prev.output = DOT_LITERAL; + const brace = braces[braces.length - 1]; + prev.type = 'dots'; + prev.output += value; + prev.value += value; + brace.dots = true; + continue; + } - var ret = (mod & o) || - (mod & g) && gid === myGid || - (mod & u) && uid === myUid || - (mod & ug) && myUid === 0 + if ((state.braces + state.parens) === 0 && prev.type !== 'bos' && prev.type !== 'slash') { + push({ type: 'text', value, output: DOT_LITERAL }); + continue; + } - return ret -} + push({ type: 'dot', value, output: DOT_LITERAL }); + continue; + } + /** + * Question marks + */ -/***/ }), + if (value === '?') { + const isGroup = prev && prev.value === '('; + if (!isGroup && opts.noextglob !== true && peek() === '(' && peek(2) !== '?') { + extglobOpen('qmark', value); + continue; + } -/***/ 5680: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + if (prev && prev.type === 'paren') { + const next = peek(); + let output = value; -module.exports = isexe -isexe.sync = sync + if (next === '<' && !utils.supportsLookbehinds()) { + throw new Error('Node.js v10 or higher is required for regex lookbehinds'); + } -var fs = __nccwpck_require__(9896) + if ((prev.value === '(' && !/[!=<:]/.test(next)) || (next === '<' && !/<([!=]|\w+>)/.test(remaining()))) { + output = `\\${value}`; + } -function checkPathExt (path, options) { - var pathext = options.pathExt !== undefined ? - options.pathExt : process.env.PATHEXT + push({ type: 'text', value, output }); + continue; + } - if (!pathext) { - return true - } + if (opts.dot !== true && (prev.type === 'slash' || prev.type === 'bos')) { + push({ type: 'qmark', value, output: QMARK_NO_DOT }); + continue; + } - pathext = pathext.split(';') - if (pathext.indexOf('') !== -1) { - return true - } - for (var i = 0; i < pathext.length; i++) { - var p = pathext[i].toLowerCase() - if (p && path.substr(-p.length).toLowerCase() === p) { - return true + push({ type: 'qmark', value, output: QMARK }); + continue; } - } - return false -} -function checkStat (stat, path, options) { - if (!stat.isSymbolicLink() && !stat.isFile()) { - return false - } - return checkPathExt(path, options) -} - -function isexe (path, options, cb) { - fs.stat(path, function (er, stat) { - cb(er, er ? false : checkStat(stat, path, options)) - }) -} + /** + * Exclamation + */ -function sync (path, options) { - return checkStat(fs.statSync(path), path, options) -} + if (value === '!') { + if (opts.noextglob !== true && peek() === '(') { + if (peek(2) !== '?' || !/[!=<:]/.test(peek(3))) { + extglobOpen('negate', value); + continue; + } + } + if (opts.nonegate !== true && state.index === 0) { + negate(); + continue; + } + } -/***/ }), + /** + * Plus + */ -/***/ 9235: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + if (value === '+') { + if (opts.noextglob !== true && peek() === '(' && peek(2) !== '?') { + extglobOpen('plus', value); + continue; + } -"use strict"; + if ((prev && prev.value === '(') || opts.regex === false) { + push({ type: 'plus', value, output: PLUS_LITERAL }); + continue; + } + if ((prev && (prev.type === 'bracket' || prev.type === 'paren' || prev.type === 'brace')) || state.parens > 0) { + push({ type: 'plus', value }); + continue; + } -const { PassThrough } = __nccwpck_require__(2203); + push({ type: 'plus', value: PLUS_LITERAL }); + continue; + } -module.exports = function (/*streams...*/) { - var sources = [] - var output = new PassThrough({objectMode: true}) + /** + * Plain text + */ - output.setMaxListeners(0) + if (value === '@') { + if (opts.noextglob !== true && peek() === '(' && peek(2) !== '?') { + push({ type: 'at', extglob: true, value, output: '' }); + continue; + } - output.add = add - output.isEmpty = isEmpty + push({ type: 'text', value }); + continue; + } - output.on('unpipe', remove) + /** + * Plain text + */ - Array.prototype.slice.call(arguments).forEach(add) + if (value !== '*') { + if (value === '$' || value === '^') { + value = `\\${value}`; + } - return output + const match = REGEX_NON_SPECIAL_CHARS.exec(remaining()); + if (match) { + value += match[0]; + state.index += match[0].length; + } - function add (source) { - if (Array.isArray(source)) { - source.forEach(add) - return this + push({ type: 'text', value }); + continue; } - sources.push(source); - source.once('end', remove.bind(null, source)) - source.once('error', output.emit.bind(output, 'error')) - source.pipe(output, {end: false}) - return this - } - - function isEmpty () { - return sources.length == 0; - } + /** + * Stars + */ - function remove (source) { - sources = sources.filter(function (it) { return it !== source }) - if (!sources.length && output.readable) { output.end() } - } -} + if (prev && (prev.type === 'globstar' || prev.star === true)) { + prev.type = 'star'; + prev.star = true; + prev.value += value; + prev.output = star; + state.backtrack = true; + state.globstar = true; + consume(value); + continue; + } + let rest = remaining(); + if (opts.noextglob !== true && /^\([^?]/.test(rest)) { + extglobOpen('star', value); + continue; + } -/***/ }), + if (prev.type === 'star') { + if (opts.noglobstar === true) { + consume(value); + continue; + } -/***/ 5775: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + const prior = prev.prev; + const before = prior.prev; + const isStart = prior.type === 'slash' || prior.type === 'bos'; + const afterStar = before && (before.type === 'star' || before.type === 'globstar'); -"use strict"; + if (opts.bash === true && (!isStart || (rest[0] && rest[0] !== '/'))) { + push({ type: 'star', value, output: '' }); + continue; + } -/* - * merge2 - * https://github.com/teambition/merge2 - * - * Copyright (c) 2014-2020 Teambition - * Licensed under the MIT license. - */ -const Stream = __nccwpck_require__(2203) -const PassThrough = Stream.PassThrough -const slice = Array.prototype.slice + const isBrace = state.braces > 0 && (prior.type === 'comma' || prior.type === 'brace'); + const isExtglob = extglobs.length && (prior.type === 'pipe' || prior.type === 'paren'); + if (!isStart && prior.type !== 'paren' && !isBrace && !isExtglob) { + push({ type: 'star', value, output: '' }); + continue; + } -module.exports = merge2 + // strip consecutive `/**/` + while (rest.slice(0, 3) === '/**') { + const after = input[state.index + 4]; + if (after && after !== '/') { + break; + } + rest = rest.slice(3); + consume('/**', 3); + } -function merge2 () { - const streamsQueue = [] - const args = slice.call(arguments) - let merging = false - let options = args[args.length - 1] + if (prior.type === 'bos' && eos()) { + prev.type = 'globstar'; + prev.value += value; + prev.output = globstar(opts); + state.output = prev.output; + state.globstar = true; + consume(value); + continue; + } - if (options && !Array.isArray(options) && options.pipe == null) { - args.pop() - } else { - options = {} - } + if (prior.type === 'slash' && prior.prev.type !== 'bos' && !afterStar && eos()) { + state.output = state.output.slice(0, -(prior.output + prev.output).length); + prior.output = `(?:${prior.output}`; - const doEnd = options.end !== false - const doPipeError = options.pipeError === true - if (options.objectMode == null) { - options.objectMode = true - } - if (options.highWaterMark == null) { - options.highWaterMark = 64 * 1024 - } - const mergedStream = PassThrough(options) + prev.type = 'globstar'; + prev.output = globstar(opts) + (opts.strictSlashes ? ')' : '|$)'); + prev.value += value; + state.globstar = true; + state.output += prior.output + prev.output; + consume(value); + continue; + } - function addStream () { - for (let i = 0, len = arguments.length; i < len; i++) { - streamsQueue.push(pauseStreams(arguments[i], options)) - } - mergeStream() - return this - } + if (prior.type === 'slash' && prior.prev.type !== 'bos' && rest[0] === '/') { + const end = rest[1] !== void 0 ? '|$' : ''; - function mergeStream () { - if (merging) { - return - } - merging = true + state.output = state.output.slice(0, -(prior.output + prev.output).length); + prior.output = `(?:${prior.output}`; - let streams = streamsQueue.shift() - if (!streams) { - process.nextTick(endStream) - return - } - if (!Array.isArray(streams)) { - streams = [streams] - } + prev.type = 'globstar'; + prev.output = `${globstar(opts)}${SLASH_LITERAL}|${SLASH_LITERAL}${end})`; + prev.value += value; - let pipesCount = streams.length + 1 + state.output += prior.output + prev.output; + state.globstar = true; - function next () { - if (--pipesCount > 0) { - return - } - merging = false - mergeStream() - } + consume(value + advance()); - function pipe (stream) { - function onend () { - stream.removeListener('merge2UnpipeEnd', onend) - stream.removeListener('end', onend) - if (doPipeError) { - stream.removeListener('error', onerror) - } - next() - } - function onerror (err) { - mergedStream.emit('error', err) + push({ type: 'slash', value: '/', output: '' }); + continue; } - // skip ended stream - if (stream._readableState.endEmitted) { - return next() + + if (prior.type === 'bos' && rest[0] === '/') { + prev.type = 'globstar'; + prev.value += value; + prev.output = `(?:^|${SLASH_LITERAL}|${globstar(opts)}${SLASH_LITERAL})`; + state.output = prev.output; + state.globstar = true; + consume(value + advance()); + push({ type: 'slash', value: '/', output: '' }); + continue; } - stream.on('merge2UnpipeEnd', onend) - stream.on('end', onend) + // remove single star from output + state.output = state.output.slice(0, -prev.output.length); - if (doPipeError) { - stream.on('error', onerror) - } + // reset previous token to globstar + prev.type = 'globstar'; + prev.output = globstar(opts); + prev.value += value; - stream.pipe(mergedStream, { end: false }) - // compatible for old stream - stream.resume() + // reset output with globstar + state.output += prev.output; + state.globstar = true; + consume(value); + continue; } - for (let i = 0; i < streams.length; i++) { - pipe(streams[i]) - } + const token = { type: 'star', value, output: star }; - next() - } + if (opts.bash === true) { + token.output = '.*?'; + if (prev.type === 'bos' || prev.type === 'slash') { + token.output = nodot + token.output; + } + push(token); + continue; + } - function endStream () { - merging = false - // emit 'queueDrain' when all streams merged. - mergedStream.emit('queueDrain') - if (doEnd) { - mergedStream.end() + if (prev && (prev.type === 'bracket' || prev.type === 'paren') && opts.regex === true) { + token.output = value; + push(token); + continue; } - } - mergedStream.setMaxListeners(0) - mergedStream.add = addStream - mergedStream.on('unpipe', function (stream) { - stream.emit('merge2UnpipeEnd') - }) + if (state.index === state.start || prev.type === 'slash' || prev.type === 'dot') { + if (prev.type === 'dot') { + state.output += NO_DOT_SLASH; + prev.output += NO_DOT_SLASH; - if (args.length) { - addStream.apply(null, args) - } - return mergedStream -} + } else if (opts.dot === true) { + state.output += NO_DOTS_SLASH; + prev.output += NO_DOTS_SLASH; -// check and pause streams for pipe. -function pauseStreams (streams, options) { - if (!Array.isArray(streams)) { - // Backwards-compat with old-style streams - if (!streams._readableState && streams.pipe) { - streams = streams.pipe(PassThrough(options)) - } - if (!streams._readableState || !streams.pause || !streams.pipe) { - throw new Error('Only readable stream can be merged.') - } - streams.pause() - } else { - for (let i = 0, len = streams.length; i < len; i++) { - streams[i] = pauseStreams(streams[i], options) + } else { + state.output += nodot; + prev.output += nodot; + } + + if (peek() !== '*') { + state.output += ONE_CHAR; + prev.output += ONE_CHAR; + } } + + push(token); + } + + while (state.brackets > 0) { + if (opts.strictBrackets === true) throw new SyntaxError(syntaxError('closing', ']')); + state.output = utils.escapeLast(state.output, '['); + decrement('brackets'); } - return streams -} + while (state.parens > 0) { + if (opts.strictBrackets === true) throw new SyntaxError(syntaxError('closing', ')')); + state.output = utils.escapeLast(state.output, '('); + decrement('parens'); + } -/***/ }), + while (state.braces > 0) { + if (opts.strictBrackets === true) throw new SyntaxError(syntaxError('closing', '}')); + state.output = utils.escapeLast(state.output, '{'); + decrement('braces'); + } -/***/ 4839: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + if (opts.strictSlashes !== true && (prev.type === 'star' || prev.type === 'bracket')) { + push({ type: 'maybe_slash', value: '', output: `${SLASH_LITERAL}?` }); + } -"use strict"; + // rebuild the output if we had to backtrack at any point + if (state.backtrack === true) { + state.output = ''; + for (const token of state.tokens) { + state.output += token.output != null ? token.output : token.value; -const util = __nccwpck_require__(9023); -const braces = __nccwpck_require__(727); -const picomatch = __nccwpck_require__(1689); -const utils = __nccwpck_require__(9116); + if (token.suffix) { + state.output += token.suffix; + } + } + } -const isEmptyString = v => v === '' || v === './'; -const hasBraces = v => { - const index = v.indexOf('{'); - return index > -1 && v.indexOf('}', index) > -1; + return state; }; /** - * Returns an array of strings that match one or more glob patterns. - * - * ```js - * const mm = require('micromatch'); - * // mm(list, patterns[, options]); - * - * console.log(mm(['a.js', 'a.txt'], ['*.js'])); - * //=> [ 'a.js' ] - * ``` - * @param {String|Array} `list` List of strings to match. - * @param {String|Array} `patterns` One or more glob patterns to use for matching. - * @param {Object} `options` See available [options](#options) - * @return {Array} Returns an array of matches - * @summary false - * @api public + * Fast paths for creating regular expressions for common glob patterns. + * This can significantly speed up processing and has very little downside + * impact when none of the fast paths match. */ -const micromatch = (list, patterns, options) => { - patterns = [].concat(patterns); - list = [].concat(list); +parse.fastpaths = (input, options) => { + const opts = { ...options }; + const max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH; + const len = input.length; + if (len > max) { + throw new SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`); + } - let omit = new Set(); - let keep = new Set(); - let items = new Set(); - let negatives = 0; + input = REPLACEMENTS[input] || input; + const win32 = utils.isWindows(options); - let onResult = state => { - items.add(state.output); - if (options && options.onResult) { - options.onResult(state); - } + // create constants based on platform, for windows or posix + const { + DOT_LITERAL, + SLASH_LITERAL, + ONE_CHAR, + DOTS_SLASH, + NO_DOT, + NO_DOTS, + NO_DOTS_SLASH, + STAR, + START_ANCHOR + } = constants.globChars(win32); + + const nodot = opts.dot ? NO_DOTS : NO_DOT; + const slashDot = opts.dot ? NO_DOTS_SLASH : NO_DOT; + const capture = opts.capture ? '' : '?:'; + const state = { negated: false, prefix: '' }; + let star = opts.bash === true ? '.*?' : STAR; + + if (opts.capture) { + star = `(${star})`; + } + + const globstar = opts => { + if (opts.noglobstar === true) return star; + return `(${capture}(?:(?!${START_ANCHOR}${opts.dot ? DOTS_SLASH : DOT_LITERAL}).)*?)`; }; - for (let i = 0; i < patterns.length; i++) { - let isMatch = picomatch(String(patterns[i]), { ...options, onResult }, true); - let negated = isMatch.state.negated || isMatch.state.negatedExtglob; - if (negated) negatives++; + const create = str => { + switch (str) { + case '*': + return `${nodot}${ONE_CHAR}${star}`; - for (let item of list) { - let matched = isMatch(item, true); + case '.*': + return `${DOT_LITERAL}${ONE_CHAR}${star}`; - let match = negated ? !matched.isMatch : matched.isMatch; - if (!match) continue; + case '*.*': + return `${nodot}${star}${DOT_LITERAL}${ONE_CHAR}${star}`; - if (negated) { - omit.add(matched.output); - } else { - omit.delete(matched.output); - keep.add(matched.output); - } - } - } + case '*/*': + return `${nodot}${star}${SLASH_LITERAL}${ONE_CHAR}${slashDot}${star}`; - let result = negatives === patterns.length ? [...items] : [...keep]; - let matches = result.filter(item => !omit.has(item)); + case '**': + return nodot + globstar(opts); - if (options && matches.length === 0) { - if (options.failglob === true) { - throw new Error(`No matches found for "${patterns.join(', ')}"`); - } + case '**/*': + return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${slashDot}${ONE_CHAR}${star}`; - if (options.nonull === true || options.nullglob === true) { - return options.unescape ? patterns.map(p => p.replace(/\\/g, '')) : patterns; + case '**/*.*': + return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${slashDot}${star}${DOT_LITERAL}${ONE_CHAR}${star}`; + + case '**/.*': + return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${DOT_LITERAL}${ONE_CHAR}${star}`; + + default: { + const match = /^(.*?)\.(\w+)$/.exec(str); + if (!match) return; + + const source = create(match[1]); + if (!source) return; + + return source + DOT_LITERAL + match[2]; + } } + }; + + const output = utils.removePrefix(input, state); + let source = create(output); + + if (source && opts.strictSlashes !== true) { + source += `${SLASH_LITERAL}?`; } - return matches; + return source; }; -/** - * Backwards compatibility - */ - -micromatch.match = micromatch; +module.exports = parse; -/** - * Returns a matcher function from the given glob `pattern` and `options`. - * The returned function takes a string to match as its only argument and returns - * true if the string is a match. - * - * ```js - * const mm = require('micromatch'); - * // mm.matcher(pattern[, options]); - * - * const isMatch = mm.matcher('*.!(*a)'); - * console.log(isMatch('a.a')); //=> false - * console.log(isMatch('a.b')); //=> true - * ``` - * @param {String} `pattern` Glob pattern - * @param {Object} `options` - * @return {Function} Returns a matcher function. - * @api public - */ -micromatch.matcher = (pattern, options) => picomatch(pattern, options); +/***/ }), -/** - * Returns true if **any** of the given glob `patterns` match the specified `string`. - * - * ```js - * const mm = require('micromatch'); - * // mm.isMatch(string, patterns[, options]); - * - * console.log(mm.isMatch('a.a', ['b.*', '*.a'])); //=> true - * console.log(mm.isMatch('a.a', 'b.*')); //=> false - * ``` - * @param {String} `str` The string to test. - * @param {String|Array} `patterns` One or more glob patterns to use for matching. - * @param {Object} `[options]` See available [options](#options). - * @return {Boolean} Returns true if any patterns match `str` - * @api public - */ +/***/ 3848: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -micromatch.isMatch = (str, patterns, options) => picomatch(patterns, options)(str); -/** - * Backwards compatibility - */ -micromatch.any = micromatch.isMatch; +const path = __nccwpck_require__(6928); +const scan = __nccwpck_require__(5277); +const parse = __nccwpck_require__(9153); +const utils = __nccwpck_require__(7379); +const constants = __nccwpck_require__(435); +const isObject = val => val && typeof val === 'object' && !Array.isArray(val); /** - * Returns a list of strings that _**do not match any**_ of the given `patterns`. + * Creates a matcher function from one or more glob patterns. The + * returned function takes a string to match as its first argument, + * and returns true if the string is a match. The returned matcher + * function also takes a boolean as the second argument that, when true, + * returns an object with additional information. * * ```js - * const mm = require('micromatch'); - * // mm.not(list, patterns[, options]); + * const picomatch = require('picomatch'); + * // picomatch(glob[, options]); * - * console.log(mm.not(['a.a', 'b.b', 'c.c'], '*.a')); - * //=> ['b.b', 'c.c'] + * const isMatch = picomatch('*.!(*a)'); + * console.log(isMatch('a.a')); //=> false + * console.log(isMatch('a.b')); //=> true * ``` - * @param {Array} `list` Array of strings to match. - * @param {String|Array} `patterns` One or more glob pattern to use for matching. - * @param {Object} `options` See available [options](#options) for changing how matches are performed - * @return {Array} Returns an array of strings that **do not match** the given patterns. + * @name picomatch + * @param {String|Array} `globs` One or more glob patterns. + * @param {Object=} `options` + * @return {Function=} Returns a matcher function. * @api public */ -micromatch.not = (list, patterns, options = {}) => { - patterns = [].concat(patterns).map(String); - let result = new Set(); - let items = []; - - let onResult = state => { - if (options.onResult) options.onResult(state); - items.push(state.output); - }; +const picomatch = (glob, options, returnState = false) => { + if (Array.isArray(glob)) { + const fns = glob.map(input => picomatch(input, options, returnState)); + const arrayMatcher = str => { + for (const isMatch of fns) { + const state = isMatch(str); + if (state) return state; + } + return false; + }; + return arrayMatcher; + } - let matches = new Set(micromatch(list, patterns, { ...options, onResult })); + const isState = isObject(glob) && glob.tokens && glob.input; - for (let item of items) { - if (!matches.has(item)) { - result.add(item); - } + if (glob === '' || (typeof glob !== 'string' && !isState)) { + throw new TypeError('Expected pattern to be a non-empty string'); } - return [...result]; -}; -/** - * Returns true if the given `string` contains the given pattern. Similar - * to [.isMatch](#isMatch) but the pattern can match any part of the string. - * - * ```js - * var mm = require('micromatch'); - * // mm.contains(string, pattern[, options]); - * - * console.log(mm.contains('aa/bb/cc', '*b')); - * //=> true - * console.log(mm.contains('aa/bb/cc', '*d')); - * //=> false - * ``` - * @param {String} `str` The string to match. - * @param {String|Array} `patterns` Glob pattern to use for matching. - * @param {Object} `options` See available [options](#options) for changing how matches are performed - * @return {Boolean} Returns true if any of the patterns matches any part of `str`. - * @api public - */ + const opts = options || {}; + const posix = utils.isWindows(options); + const regex = isState + ? picomatch.compileRe(glob, options) + : picomatch.makeRe(glob, options, false, true); -micromatch.contains = (str, pattern, options) => { - if (typeof str !== 'string') { - throw new TypeError(`Expected a string: "${util.inspect(str)}"`); - } + const state = regex.state; + delete regex.state; - if (Array.isArray(pattern)) { - return pattern.some(p => micromatch.contains(str, p, options)); + let isIgnored = () => false; + if (opts.ignore) { + const ignoreOpts = { ...options, ignore: null, onMatch: null, onResult: null }; + isIgnored = picomatch(opts.ignore, ignoreOpts, returnState); } - if (typeof pattern === 'string') { - if (isEmptyString(str) || isEmptyString(pattern)) { - return false; + const matcher = (input, returnObject = false) => { + const { isMatch, match, output } = picomatch.test(input, regex, options, { glob, posix }); + const result = { glob, state, regex, posix, input, output, match, isMatch }; + + if (typeof opts.onResult === 'function') { + opts.onResult(result); } - if (str.includes(pattern) || (str.startsWith('./') && str.slice(2).includes(pattern))) { - return true; + if (isMatch === false) { + result.isMatch = false; + return returnObject ? result : false; + } + + if (isIgnored(input)) { + if (typeof opts.onIgnore === 'function') { + opts.onIgnore(result); + } + result.isMatch = false; + return returnObject ? result : false; + } + + if (typeof opts.onMatch === 'function') { + opts.onMatch(result); } + return returnObject ? result : true; + }; + + if (returnState) { + matcher.state = state; } - return micromatch.isMatch(str, pattern, { ...options, contains: true }); + return matcher; }; /** - * Filter the keys of the given object with the given `glob` pattern - * and `options`. Does not attempt to match nested keys. If you need this feature, - * use [glob-object][] instead. + * Test `input` with the given `regex`. This is used by the main + * `picomatch()` function to test the input string. * * ```js - * const mm = require('micromatch'); - * // mm.matchKeys(object, patterns[, options]); + * const picomatch = require('picomatch'); + * // picomatch.test(input, regex[, options]); * - * const obj = { aa: 'a', ab: 'b', ac: 'c' }; - * console.log(mm.matchKeys(obj, '*b')); - * //=> { ab: 'b' } + * console.log(picomatch.test('foo/bar', /^(?:([^/]*?)\/([^/]*?))$/)); + * // { isMatch: true, match: [ 'foo/', 'foo', 'bar' ], output: 'foo/bar' } * ``` - * @param {Object} `object` The object with keys to filter. - * @param {String|Array} `patterns` One or more glob patterns to use for matching. - * @param {Object} `options` See available [options](#options) for changing how matches are performed - * @return {Object} Returns an object with only keys that match the given patterns. + * @param {String} `input` String to test. + * @param {RegExp} `regex` + * @return {Object} Returns an object with matching info. * @api public */ -micromatch.matchKeys = (obj, patterns, options) => { - if (!utils.isObject(obj)) { - throw new TypeError('Expected the first argument to be an object'); +picomatch.test = (input, regex, options, { glob, posix } = {}) => { + if (typeof input !== 'string') { + throw new TypeError('Expected input to be a string'); } - let keys = micromatch(Object.keys(obj), patterns, options); - let res = {}; - for (let key of keys) res[key] = obj[key]; - return res; -}; -/** - * Returns true if some of the strings in the given `list` match any of the given glob `patterns`. - * - * ```js - * const mm = require('micromatch'); - * // mm.some(list, patterns[, options]); - * - * console.log(mm.some(['foo.js', 'bar.js'], ['*.js', '!foo.js'])); - * // true - * console.log(mm.some(['foo.js'], ['*.js', '!foo.js'])); - * // false - * ``` - * @param {String|Array} `list` The string or array of strings to test. Returns as soon as the first match is found. - * @param {String|Array} `patterns` One or more glob patterns to use for matching. - * @param {Object} `options` See available [options](#options) for changing how matches are performed - * @return {Boolean} Returns true if any `patterns` matches any of the strings in `list` - * @api public - */ + if (input === '') { + return { isMatch: false, output: '' }; + } -micromatch.some = (list, patterns, options) => { - let items = [].concat(list); + const opts = options || {}; + const format = opts.format || (posix ? utils.toPosixSlashes : null); + let match = input === glob; + let output = (match && format) ? format(input) : input; - for (let pattern of [].concat(patterns)) { - let isMatch = picomatch(String(pattern), options); - if (items.some(item => isMatch(item))) { - return true; + if (match === false) { + output = format ? format(input) : input; + match = output === glob; + } + + if (match === false || opts.capture === true) { + if (opts.matchBase === true || opts.basename === true) { + match = picomatch.matchBase(input, regex, options, posix); + } else { + match = regex.exec(output); } } - return false; + + return { isMatch: Boolean(match), match, output }; }; /** - * Returns true if every string in the given `list` matches - * any of the given glob `patterns`. + * Match the basename of a filepath. * * ```js - * const mm = require('micromatch'); - * // mm.every(list, patterns[, options]); - * - * console.log(mm.every('foo.js', ['foo.js'])); - * // true - * console.log(mm.every(['foo.js', 'bar.js'], ['*.js'])); - * // true - * console.log(mm.every(['foo.js', 'bar.js'], ['*.js', '!foo.js'])); - * // false - * console.log(mm.every(['foo.js'], ['*.js', '!foo.js'])); - * // false + * const picomatch = require('picomatch'); + * // picomatch.matchBase(input, glob[, options]); + * console.log(picomatch.matchBase('foo/bar.js', '*.js'); // true * ``` - * @param {String|Array} `list` The string or array of strings to test. - * @param {String|Array} `patterns` One or more glob patterns to use for matching. - * @param {Object} `options` See available [options](#options) for changing how matches are performed - * @return {Boolean} Returns true if all `patterns` matches all of the strings in `list` + * @param {String} `input` String to test. + * @param {RegExp|String} `glob` Glob pattern or regex created by [.makeRe](#makeRe). + * @return {Boolean} * @api public */ -micromatch.every = (list, patterns, options) => { - let items = [].concat(list); - - for (let pattern of [].concat(patterns)) { - let isMatch = picomatch(String(pattern), options); - if (!items.every(item => isMatch(item))) { - return false; - } - } - return true; +picomatch.matchBase = (input, glob, options, posix = utils.isWindows(options)) => { + const regex = glob instanceof RegExp ? glob : picomatch.makeRe(glob, options); + return regex.test(path.basename(input)); }; /** - * Returns true if **all** of the given `patterns` match - * the specified string. + * Returns true if **any** of the given glob `patterns` match the specified `string`. * * ```js - * const mm = require('micromatch'); - * // mm.all(string, patterns[, options]); - * - * console.log(mm.all('foo.js', ['foo.js'])); - * // true - * - * console.log(mm.all('foo.js', ['*.js', '!foo.js'])); - * // false - * - * console.log(mm.all('foo.js', ['*.js', 'foo.js'])); - * // true + * const picomatch = require('picomatch'); + * // picomatch.isMatch(string, patterns[, options]); * - * console.log(mm.all('foo.js', ['*.js', 'f*', '*o*', '*o.js'])); - * // true + * console.log(picomatch.isMatch('a.a', ['b.*', '*.a'])); //=> true + * console.log(picomatch.isMatch('a.a', 'b.*')); //=> false * ``` - * @param {String|Array} `str` The string to test. - * @param {String|Array} `patterns` One or more glob patterns to use for matching. - * @param {Object} `options` See available [options](#options) for changing how matches are performed + * @param {String|Array} str The string to test. + * @param {String|Array} patterns One or more glob patterns to use for matching. + * @param {Object} [options] See available [options](#options). * @return {Boolean} Returns true if any patterns match `str` * @api public */ -micromatch.all = (str, patterns, options) => { - if (typeof str !== 'string') { - throw new TypeError(`Expected a string: "${util.inspect(str)}"`); - } - - return [].concat(patterns).every(p => picomatch(p, options)(str)); -}; +picomatch.isMatch = (str, patterns, options) => picomatch(patterns, options)(str); /** - * Returns an array of matches captured by `pattern` in `string, or `null` if the pattern did not match. + * Parse a glob pattern to create the source string for a regular + * expression. * * ```js - * const mm = require('micromatch'); - * // mm.capture(pattern, string[, options]); - * - * console.log(mm.capture('test/*.js', 'test/foo.js')); - * //=> ['foo'] - * console.log(mm.capture('test/*.js', 'foo/bar.css')); - * //=> null + * const picomatch = require('picomatch'); + * const result = picomatch.parse(pattern[, options]); * ``` - * @param {String} `glob` Glob pattern to use for matching. - * @param {String} `input` String to match - * @param {Object} `options` See available [options](#options) for changing how matches are performed - * @return {Array|null} Returns an array of captures if the input matches the glob pattern, otherwise `null`. + * @param {String} `pattern` + * @param {Object} `options` + * @return {Object} Returns an object with useful properties and output to be used as a regex source string. * @api public */ -micromatch.capture = (glob, input, options) => { - let posix = utils.isWindows(options); - let regex = picomatch.makeRe(String(glob), { ...options, capture: true }); - let match = regex.exec(posix ? utils.toPosixSlashes(input) : input); - - if (match) { - return match.slice(1).map(v => v === void 0 ? '' : v); - } +picomatch.parse = (pattern, options) => { + if (Array.isArray(pattern)) return pattern.map(p => picomatch.parse(p, options)); + return parse(pattern, { ...options, fastpaths: false }); }; /** - * Create a regular expression from the given glob `pattern`. + * Scan a glob pattern to separate the pattern into segments. * * ```js - * const mm = require('micromatch'); - * // mm.makeRe(pattern[, options]); + * const picomatch = require('picomatch'); + * // picomatch.scan(input[, options]); * - * console.log(mm.makeRe('*.js')); - * //=> /^(?:(\.[\\\/])?(?!\.)(?=.)[^\/]*?\.js)$/ + * const result = picomatch.scan('!./foo/*.js'); + * console.log(result); + * { prefix: '!./', + * input: '!./foo/*.js', + * start: 3, + * base: 'foo', + * glob: '*.js', + * isBrace: false, + * isBracket: false, + * isGlob: true, + * isExtglob: false, + * isGlobstar: false, + * negated: true } * ``` - * @param {String} `pattern` A glob pattern to convert to regex. + * @param {String} `input` Glob pattern to scan. * @param {Object} `options` - * @return {RegExp} Returns a regex created from the given pattern. + * @return {Object} Returns an object with * @api public */ -micromatch.makeRe = (...args) => picomatch.makeRe(...args); +picomatch.scan = (input, options) => scan(input, options); /** - * Scan a glob pattern to separate the pattern into segments. Used - * by the [split](#split) method. + * Compile a regular expression from the `state` object returned by the + * [parse()](#parse) method. * - * ```js - * const mm = require('micromatch'); - * const state = mm.scan(pattern[, options]); - * ``` - * @param {String} `pattern` + * @param {Object} `state` * @param {Object} `options` - * @return {Object} Returns an object with + * @param {Boolean} `returnOutput` Intended for implementors, this argument allows you to return the raw output from the parser. + * @param {Boolean} `returnState` Adds the state to a `state` property on the returned regex. Useful for implementors and debugging. + * @return {RegExp} * @api public */ -micromatch.scan = (...args) => picomatch.scan(...args); +picomatch.compileRe = (state, options, returnOutput = false, returnState = false) => { + if (returnOutput === true) { + return state.output; + } + + const opts = options || {}; + const prepend = opts.contains ? '' : '^'; + const append = opts.contains ? '' : '$'; + + let source = `${prepend}(?:${state.output})${append}`; + if (state && state.negated === true) { + source = `^(?!${source}).*$`; + } + + const regex = picomatch.toRegex(source, options); + if (returnState === true) { + regex.state = state; + } + + return regex; +}; /** - * Parse a glob pattern to create the source string for a regular - * expression. + * Create a regular expression from a parsed glob pattern. * * ```js - * const mm = require('micromatch'); - * const state = mm.parse(pattern[, options]); + * const picomatch = require('picomatch'); + * const state = picomatch.parse('*.js'); + * // picomatch.compileRe(state[, options]); + * + * console.log(picomatch.compileRe(state)); + * //=> /^(?:(?!\.)(?=.)[^/]*?\.js)$/ * ``` - * @param {String} `glob` + * @param {String} `state` The object returned from the `.parse` method. * @param {Object} `options` - * @return {Object} Returns an object with useful properties and output to be used as regex source string. + * @param {Boolean} `returnOutput` Implementors may use this argument to return the compiled output, instead of a regular expression. This is not exposed on the options to prevent end-users from mutating the result. + * @param {Boolean} `returnState` Implementors may use this argument to return the state from the parsed glob with the returned regular expression. + * @return {RegExp} Returns a regex created from the given pattern. * @api public */ -micromatch.parse = (patterns, options) => { - let res = []; - for (let pattern of [].concat(patterns || [])) { - for (let str of braces(String(pattern), options)) { - res.push(picomatch.parse(str, options)); - } +picomatch.makeRe = (input, options = {}, returnOutput = false, returnState = false) => { + if (!input || typeof input !== 'string') { + throw new TypeError('Expected a non-empty string'); } - return res; + + let parsed = { negated: false, fastpaths: true }; + + if (options.fastpaths !== false && (input[0] === '.' || input[0] === '*')) { + parsed.output = parse.fastpaths(input, options); + } + + if (!parsed.output) { + parsed = parse(input, options); + } + + return picomatch.compileRe(parsed, options, returnOutput, returnState); }; /** - * Process the given brace `pattern`. + * Create a regular expression from the given regex source string. * * ```js - * const { braces } = require('micromatch'); - * console.log(braces('foo/{a,b,c}/bar')); - * //=> [ 'foo/(a|b|c)/bar' ] + * const picomatch = require('picomatch'); + * // picomatch.toRegex(source[, options]); * - * console.log(braces('foo/{a,b,c}/bar', { expand: true })); - * //=> [ 'foo/a/bar', 'foo/b/bar', 'foo/c/bar' ] + * const { output } = picomatch.parse('*.js'); + * console.log(picomatch.toRegex(output)); + * //=> /^(?:(?!\.)(?=.)[^/]*?\.js)$/ * ``` - * @param {String} `pattern` String with brace pattern to process. - * @param {Object} `options` Any [options](#options) to change how expansion is performed. See the [braces][] library for all available options. - * @return {Array} + * @param {String} `source` Regular expression source string. + * @param {Object} `options` + * @return {RegExp} * @api public */ -micromatch.braces = (pattern, options) => { - if (typeof pattern !== 'string') throw new TypeError('Expected a string'); - if ((options && options.nobrace === true) || !hasBraces(pattern)) { - return [pattern]; +picomatch.toRegex = (source, options) => { + try { + const opts = options || {}; + return new RegExp(source, opts.flags || (opts.nocase ? 'i' : '')); + } catch (err) { + if (options && options.debug === true) throw err; + return /$^/; } - return braces(pattern, options); }; /** - * Expand braces + * Picomatch constants. + * @return {Object} */ -micromatch.braceExpand = (pattern, options) => { - if (typeof pattern !== 'string') throw new TypeError('Expected a string'); - return micromatch.braces(pattern, { ...options, expand: true }); -}; +picomatch.constants = constants; /** - * Expose micromatch + * Expose "picomatch" */ -// exposed for tests -micromatch.hasBraces = hasBraces; -module.exports = micromatch; +module.exports = picomatch; /***/ }), -/***/ 1881: -/***/ ((module) => { +/***/ 5277: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -const mimicFn = (to, from) => { - for (const prop of Reflect.ownKeys(from)) { - Object.defineProperty(to, prop, Object.getOwnPropertyDescriptor(from, prop)); - } +const utils = __nccwpck_require__(7379); +const { + CHAR_ASTERISK, /* * */ + CHAR_AT, /* @ */ + CHAR_BACKWARD_SLASH, /* \ */ + CHAR_COMMA, /* , */ + CHAR_DOT, /* . */ + CHAR_EXCLAMATION_MARK, /* ! */ + CHAR_FORWARD_SLASH, /* / */ + CHAR_LEFT_CURLY_BRACE, /* { */ + CHAR_LEFT_PARENTHESES, /* ( */ + CHAR_LEFT_SQUARE_BRACKET, /* [ */ + CHAR_PLUS, /* + */ + CHAR_QUESTION_MARK, /* ? */ + CHAR_RIGHT_CURLY_BRACE, /* } */ + CHAR_RIGHT_PARENTHESES, /* ) */ + CHAR_RIGHT_SQUARE_BRACKET /* ] */ +} = __nccwpck_require__(435); - return to; +const isPathSeparator = code => { + return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH; }; -module.exports = mimicFn; -// TODO: Remove this for the next major release -module.exports["default"] = mimicFn; - +const depth = token => { + if (token.isPrefix !== true) { + token.depth = token.isGlobstar ? Infinity : 1; + } +}; -/***/ }), +/** + * Quickly scans a glob pattern and returns an object with a handful of + * useful properties, like `isGlob`, `path` (the leading non-glob, if it exists), + * `glob` (the actual pattern), `negated` (true if the path starts with `!` but not + * with `!(`) and `negatedExtglob` (true if the path starts with `!(`). + * + * ```js + * const pm = require('picomatch'); + * console.log(pm.scan('foo/bar/*.js')); + * { isGlob: true, input: 'foo/bar/*.js', base: 'foo/bar', glob: '*.js' } + * ``` + * @param {String} `str` + * @param {Object} `options` + * @return {Object} Returns an object with tokens and regex source string. + * @api public + */ -/***/ 7227: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +const scan = (input, options) => { + const opts = options || {}; -"use strict"; + const length = input.length - 1; + const scanToEnd = opts.parts === true || opts.scanToEnd === true; + const slashes = []; + const tokens = []; + const parts = []; -const path = __nccwpck_require__(6928); -const pathKey = __nccwpck_require__(5914); + let str = input; + let index = -1; + let start = 0; + let lastIndex = 0; + let isBrace = false; + let isBracket = false; + let isGlob = false; + let isExtglob = false; + let isGlobstar = false; + let braceEscaped = false; + let backslashes = false; + let negated = false; + let negatedExtglob = false; + let finished = false; + let braces = 0; + let prev; + let code; + let token = { value: '', depth: 0, isGlob: false }; -const npmRunPath = options => { - options = { - cwd: process.cwd(), - path: process.env[pathKey()], - execPath: process.execPath, - ...options - }; + const eos = () => index >= length; + const peek = () => str.charCodeAt(index + 1); + const advance = () => { + prev = code; + return str.charCodeAt(++index); + }; - let previous; - let cwdPath = path.resolve(options.cwd); - const result = []; + while (index < length) { + code = advance(); + let next; - while (previous !== cwdPath) { - result.push(path.join(cwdPath, 'node_modules/.bin')); - previous = cwdPath; - cwdPath = path.resolve(cwdPath, '..'); - } + if (code === CHAR_BACKWARD_SLASH) { + backslashes = token.backslashes = true; + code = advance(); - // Ensure the running `node` binary is used - const execPathDir = path.resolve(options.cwd, options.execPath, '..'); - result.push(execPathDir); + if (code === CHAR_LEFT_CURLY_BRACE) { + braceEscaped = true; + } + continue; + } - return result.concat(options.path).join(path.delimiter); -}; - -module.exports = npmRunPath; -// TODO: Remove this for the next major release -module.exports["default"] = npmRunPath; + if (braceEscaped === true || code === CHAR_LEFT_CURLY_BRACE) { + braces++; -module.exports.env = options => { - options = { - env: process.env, - ...options - }; + while (eos() !== true && (code = advance())) { + if (code === CHAR_BACKWARD_SLASH) { + backslashes = token.backslashes = true; + advance(); + continue; + } - const env = {...options.env}; - const path = pathKey({env}); + if (code === CHAR_LEFT_CURLY_BRACE) { + braces++; + continue; + } - options.path = env[path]; - env[path] = module.exports(options); + if (braceEscaped !== true && code === CHAR_DOT && (code = advance()) === CHAR_DOT) { + isBrace = token.isBrace = true; + isGlob = token.isGlob = true; + finished = true; - return env; -}; + if (scanToEnd === true) { + continue; + } + break; + } -/***/ }), + if (braceEscaped !== true && code === CHAR_COMMA) { + isBrace = token.isBrace = true; + isGlob = token.isGlob = true; + finished = true; -/***/ 1907: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + if (scanToEnd === true) { + continue; + } -"use strict"; + break; + } -const mimicFn = __nccwpck_require__(1881); + if (code === CHAR_RIGHT_CURLY_BRACE) { + braces--; -const calledFunctions = new WeakMap(); + if (braces === 0) { + braceEscaped = false; + isBrace = token.isBrace = true; + finished = true; + break; + } + } + } -const onetime = (function_, options = {}) => { - if (typeof function_ !== 'function') { - throw new TypeError('Expected a function'); - } + if (scanToEnd === true) { + continue; + } - let returnValue; - let callCount = 0; - const functionName = function_.displayName || function_.name || ''; + break; + } - const onetime = function (...arguments_) { - calledFunctions.set(onetime, ++callCount); + if (code === CHAR_FORWARD_SLASH) { + slashes.push(index); + tokens.push(token); + token = { value: '', depth: 0, isGlob: false }; - if (callCount === 1) { - returnValue = function_.apply(this, arguments_); - function_ = null; - } else if (options.throw === true) { - throw new Error(`Function \`${functionName}\` can only be called once`); - } + if (finished === true) continue; + if (prev === CHAR_DOT && index === (start + 1)) { + start += 2; + continue; + } - return returnValue; - }; + lastIndex = index + 1; + continue; + } - mimicFn(onetime, function_); - calledFunctions.set(onetime, callCount); + if (opts.noext !== true) { + const isExtglobChar = code === CHAR_PLUS + || code === CHAR_AT + || code === CHAR_ASTERISK + || code === CHAR_QUESTION_MARK + || code === CHAR_EXCLAMATION_MARK; - return onetime; -}; + if (isExtglobChar === true && peek() === CHAR_LEFT_PARENTHESES) { + isGlob = token.isGlob = true; + isExtglob = token.isExtglob = true; + finished = true; + if (code === CHAR_EXCLAMATION_MARK && index === start) { + negatedExtglob = true; + } -module.exports = onetime; -// TODO: Remove this for the next major release -module.exports["default"] = onetime; + if (scanToEnd === true) { + while (eos() !== true && (code = advance())) { + if (code === CHAR_BACKWARD_SLASH) { + backslashes = token.backslashes = true; + code = advance(); + continue; + } -module.exports.callCount = function_ => { - if (!calledFunctions.has(function_)) { - throw new Error(`The given function \`${function_.name}\` is not wrapped by the \`onetime\` package`); - } + if (code === CHAR_RIGHT_PARENTHESES) { + isGlob = token.isGlob = true; + finished = true; + break; + } + } + continue; + } + break; + } + } - return calledFunctions.get(function_); -}; + if (code === CHAR_ASTERISK) { + if (prev === CHAR_ASTERISK) isGlobstar = token.isGlobstar = true; + isGlob = token.isGlob = true; + finished = true; + if (scanToEnd === true) { + continue; + } + break; + } -/***/ }), + if (code === CHAR_QUESTION_MARK) { + isGlob = token.isGlob = true; + finished = true; -/***/ 5914: -/***/ ((module) => { + if (scanToEnd === true) { + continue; + } + break; + } -"use strict"; + if (code === CHAR_LEFT_SQUARE_BRACKET) { + while (eos() !== true && (next = advance())) { + if (next === CHAR_BACKWARD_SLASH) { + backslashes = token.backslashes = true; + advance(); + continue; + } + if (next === CHAR_RIGHT_SQUARE_BRACKET) { + isBracket = token.isBracket = true; + isGlob = token.isGlob = true; + finished = true; + break; + } + } -const pathKey = (options = {}) => { - const environment = options.env || process.env; - const platform = options.platform || process.platform; + if (scanToEnd === true) { + continue; + } - if (platform !== 'win32') { - return 'PATH'; - } + break; + } - return Object.keys(environment).reverse().find(key => key.toUpperCase() === 'PATH') || 'Path'; -}; + if (opts.nonegate !== true && code === CHAR_EXCLAMATION_MARK && index === start) { + negated = token.negated = true; + start++; + continue; + } -module.exports = pathKey; -// TODO: Remove this for the next major release -module.exports["default"] = pathKey; + if (opts.noparen !== true && code === CHAR_LEFT_PARENTHESES) { + isGlob = token.isGlob = true; + if (scanToEnd === true) { + while (eos() !== true && (code = advance())) { + if (code === CHAR_LEFT_PARENTHESES) { + backslashes = token.backslashes = true; + code = advance(); + continue; + } -/***/ }), + if (code === CHAR_RIGHT_PARENTHESES) { + finished = true; + break; + } + } + continue; + } + break; + } -/***/ 1689: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + if (isGlob === true) { + finished = true; -"use strict"; + if (scanToEnd === true) { + continue; + } + break; + } + } -module.exports = __nccwpck_require__(9511); + if (opts.noext === true) { + isExtglob = false; + isGlob = false; + } + let base = str; + let prefix = ''; + let glob = ''; -/***/ }), + if (start > 0) { + prefix = str.slice(0, start); + str = str.slice(start); + lastIndex -= start; + } -/***/ 4952: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + if (base && isGlob === true && lastIndex > 0) { + base = str.slice(0, lastIndex); + glob = str.slice(lastIndex); + } else if (isGlob === true) { + base = ''; + glob = str; + } else { + base = str; + } -"use strict"; + if (base && base !== '' && base !== '/' && base !== str) { + if (isPathSeparator(base.charCodeAt(base.length - 1))) { + base = base.slice(0, -1); + } + } + if (opts.unescape === true) { + if (glob) glob = utils.removeBackslashes(glob); -const path = __nccwpck_require__(6928); -const WIN_SLASH = '\\\\/'; -const WIN_NO_SLASH = `[^${WIN_SLASH}]`; + if (base && backslashes === true) { + base = utils.removeBackslashes(base); + } + } -/** - * Posix glob regex - */ + const state = { + prefix, + input, + start, + base, + glob, + isBrace, + isBracket, + isGlob, + isExtglob, + isGlobstar, + negated, + negatedExtglob + }; -const DOT_LITERAL = '\\.'; -const PLUS_LITERAL = '\\+'; -const QMARK_LITERAL = '\\?'; -const SLASH_LITERAL = '\\/'; -const ONE_CHAR = '(?=.)'; -const QMARK = '[^/]'; -const END_ANCHOR = `(?:${SLASH_LITERAL}|$)`; -const START_ANCHOR = `(?:^|${SLASH_LITERAL})`; -const DOTS_SLASH = `${DOT_LITERAL}{1,2}${END_ANCHOR}`; -const NO_DOT = `(?!${DOT_LITERAL})`; -const NO_DOTS = `(?!${START_ANCHOR}${DOTS_SLASH})`; -const NO_DOT_SLASH = `(?!${DOT_LITERAL}{0,1}${END_ANCHOR})`; -const NO_DOTS_SLASH = `(?!${DOTS_SLASH})`; -const QMARK_NO_DOT = `[^.${SLASH_LITERAL}]`; -const STAR = `${QMARK}*?`; + if (opts.tokens === true) { + state.maxDepth = 0; + if (!isPathSeparator(code)) { + tokens.push(token); + } + state.tokens = tokens; + } -const POSIX_CHARS = { - DOT_LITERAL, - PLUS_LITERAL, - QMARK_LITERAL, - SLASH_LITERAL, - ONE_CHAR, - QMARK, - END_ANCHOR, - DOTS_SLASH, - NO_DOT, - NO_DOTS, - NO_DOT_SLASH, - NO_DOTS_SLASH, - QMARK_NO_DOT, - STAR, - START_ANCHOR -}; + if (opts.parts === true || opts.tokens === true) { + let prevIndex; -/** - * Windows glob regex - */ + for (let idx = 0; idx < slashes.length; idx++) { + const n = prevIndex ? prevIndex + 1 : start; + const i = slashes[idx]; + const value = input.slice(n, i); + if (opts.tokens) { + if (idx === 0 && start !== 0) { + tokens[idx].isPrefix = true; + tokens[idx].value = prefix; + } else { + tokens[idx].value = value; + } + depth(tokens[idx]); + state.maxDepth += tokens[idx].depth; + } + if (idx !== 0 || value !== '') { + parts.push(value); + } + prevIndex = i; + } -const WINDOWS_CHARS = { - ...POSIX_CHARS, + if (prevIndex && prevIndex + 1 < input.length) { + const value = input.slice(prevIndex + 1); + parts.push(value); - SLASH_LITERAL: `[${WIN_SLASH}]`, - QMARK: WIN_NO_SLASH, - STAR: `${WIN_NO_SLASH}*?`, - DOTS_SLASH: `${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$)`, - NO_DOT: `(?!${DOT_LITERAL})`, - NO_DOTS: `(?!(?:^|[${WIN_SLASH}])${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$))`, - NO_DOT_SLASH: `(?!${DOT_LITERAL}{0,1}(?:[${WIN_SLASH}]|$))`, - NO_DOTS_SLASH: `(?!${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$))`, - QMARK_NO_DOT: `[^.${WIN_SLASH}]`, - START_ANCHOR: `(?:^|[${WIN_SLASH}])`, - END_ANCHOR: `(?:[${WIN_SLASH}]|$)` -}; + if (opts.tokens) { + tokens[tokens.length - 1].value = value; + depth(tokens[tokens.length - 1]); + state.maxDepth += tokens[tokens.length - 1].depth; + } + } -/** - * POSIX Bracket Regex - */ + state.slashes = slashes; + state.parts = parts; + } -const POSIX_REGEX_SOURCE = { - alnum: 'a-zA-Z0-9', - alpha: 'a-zA-Z', - ascii: '\\x00-\\x7F', - blank: ' \\t', - cntrl: '\\x00-\\x1F\\x7F', - digit: '0-9', - graph: '\\x21-\\x7E', - lower: 'a-z', - print: '\\x20-\\x7E ', - punct: '\\-!"#$%&\'()\\*+,./:;<=>?@[\\]^_`{|}~', - space: ' \\t\\r\\n\\v\\f', - upper: 'A-Z', - word: 'A-Za-z0-9_', - xdigit: 'A-Fa-f0-9' + return state; }; -module.exports = { - MAX_LENGTH: 1024 * 64, - POSIX_REGEX_SOURCE, +module.exports = scan; - // regular expressions - REGEX_BACKSLASH: /\\(?![*+?^${}(|)[\]])/g, - REGEX_NON_SPECIAL_CHARS: /^[^@![\].,$*+?^{}()|\\/]+/, - REGEX_SPECIAL_CHARS: /[-*+?.^${}(|)[\]]/, - REGEX_SPECIAL_CHARS_BACKREF: /(\\?)((\W)(\3*))/g, - REGEX_SPECIAL_CHARS_GLOBAL: /([-*+?.^${}(|)[\]])/g, - REGEX_REMOVE_BACKSLASH: /(?:\[.*?[^\\]\]|\\(?=.))/g, - // Replace globs with equivalent patterns to reduce parsing time. - REPLACEMENTS: { - '***': '*', - '**/**': '**', - '**/**/**': '**' - }, +/***/ }), - // Digits - CHAR_0: 48, /* 0 */ - CHAR_9: 57, /* 9 */ +/***/ 7379: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - // Alphabet chars. - CHAR_UPPERCASE_A: 65, /* A */ - CHAR_LOWERCASE_A: 97, /* a */ - CHAR_UPPERCASE_Z: 90, /* Z */ - CHAR_LOWERCASE_Z: 122, /* z */ - CHAR_LEFT_PARENTHESES: 40, /* ( */ - CHAR_RIGHT_PARENTHESES: 41, /* ) */ - CHAR_ASTERISK: 42, /* * */ +const path = __nccwpck_require__(6928); +const win32 = process.platform === 'win32'; +const { + REGEX_BACKSLASH, + REGEX_REMOVE_BACKSLASH, + REGEX_SPECIAL_CHARS, + REGEX_SPECIAL_CHARS_GLOBAL +} = __nccwpck_require__(435); - // Non-alphabetic chars. - CHAR_AMPERSAND: 38, /* & */ - CHAR_AT: 64, /* @ */ - CHAR_BACKWARD_SLASH: 92, /* \ */ - CHAR_CARRIAGE_RETURN: 13, /* \r */ - CHAR_CIRCUMFLEX_ACCENT: 94, /* ^ */ - CHAR_COLON: 58, /* : */ - CHAR_COMMA: 44, /* , */ - CHAR_DOT: 46, /* . */ - CHAR_DOUBLE_QUOTE: 34, /* " */ - CHAR_EQUAL: 61, /* = */ - CHAR_EXCLAMATION_MARK: 33, /* ! */ - CHAR_FORM_FEED: 12, /* \f */ - CHAR_FORWARD_SLASH: 47, /* / */ - CHAR_GRAVE_ACCENT: 96, /* ` */ - CHAR_HASH: 35, /* # */ - CHAR_HYPHEN_MINUS: 45, /* - */ - CHAR_LEFT_ANGLE_BRACKET: 60, /* < */ - CHAR_LEFT_CURLY_BRACE: 123, /* { */ - CHAR_LEFT_SQUARE_BRACKET: 91, /* [ */ - CHAR_LINE_FEED: 10, /* \n */ - CHAR_NO_BREAK_SPACE: 160, /* \u00A0 */ - CHAR_PERCENT: 37, /* % */ - CHAR_PLUS: 43, /* + */ - CHAR_QUESTION_MARK: 63, /* ? */ - CHAR_RIGHT_ANGLE_BRACKET: 62, /* > */ - CHAR_RIGHT_CURLY_BRACE: 125, /* } */ - CHAR_RIGHT_SQUARE_BRACKET: 93, /* ] */ - CHAR_SEMICOLON: 59, /* ; */ - CHAR_SINGLE_QUOTE: 39, /* ' */ - CHAR_SPACE: 32, /* */ - CHAR_TAB: 9, /* \t */ - CHAR_UNDERSCORE: 95, /* _ */ - CHAR_VERTICAL_LINE: 124, /* | */ - CHAR_ZERO_WIDTH_NOBREAK_SPACE: 65279, /* \uFEFF */ +exports.isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val); +exports.hasRegexChars = str => REGEX_SPECIAL_CHARS.test(str); +exports.isRegexChar = str => str.length === 1 && exports.hasRegexChars(str); +exports.escapeRegex = str => str.replace(REGEX_SPECIAL_CHARS_GLOBAL, '\\$1'); +exports.toPosixSlashes = str => str.replace(REGEX_BACKSLASH, '/'); - SEP: path.sep, +exports.removeBackslashes = str => { + return str.replace(REGEX_REMOVE_BACKSLASH, match => { + return match === '\\' ? '' : match; + }); +}; - /** - * Create EXTGLOB_CHARS - */ +exports.supportsLookbehinds = () => { + const segs = process.version.slice(1).split('.').map(Number); + if (segs.length === 3 && segs[0] >= 9 || (segs[0] === 8 && segs[1] >= 10)) { + return true; + } + return false; +}; - extglobChars(chars) { - return { - '!': { type: 'negate', open: '(?:(?!(?:', close: `))${chars.STAR})` }, - '?': { type: 'qmark', open: '(?:', close: ')?' }, - '+': { type: 'plus', open: '(?:', close: ')+' }, - '*': { type: 'star', open: '(?:', close: ')*' }, - '@': { type: 'at', open: '(?:', close: ')' } - }; - }, +exports.isWindows = options => { + if (options && typeof options.windows === 'boolean') { + return options.windows; + } + return win32 === true || path.sep === '\\'; +}; - /** - * Create GLOB_CHARS - */ +exports.escapeLast = (input, char, lastIdx) => { + const idx = input.lastIndexOf(char, lastIdx); + if (idx === -1) return input; + if (input[idx - 1] === '\\') return exports.escapeLast(input, char, idx - 1); + return `${input.slice(0, idx)}\\${input.slice(idx)}`; +}; - globChars(win32) { - return win32 === true ? WINDOWS_CHARS : POSIX_CHARS; +exports.removePrefix = (input, state = {}) => { + let output = input; + if (output.startsWith('./')) { + output = output.slice(2); + state.prefix = './'; } + return output; }; +exports.wrapOutput = (input, state = {}, options = {}) => { + const prepend = options.contains ? '' : '^'; + const append = options.contains ? '' : '$'; -/***/ }), - -/***/ 5638: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + let output = `${prepend}(?:${input})${append}`; + if (state.negated === true) { + output = `(?:^(?!${output}).*$)`; + } + return output; +}; -"use strict"; +/***/ }), -const constants = __nccwpck_require__(4952); -const utils = __nccwpck_require__(9116); +/***/ 1245: +/***/ ((module) => { -/** - * Constants - */ +/*! queue-microtask. MIT License. Feross Aboukhadijeh */ +let promise -const { - MAX_LENGTH, - POSIX_REGEX_SOURCE, - REGEX_NON_SPECIAL_CHARS, - REGEX_SPECIAL_CHARS_BACKREF, - REPLACEMENTS -} = constants; +module.exports = typeof queueMicrotask === 'function' + ? queueMicrotask.bind(typeof window !== 'undefined' ? window : global) + // reuse resolved promise, and allocate it lazily + : cb => (promise || (promise = Promise.resolve())) + .then(cb) + .catch(err => setTimeout(() => { throw err }, 0)) -/** - * Helpers - */ -const expandRange = (args, options) => { - if (typeof options.expandRange === 'function') { - return options.expandRange(...args, options); - } +/***/ }), - args.sort(); - const value = `[${args.join('-')}]`; +/***/ 7093: +/***/ ((module) => { - try { - /* eslint-disable-next-line no-new */ - new RegExp(value); - } catch (ex) { - return args.map(v => utils.escapeRegex(v)).join('..'); - } - return value; -}; -/** - * Create the message for a syntax error - */ +function reusify (Constructor) { + var head = new Constructor() + var tail = head -const syntaxError = (type, char) => { - return `Missing ${type}: "${char}" - use "\\\\${char}" to match literal characters`; -}; + function get () { + var current = head -/** - * Parse the given input string. - * @param {String} input - * @param {Object} options - * @return {Object} - */ + if (current.next) { + head = current.next + } else { + head = new Constructor() + tail = head + } -const parse = (input, options) => { - if (typeof input !== 'string') { - throw new TypeError('Expected a string'); - } + current.next = null - input = REPLACEMENTS[input] || input; + return current + } - const opts = { ...options }; - const max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH; + function release (obj) { + tail.next = obj + tail = obj + } - let len = input.length; - if (len > max) { - throw new SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`); + return { + get: get, + release: release } +} - const bos = { type: 'bos', value: '', output: opts.prepend || '' }; - const tokens = [bos]; +module.exports = reusify - const capture = opts.capture ? '' : '?:'; - const win32 = utils.isWindows(options); - // create constants based on platform, for windows or posix - const PLATFORM_CHARS = constants.globChars(win32); - const EXTGLOB_CHARS = constants.extglobChars(PLATFORM_CHARS); +/***/ }), - const { - DOT_LITERAL, - PLUS_LITERAL, - SLASH_LITERAL, - ONE_CHAR, - DOTS_SLASH, - NO_DOT, - NO_DOT_SLASH, - NO_DOTS_SLASH, - QMARK, - QMARK_NO_DOT, - STAR, - START_ANCHOR - } = PLATFORM_CHARS; +/***/ 9571: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - const globstar = opts => { - return `(${capture}(?:(?!${START_ANCHOR}${opts.dot ? DOTS_SLASH : DOT_LITERAL}).)*?)`; - }; +/*! run-parallel. MIT License. Feross Aboukhadijeh */ +module.exports = runParallel - const nodot = opts.dot ? '' : NO_DOT; - const qmarkNoDot = opts.dot ? QMARK : QMARK_NO_DOT; - let star = opts.bash === true ? globstar(opts) : STAR; +const queueMicrotask = __nccwpck_require__(1245) - if (opts.capture) { - star = `(${star})`; - } +function runParallel (tasks, cb) { + let results, pending, keys + let isSync = true - // minimatch options support - if (typeof opts.noext === 'boolean') { - opts.noextglob = opts.noext; + if (Array.isArray(tasks)) { + results = [] + pending = tasks.length + } else { + keys = Object.keys(tasks) + results = {} + pending = keys.length } - const state = { - input, - index: -1, - start: 0, - dot: opts.dot === true, - consumed: '', - output: '', - prefix: '', - backtrack: false, - negated: false, - brackets: 0, - braces: 0, - parens: 0, - quotes: 0, - globstar: false, - tokens - }; - - input = utils.removePrefix(input, state); - len = input.length; - - const extglobs = []; - const braces = []; - const stack = []; - let prev = bos; - let value; - - /** - * Tokenizing helpers - */ + function done (err) { + function end () { + if (cb) cb(err, results) + cb = null + } + if (isSync) queueMicrotask(end) + else end() + } - const eos = () => state.index === len - 1; - const peek = state.peek = (n = 1) => input[state.index + n]; - const advance = state.advance = () => input[++state.index] || ''; - const remaining = () => input.slice(state.index + 1); - const consume = (value = '', num = 0) => { - state.consumed += value; - state.index += num; - }; + function each (i, err, result) { + results[i] = result + if (--pending === 0 || err) { + done(err) + } + } - const append = token => { - state.output += token.output != null ? token.output : token.value; - consume(token.value); - }; + if (!pending) { + // empty + done(null) + } else if (keys) { + // object + keys.forEach(function (key) { + tasks[key](function (err, result) { each(key, err, result) }) + }) + } else { + // array + tasks.forEach(function (task, i) { + task(function (err, result) { each(i, err, result) }) + }) + } - const negate = () => { - let count = 1; + isSync = false +} - while (peek() === '!' && (peek(2) !== '(' || peek(3) === '?')) { - advance(); - state.start++; - count++; - } - if (count % 2 === 0) { - return false; - } +/***/ }), - state.negated = true; - state.start++; - return true; - }; +/***/ 5388: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - const increment = type => { - state[type]++; - stack.push(type); - }; - const decrement = type => { - state[type]--; - stack.pop(); - }; - /** - * Push tokens onto the tokens array. This helper speeds up - * tokenizing by 1) helping us avoid backtracking as much as possible, - * and 2) helping us avoid creating extra tokens when consecutive - * characters are plain text. This improves performance and simplifies - * lookbehinds. - */ +const ANY = Symbol('SemVer ANY') +// hoisted class for cyclic dependency +class Comparator { + static get ANY () { + return ANY + } - const push = tok => { - if (prev.type === 'globstar') { - const isBrace = state.braces > 0 && (tok.type === 'comma' || tok.type === 'brace'); - const isExtglob = tok.extglob === true || (extglobs.length && (tok.type === 'pipe' || tok.type === 'paren')); + constructor (comp, options) { + options = parseOptions(options) - if (tok.type !== 'slash' && tok.type !== 'paren' && !isBrace && !isExtglob) { - state.output = state.output.slice(0, -prev.output.length); - prev.type = 'star'; - prev.value = '*'; - prev.output = star; - state.output += prev.output; + if (comp instanceof Comparator) { + if (comp.loose === !!options.loose) { + return comp + } else { + comp = comp.value } } - if (extglobs.length && tok.type !== 'paren') { - extglobs[extglobs.length - 1].inner += tok.value; - } + comp = comp.trim().split(/\s+/).join(' ') + debug('comparator', comp, options) + this.options = options + this.loose = !!options.loose + this.parse(comp) - if (tok.value || tok.output) append(tok); - if (prev && prev.type === 'text' && tok.type === 'text') { - prev.value += tok.value; - prev.output = (prev.output || '') + tok.value; - return; + if (this.semver === ANY) { + this.value = '' + } else { + this.value = this.operator + this.semver.version } - tok.prev = prev; - tokens.push(tok); - prev = tok; - }; - - const extglobOpen = (type, value) => { - const token = { ...EXTGLOB_CHARS[value], conditions: 1, inner: '' }; - - token.prev = prev; - token.parens = state.parens; - token.output = state.output; - const output = (opts.capture ? '(' : '') + token.open; + debug('comp', this) + } - increment('parens'); - push({ type, value, output: state.output ? '' : ONE_CHAR }); - push({ type: 'paren', extglob: true, value: advance(), output }); - extglobs.push(token); - }; + parse (comp) { + const r = this.options.loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR] + const m = comp.match(r) - const extglobClose = token => { - let output = token.close + (opts.capture ? ')' : ''); - let rest; + if (!m) { + throw new TypeError(`Invalid comparator: ${comp}`) + } - if (token.type === 'negate') { - let extglobStar = star; + this.operator = m[1] !== undefined ? m[1] : '' + if (this.operator === '=') { + this.operator = '' + } - if (token.inner && token.inner.length > 1 && token.inner.includes('/')) { - extglobStar = globstar(opts); - } + // if it literally is just '>' or '' then allow anything. + if (!m[2]) { + this.semver = ANY + } else { + this.semver = new SemVer(m[2], this.options.loose) + } + } - if (extglobStar !== star || eos() || /^\)+$/.test(remaining())) { - output = token.close = `)$))${extglobStar}`; - } + toString () { + return this.value + } - if (token.inner.includes('*') && (rest = remaining()) && /^\.[^\\/.]+$/.test(rest)) { - // Any non-magical string (`.ts`) or even nested expression (`.{ts,tsx}`) can follow after the closing parenthesis. - // In this case, we need to parse the string and use it in the output of the original pattern. - // Suitable patterns: `/!(*.d).ts`, `/!(*.d).{ts,tsx}`, `**/!(*-dbg).@(js)`. - // - // Disabling the `fastpaths` option due to a problem with parsing strings as `.ts` in the pattern like `**/!(*.d).ts`. - const expression = parse(rest, { ...options, fastpaths: false }).output; + test (version) { + debug('Comparator.test', version, this.options.loose) - output = token.close = `)${expression})${extglobStar})`; - } + if (this.semver === ANY || version === ANY) { + return true + } - if (token.prev.type === 'bos') { - state.negatedExtglob = true; + if (typeof version === 'string') { + try { + version = new SemVer(version, this.options) + } catch (er) { + return false } } - push({ type: 'paren', extglob: true, value, output }); - decrement('parens'); - }; - - /** - * Fast paths - */ - - if (opts.fastpaths !== false && !/(^[*!]|[/()[\]{}"])/.test(input)) { - let backslashes = false; + return cmp(version, this.operator, this.semver, this.options) + } - let output = input.replace(REGEX_SPECIAL_CHARS_BACKREF, (m, esc, chars, first, rest, index) => { - if (first === '\\') { - backslashes = true; - return m; - } + intersects (comp, options) { + if (!(comp instanceof Comparator)) { + throw new TypeError('a Comparator is required') + } - if (first === '?') { - if (esc) { - return esc + first + (rest ? QMARK.repeat(rest.length) : ''); - } - if (index === 0) { - return qmarkNoDot + (rest ? QMARK.repeat(rest.length) : ''); - } - return QMARK.repeat(chars.length); + if (this.operator === '') { + if (this.value === '') { + return true } - - if (first === '.') { - return DOT_LITERAL.repeat(chars.length); + return new Range(comp.value, options).test(this.value) + } else if (comp.operator === '') { + if (comp.value === '') { + return true } + return new Range(this.value, options).test(comp.semver) + } - if (first === '*') { - if (esc) { - return esc + first + (rest ? star : ''); - } - return star; - } - return esc ? m : `\\${m}`; - }); + options = parseOptions(options) - if (backslashes === true) { - if (opts.unescape === true) { - output = output.replace(/\\/g, ''); - } else { - output = output.replace(/\\+/g, m => { - return m.length % 2 === 0 ? '\\\\' : (m ? '\\' : ''); - }); - } + // Special cases where nothing can possibly be lower + if (options.includePrerelease && + (this.value === '<0.0.0-0' || comp.value === '<0.0.0-0')) { + return false } - - if (output === input && opts.contains === true) { - state.output = input; - return state; + if (!options.includePrerelease && + (this.value.startsWith('<0.0.0') || comp.value.startsWith('<0.0.0'))) { + return false } - state.output = utils.wrapOutput(output, state, options); - return state; + // Same direction increasing (> or >=) + if (this.operator.startsWith('>') && comp.operator.startsWith('>')) { + return true + } + // Same direction decreasing (< or <=) + if (this.operator.startsWith('<') && comp.operator.startsWith('<')) { + return true + } + // same SemVer and both sides are inclusive (<= or >=) + if ( + (this.semver.version === comp.semver.version) && + this.operator.includes('=') && comp.operator.includes('=')) { + return true + } + // opposite directions less than + if (cmp(this.semver, '<', comp.semver, options) && + this.operator.startsWith('>') && comp.operator.startsWith('<')) { + return true + } + // opposite directions greater than + if (cmp(this.semver, '>', comp.semver, options) && + this.operator.startsWith('<') && comp.operator.startsWith('>')) { + return true + } + return false } +} - /** - * Tokenize input until we reach end-of-string - */ - - while (!eos()) { - value = advance(); +module.exports = Comparator - if (value === '\u0000') { - continue; - } +const parseOptions = __nccwpck_require__(207) +const { safeRe: re, t } = __nccwpck_require__(2330) +const cmp = __nccwpck_require__(6907) +const debug = __nccwpck_require__(8284) +const SemVer = __nccwpck_require__(1776) +const Range = __nccwpck_require__(1699) - /** - * Escaped characters - */ - if (value === '\\') { - const next = peek(); +/***/ }), - if (next === '/' && opts.bash !== true) { - continue; - } +/***/ 1699: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - if (next === '.' || next === ';') { - continue; - } - if (!next) { - value += '\\'; - push({ type: 'text', value }); - continue; - } - // collapse slashes to reduce potential for exploits - const match = /^\\+/.exec(remaining()); - let slashes = 0; +const SPACE_CHARACTERS = /\s+/g - if (match && match[0].length > 2) { - slashes = match[0].length; - state.index += slashes; - if (slashes % 2 !== 0) { - value += '\\'; - } - } +// hoisted class for cyclic dependency +class Range { + constructor (range, options) { + options = parseOptions(options) - if (opts.unescape === true) { - value = advance(); + if (range instanceof Range) { + if ( + range.loose === !!options.loose && + range.includePrerelease === !!options.includePrerelease + ) { + return range } else { - value += advance(); - } - - if (state.brackets === 0) { - push({ type: 'text', value }); - continue; + return new Range(range.raw, options) } } - /** - * If we're inside a regex character class, continue - * until we reach the closing bracket. - */ - - if (state.brackets > 0 && (value !== ']' || prev.value === '[' || prev.value === '[^')) { - if (opts.posix !== false && value === ':') { - const inner = prev.value.slice(1); - if (inner.includes('[')) { - prev.posix = true; + if (range instanceof Comparator) { + // just put it in the set and return + this.raw = range.value + this.set = [[range]] + this.formatted = undefined + return this + } - if (inner.includes(':')) { - const idx = prev.value.lastIndexOf('['); - const pre = prev.value.slice(0, idx); - const rest = prev.value.slice(idx + 2); - const posix = POSIX_REGEX_SOURCE[rest]; - if (posix) { - prev.value = pre + posix; - state.backtrack = true; - advance(); + this.options = options + this.loose = !!options.loose + this.includePrerelease = !!options.includePrerelease - if (!bos.output && tokens.indexOf(prev) === 1) { - bos.output = ONE_CHAR; - } - continue; - } + // First reduce all whitespace as much as possible so we do not have to rely + // on potentially slow regexes like \s*. This is then stored and used for + // future error messages as well. + this.raw = range.trim().replace(SPACE_CHARACTERS, ' ') + + // First, split on || + this.set = this.raw + .split('||') + // map the range to a 2d array of comparators + .map(r => this.parseRange(r.trim())) + // throw out any comparator lists that are empty + // this generally means that it was not a valid range, which is allowed + // in loose mode, but will still throw if the WHOLE range is invalid. + .filter(c => c.length) + + if (!this.set.length) { + throw new TypeError(`Invalid SemVer Range: ${this.raw}`) + } + + // if we have any that are not the null set, throw out null sets. + if (this.set.length > 1) { + // keep the first one, in case they're all null sets + const first = this.set[0] + this.set = this.set.filter(c => !isNullSet(c[0])) + if (this.set.length === 0) { + this.set = [first] + } else if (this.set.length > 1) { + // if we have any that are *, then the range is just * + for (const c of this.set) { + if (c.length === 1 && isAny(c[0])) { + this.set = [c] + break } } } + } - if ((value === '[' && peek() !== ':') || (value === '-' && peek() === ']')) { - value = `\\${value}`; - } + this.formatted = undefined + } - if (value === ']' && (prev.value === '[' || prev.value === '[^')) { - value = `\\${value}`; + get range () { + if (this.formatted === undefined) { + this.formatted = '' + for (let i = 0; i < this.set.length; i++) { + if (i > 0) { + this.formatted += '||' + } + const comps = this.set[i] + for (let k = 0; k < comps.length; k++) { + if (k > 0) { + this.formatted += ' ' + } + this.formatted += comps[k].toString().trim() + } } + } + return this.formatted + } - if (opts.posix === true && value === '!' && prev.value === '[') { - value = '^'; - } + format () { + return this.range + } - prev.value += value; - append({ value }); - continue; + toString () { + return this.range + } + + parseRange (range) { + // memoize range parsing for performance. + // this is a very hot path, and fully deterministic. + const memoOpts = + (this.options.includePrerelease && FLAG_INCLUDE_PRERELEASE) | + (this.options.loose && FLAG_LOOSE) + const memoKey = memoOpts + ':' + range + const cached = cache.get(memoKey) + if (cached) { + return cached } - /** - * If we're inside a quoted string, continue - * until we reach the closing double quote. - */ + const loose = this.options.loose + // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4` + const hr = loose ? re[t.HYPHENRANGELOOSE] : re[t.HYPHENRANGE] + range = range.replace(hr, hyphenReplace(this.options.includePrerelease)) + debug('hyphen replace', range) - if (state.quotes === 1 && value !== '"') { - value = utils.escapeRegex(value); - prev.value += value; - append({ value }); - continue; - } + // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5` + range = range.replace(re[t.COMPARATORTRIM], comparatorTrimReplace) + debug('comparator trim', range) - /** - * Double quotes - */ + // `~ 1.2.3` => `~1.2.3` + range = range.replace(re[t.TILDETRIM], tildeTrimReplace) + debug('tilde trim', range) - if (value === '"') { - state.quotes = state.quotes === 1 ? 0 : 1; - if (opts.keepQuotes === true) { - push({ type: 'text', value }); - } - continue; - } + // `^ 1.2.3` => `^1.2.3` + range = range.replace(re[t.CARETTRIM], caretTrimReplace) + debug('caret trim', range) - /** - * Parentheses - */ + // At this point, the range is completely trimmed and + // ready to be split into comparators. - if (value === '(') { - increment('parens'); - push({ type: 'paren', value }); - continue; + let rangeList = range + .split(' ') + .map(comp => parseComparator(comp, this.options)) + .join(' ') + .split(/\s+/) + // >=0.0.0 is equivalent to * + .map(comp => replaceGTE0(comp, this.options)) + + if (loose) { + // in loose mode, throw out any that are not valid comparators + rangeList = rangeList.filter(comp => { + debug('loose invalid filter', comp, this.options) + return !!comp.match(re[t.COMPARATORLOOSE]) + }) } + debug('range list', rangeList) - if (value === ')') { - if (state.parens === 0 && opts.strictBrackets === true) { - throw new SyntaxError(syntaxError('opening', '(')); + // if any comparators are the null set, then replace with JUST null set + // if more than one comparator, remove any * comparators + // also, don't include the same comparator more than once + const rangeMap = new Map() + const comparators = rangeList.map(comp => new Comparator(comp, this.options)) + for (const comp of comparators) { + if (isNullSet(comp)) { + return [comp] } + rangeMap.set(comp.value, comp) + } + if (rangeMap.size > 1 && rangeMap.has('')) { + rangeMap.delete('') + } - const extglob = extglobs[extglobs.length - 1]; - if (extglob && state.parens === extglob.parens + 1) { - extglobClose(extglobs.pop()); - continue; - } + const result = [...rangeMap.values()] + cache.set(memoKey, result) + return result + } - push({ type: 'paren', value, output: state.parens ? ')' : '\\)' }); - decrement('parens'); - continue; + intersects (range, options) { + if (!(range instanceof Range)) { + throw new TypeError('a Range is required') } - /** - * Square brackets - */ + return this.set.some((thisComparators) => { + return ( + isSatisfiable(thisComparators, options) && + range.set.some((rangeComparators) => { + return ( + isSatisfiable(rangeComparators, options) && + thisComparators.every((thisComparator) => { + return rangeComparators.every((rangeComparator) => { + return thisComparator.intersects(rangeComparator, options) + }) + }) + ) + }) + ) + }) + } - if (value === '[') { - if (opts.nobracket === true || !remaining().includes(']')) { - if (opts.nobracket !== true && opts.strictBrackets === true) { - throw new SyntaxError(syntaxError('closing', ']')); - } + // if ANY of the sets match ALL of its comparators, then pass + test (version) { + if (!version) { + return false + } - value = `\\${value}`; - } else { - increment('brackets'); + if (typeof version === 'string') { + try { + version = new SemVer(version, this.options) + } catch (er) { + return false } - - push({ type: 'bracket', value }); - continue; } - if (value === ']') { - if (opts.nobracket === true || (prev && prev.type === 'bracket' && prev.value.length === 1)) { - push({ type: 'text', value, output: `\\${value}` }); - continue; + for (let i = 0; i < this.set.length; i++) { + if (testSet(this.set[i], version, this.options)) { + return true } + } + return false + } +} - if (state.brackets === 0) { - if (opts.strictBrackets === true) { - throw new SyntaxError(syntaxError('opening', '[')); - } +module.exports = Range - push({ type: 'text', value, output: `\\${value}` }); - continue; - } +const LRU = __nccwpck_require__(5630) +const cache = new LRU() - decrement('brackets'); +const parseOptions = __nccwpck_require__(207) +const Comparator = __nccwpck_require__(5388) +const debug = __nccwpck_require__(8284) +const SemVer = __nccwpck_require__(1776) +const { + safeRe: re, + t, + comparatorTrimReplace, + tildeTrimReplace, + caretTrimReplace, +} = __nccwpck_require__(2330) +const { FLAG_INCLUDE_PRERELEASE, FLAG_LOOSE } = __nccwpck_require__(470) - const prevValue = prev.value.slice(1); - if (prev.posix !== true && prevValue[0] === '^' && !prevValue.includes('/')) { - value = `/${value}`; - } +const isNullSet = c => c.value === '<0.0.0-0' +const isAny = c => c.value === '' - prev.value += value; - append({ value }); +// take a set of comparators and determine whether there +// exists a version which can satisfy it +const isSatisfiable = (comparators, options) => { + let result = true + const remainingComparators = comparators.slice() + let testComparator = remainingComparators.pop() - // when literal brackets are explicitly disabled - // assume we should match with a regex character class - if (opts.literalBrackets === false || utils.hasRegexChars(prevValue)) { - continue; - } + while (result && remainingComparators.length) { + result = remainingComparators.every((otherComparator) => { + return testComparator.intersects(otherComparator, options) + }) - const escaped = utils.escapeRegex(prev.value); - state.output = state.output.slice(0, -prev.value.length); + testComparator = remainingComparators.pop() + } - // when literal brackets are explicitly enabled - // assume we should escape the brackets to match literal characters - if (opts.literalBrackets === true) { - state.output += escaped; - prev.value = escaped; - continue; - } + return result +} - // when the user specifies nothing, try to match both - prev.value = `(${capture}${escaped}|${prev.value})`; - state.output += prev.value; - continue; - } +// comprised of xranges, tildes, stars, and gtlt's at this point. +// already replaced the hyphen ranges +// turn into a set of JUST comparators. +const parseComparator = (comp, options) => { + comp = comp.replace(re[t.BUILD], '') + debug('comp', comp, options) + comp = replaceCarets(comp, options) + debug('caret', comp) + comp = replaceTildes(comp, options) + debug('tildes', comp) + comp = replaceXRanges(comp, options) + debug('xrange', comp) + comp = replaceStars(comp, options) + debug('stars', comp) + return comp +} - /** - * Braces - */ +const isX = id => !id || id.toLowerCase() === 'x' || id === '*' - if (value === '{' && opts.nobrace !== true) { - increment('braces'); +// ~, ~> --> * (any, kinda silly) +// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0-0 +// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0-0 +// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0-0 +// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0-0 +// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0-0 +// ~0.0.1 --> >=0.0.1 <0.1.0-0 +const replaceTildes = (comp, options) => { + return comp + .trim() + .split(/\s+/) + .map((c) => replaceTilde(c, options)) + .join(' ') +} - const open = { - type: 'brace', - value, - output: '(', - outputIndex: state.output.length, - tokensIndex: state.tokens.length - }; +const replaceTilde = (comp, options) => { + const r = options.loose ? re[t.TILDELOOSE] : re[t.TILDE] + return comp.replace(r, (_, M, m, p, pr) => { + debug('tilde', comp, _, M, m, p, pr) + let ret - braces.push(open); - push(open); - continue; + if (isX(M)) { + ret = '' + } else if (isX(m)) { + ret = `>=${M}.0.0 <${+M + 1}.0.0-0` + } else if (isX(p)) { + // ~1.2 == >=1.2.0 <1.3.0-0 + ret = `>=${M}.${m}.0 <${M}.${+m + 1}.0-0` + } else if (pr) { + debug('replaceTilde pr', pr) + ret = `>=${M}.${m}.${p}-${pr + } <${M}.${+m + 1}.0-0` + } else { + // ~1.2.3 == >=1.2.3 <1.3.0-0 + ret = `>=${M}.${m}.${p + } <${M}.${+m + 1}.0-0` } - if (value === '}') { - const brace = braces[braces.length - 1]; - - if (opts.nobrace === true || !brace) { - push({ type: 'text', value, output: value }); - continue; - } + debug('tilde return', ret) + return ret + }) +} - let output = ')'; +// ^ --> * (any, kinda silly) +// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0-0 +// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0-0 +// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0-0 +// ^1.2.3 --> >=1.2.3 <2.0.0-0 +// ^1.2.0 --> >=1.2.0 <2.0.0-0 +// ^0.0.1 --> >=0.0.1 <0.0.2-0 +// ^0.1.0 --> >=0.1.0 <0.2.0-0 +const replaceCarets = (comp, options) => { + return comp + .trim() + .split(/\s+/) + .map((c) => replaceCaret(c, options)) + .join(' ') +} - if (brace.dots === true) { - const arr = tokens.slice(); - const range = []; +const replaceCaret = (comp, options) => { + debug('caret', comp, options) + const r = options.loose ? re[t.CARETLOOSE] : re[t.CARET] + const z = options.includePrerelease ? '-0' : '' + return comp.replace(r, (_, M, m, p, pr) => { + debug('caret', comp, _, M, m, p, pr) + let ret - for (let i = arr.length - 1; i >= 0; i--) { - tokens.pop(); - if (arr[i].type === 'brace') { - break; - } - if (arr[i].type !== 'dots') { - range.unshift(arr[i].value); - } + if (isX(M)) { + ret = '' + } else if (isX(m)) { + ret = `>=${M}.0.0${z} <${+M + 1}.0.0-0` + } else if (isX(p)) { + if (M === '0') { + ret = `>=${M}.${m}.0${z} <${M}.${+m + 1}.0-0` + } else { + ret = `>=${M}.${m}.0${z} <${+M + 1}.0.0-0` + } + } else if (pr) { + debug('replaceCaret pr', pr) + if (M === '0') { + if (m === '0') { + ret = `>=${M}.${m}.${p}-${pr + } <${M}.${m}.${+p + 1}-0` + } else { + ret = `>=${M}.${m}.${p}-${pr + } <${M}.${+m + 1}.0-0` } - - output = expandRange(range, opts); - state.backtrack = true; + } else { + ret = `>=${M}.${m}.${p}-${pr + } <${+M + 1}.0.0-0` } - - if (brace.comma !== true && brace.dots !== true) { - const out = state.output.slice(0, brace.outputIndex); - const toks = state.tokens.slice(brace.tokensIndex); - brace.value = brace.output = '\\{'; - value = output = '\\}'; - state.output = out; - for (const t of toks) { - state.output += (t.output || t.value); + } else { + debug('no pr') + if (M === '0') { + if (m === '0') { + ret = `>=${M}.${m}.${p + }${z} <${M}.${m}.${+p + 1}-0` + } else { + ret = `>=${M}.${m}.${p + }${z} <${M}.${+m + 1}.0-0` } + } else { + ret = `>=${M}.${m}.${p + } <${+M + 1}.0.0-0` } - - push({ type: 'brace', value, output }); - decrement('braces'); - braces.pop(); - continue; } - /** - * Pipes - */ - - if (value === '|') { - if (extglobs.length > 0) { - extglobs[extglobs.length - 1].conditions++; - } - push({ type: 'text', value }); - continue; - } + debug('caret return', ret) + return ret + }) +} - /** - * Commas - */ +const replaceXRanges = (comp, options) => { + debug('replaceXRanges', comp, options) + return comp + .split(/\s+/) + .map((c) => replaceXRange(c, options)) + .join(' ') +} - if (value === ',') { - let output = value; +const replaceXRange = (comp, options) => { + comp = comp.trim() + const r = options.loose ? re[t.XRANGELOOSE] : re[t.XRANGE] + return comp.replace(r, (ret, gtlt, M, m, p, pr) => { + debug('xRange', comp, ret, gtlt, M, m, p, pr) + const xM = isX(M) + const xm = xM || isX(m) + const xp = xm || isX(p) + const anyX = xp - const brace = braces[braces.length - 1]; - if (brace && stack[stack.length - 1] === 'braces') { - brace.comma = true; - output = '|'; - } + if (gtlt === '=' && anyX) { + gtlt = '' + } - push({ type: 'comma', value, output }); - continue; - } - - /** - * Slashes - */ - - if (value === '/') { - // if the beginning of the glob is "./", advance the start - // to the current index, and don't add the "./" characters - // to the state. This greatly simplifies lookbehinds when - // checking for BOS characters like "!" and "." (not "./") - if (prev.type === 'dot' && state.index === state.start + 1) { - state.start = state.index + 1; - state.consumed = ''; - state.output = ''; - tokens.pop(); - prev = bos; // reset "prev" to the first token - continue; - } - - push({ type: 'slash', value, output: SLASH_LITERAL }); - continue; - } - - /** - * Dots - */ - - if (value === '.') { - if (state.braces > 0 && prev.type === 'dot') { - if (prev.value === '.') prev.output = DOT_LITERAL; - const brace = braces[braces.length - 1]; - prev.type = 'dots'; - prev.output += value; - prev.value += value; - brace.dots = true; - continue; - } + // if we're including prereleases in the match, then we need + // to fix this to -0, the lowest possible prerelease value + pr = options.includePrerelease ? '-0' : '' - if ((state.braces + state.parens) === 0 && prev.type !== 'bos' && prev.type !== 'slash') { - push({ type: 'text', value, output: DOT_LITERAL }); - continue; + if (xM) { + if (gtlt === '>' || gtlt === '<') { + // nothing is allowed + ret = '<0.0.0-0' + } else { + // nothing is forbidden + ret = '*' } - - push({ type: 'dot', value, output: DOT_LITERAL }); - continue; - } - - /** - * Question marks - */ - - if (value === '?') { - const isGroup = prev && prev.value === '('; - if (!isGroup && opts.noextglob !== true && peek() === '(' && peek(2) !== '?') { - extglobOpen('qmark', value); - continue; + } else if (gtlt && anyX) { + // we know patch is an x, because we have any x at all. + // replace X with 0 + if (xm) { + m = 0 } + p = 0 - if (prev && prev.type === 'paren') { - const next = peek(); - let output = value; - - if (next === '<' && !utils.supportsLookbehinds()) { - throw new Error('Node.js v10 or higher is required for regex lookbehinds'); + if (gtlt === '>') { + // >1 => >=2.0.0 + // >1.2 => >=1.3.0 + gtlt = '>=' + if (xm) { + M = +M + 1 + m = 0 + p = 0 + } else { + m = +m + 1 + p = 0 } - - if ((prev.value === '(' && !/[!=<:]/.test(next)) || (next === '<' && !/<([!=]|\w+>)/.test(remaining()))) { - output = `\\${value}`; + } else if (gtlt === '<=') { + // <=0.7.x is actually <0.8.0, since any 0.7.x should + // pass. Similarly, <=7.x is actually <8.0.0, etc. + gtlt = '<' + if (xm) { + M = +M + 1 + } else { + m = +m + 1 } - - push({ type: 'text', value, output }); - continue; } - if (opts.dot !== true && (prev.type === 'slash' || prev.type === 'bos')) { - push({ type: 'qmark', value, output: QMARK_NO_DOT }); - continue; - } - - push({ type: 'qmark', value, output: QMARK }); - continue; - } - - /** - * Exclamation - */ - - if (value === '!') { - if (opts.noextglob !== true && peek() === '(') { - if (peek(2) !== '?' || !/[!=<:]/.test(peek(3))) { - extglobOpen('negate', value); - continue; - } + if (gtlt === '<') { + pr = '-0' } - if (opts.nonegate !== true && state.index === 0) { - negate(); - continue; - } + ret = `${gtlt + M}.${m}.${p}${pr}` + } else if (xm) { + ret = `>=${M}.0.0${pr} <${+M + 1}.0.0-0` + } else if (xp) { + ret = `>=${M}.${m}.0${pr + } <${M}.${+m + 1}.0-0` } - /** - * Plus - */ + debug('xRange return', ret) - if (value === '+') { - if (opts.noextglob !== true && peek() === '(' && peek(2) !== '?') { - extglobOpen('plus', value); - continue; - } + return ret + }) +} - if ((prev && prev.value === '(') || opts.regex === false) { - push({ type: 'plus', value, output: PLUS_LITERAL }); - continue; - } +// Because * is AND-ed with everything else in the comparator, +// and '' means "any version", just remove the *s entirely. +const replaceStars = (comp, options) => { + debug('replaceStars', comp, options) + // Looseness is ignored here. star is always as loose as it gets! + return comp + .trim() + .replace(re[t.STAR], '') +} - if ((prev && (prev.type === 'bracket' || prev.type === 'paren' || prev.type === 'brace')) || state.parens > 0) { - push({ type: 'plus', value }); - continue; - } +const replaceGTE0 = (comp, options) => { + debug('replaceGTE0', comp, options) + return comp + .trim() + .replace(re[options.includePrerelease ? t.GTE0PRE : t.GTE0], '') +} - push({ type: 'plus', value: PLUS_LITERAL }); - continue; - } +// This function is passed to string.replace(re[t.HYPHENRANGE]) +// M, m, patch, prerelease, build +// 1.2 - 3.4.5 => >=1.2.0 <=3.4.5 +// 1.2.3 - 3.4 => >=1.2.0 <3.5.0-0 Any 3.4.x will do +// 1.2 - 3.4 => >=1.2.0 <3.5.0-0 +// TODO build? +const hyphenReplace = incPr => ($0, + from, fM, fm, fp, fpr, fb, + to, tM, tm, tp, tpr) => { + if (isX(fM)) { + from = '' + } else if (isX(fm)) { + from = `>=${fM}.0.0${incPr ? '-0' : ''}` + } else if (isX(fp)) { + from = `>=${fM}.${fm}.0${incPr ? '-0' : ''}` + } else if (fpr) { + from = `>=${from}` + } else { + from = `>=${from}${incPr ? '-0' : ''}` + } - /** - * Plain text - */ + if (isX(tM)) { + to = '' + } else if (isX(tm)) { + to = `<${+tM + 1}.0.0-0` + } else if (isX(tp)) { + to = `<${tM}.${+tm + 1}.0-0` + } else if (tpr) { + to = `<=${tM}.${tm}.${tp}-${tpr}` + } else if (incPr) { + to = `<${tM}.${tm}.${+tp + 1}-0` + } else { + to = `<=${to}` + } - if (value === '@') { - if (opts.noextglob !== true && peek() === '(' && peek(2) !== '?') { - push({ type: 'at', extglob: true, value, output: '' }); - continue; - } + return `${from} ${to}`.trim() +} - push({ type: 'text', value }); - continue; +const testSet = (set, version, options) => { + for (let i = 0; i < set.length; i++) { + if (!set[i].test(version)) { + return false } + } - /** - * Plain text - */ - - if (value !== '*') { - if (value === '$' || value === '^') { - value = `\\${value}`; + if (version.prerelease.length && !options.includePrerelease) { + // Find the set of versions that are allowed to have prereleases + // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0 + // That should allow `1.2.3-pr.2` to pass. + // However, `1.2.4-alpha.notready` should NOT be allowed, + // even though it's within the range set by the comparators. + for (let i = 0; i < set.length; i++) { + debug(set[i].semver) + if (set[i].semver === Comparator.ANY) { + continue } - const match = REGEX_NON_SPECIAL_CHARS.exec(remaining()); - if (match) { - value += match[0]; - state.index += match[0].length; + if (set[i].semver.prerelease.length > 0) { + const allowed = set[i].semver + if (allowed.major === version.major && + allowed.minor === version.minor && + allowed.patch === version.patch) { + return true + } } - - push({ type: 'text', value }); - continue; } - /** - * Stars - */ - - if (prev && (prev.type === 'globstar' || prev.star === true)) { - prev.type = 'star'; - prev.star = true; - prev.value += value; - prev.output = star; - state.backtrack = true; - state.globstar = true; - consume(value); - continue; - } + // Version has a -pre, but it's not one of the ones we like. + return false + } - let rest = remaining(); - if (opts.noextglob !== true && /^\([^?]/.test(rest)) { - extglobOpen('star', value); - continue; - } + return true +} - if (prev.type === 'star') { - if (opts.noglobstar === true) { - consume(value); - continue; - } - const prior = prev.prev; - const before = prior.prev; - const isStart = prior.type === 'slash' || prior.type === 'bos'; - const afterStar = before && (before.type === 'star' || before.type === 'globstar'); +/***/ }), - if (opts.bash === true && (!isStart || (rest[0] && rest[0] !== '/'))) { - push({ type: 'star', value, output: '' }); - continue; - } +/***/ 1776: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - const isBrace = state.braces > 0 && (prior.type === 'comma' || prior.type === 'brace'); - const isExtglob = extglobs.length && (prior.type === 'pipe' || prior.type === 'paren'); - if (!isStart && prior.type !== 'paren' && !isBrace && !isExtglob) { - push({ type: 'star', value, output: '' }); - continue; - } - // strip consecutive `/**/` - while (rest.slice(0, 3) === '/**') { - const after = input[state.index + 4]; - if (after && after !== '/') { - break; - } - rest = rest.slice(3); - consume('/**', 3); - } - if (prior.type === 'bos' && eos()) { - prev.type = 'globstar'; - prev.value += value; - prev.output = globstar(opts); - state.output = prev.output; - state.globstar = true; - consume(value); - continue; - } +const debug = __nccwpck_require__(8284) +const { MAX_LENGTH, MAX_SAFE_INTEGER } = __nccwpck_require__(470) +const { safeRe: re, t } = __nccwpck_require__(2330) - if (prior.type === 'slash' && prior.prev.type !== 'bos' && !afterStar && eos()) { - state.output = state.output.slice(0, -(prior.output + prev.output).length); - prior.output = `(?:${prior.output}`; +const parseOptions = __nccwpck_require__(207) +const { compareIdentifiers } = __nccwpck_require__(6247) +class SemVer { + constructor (version, options) { + options = parseOptions(options) - prev.type = 'globstar'; - prev.output = globstar(opts) + (opts.strictSlashes ? ')' : '|$)'); - prev.value += value; - state.globstar = true; - state.output += prior.output + prev.output; - consume(value); - continue; + if (version instanceof SemVer) { + if (version.loose === !!options.loose && + version.includePrerelease === !!options.includePrerelease) { + return version + } else { + version = version.version } + } else if (typeof version !== 'string') { + throw new TypeError(`Invalid version. Must be a string. Got type "${typeof version}".`) + } - if (prior.type === 'slash' && prior.prev.type !== 'bos' && rest[0] === '/') { - const end = rest[1] !== void 0 ? '|$' : ''; - - state.output = state.output.slice(0, -(prior.output + prev.output).length); - prior.output = `(?:${prior.output}`; - - prev.type = 'globstar'; - prev.output = `${globstar(opts)}${SLASH_LITERAL}|${SLASH_LITERAL}${end})`; - prev.value += value; - - state.output += prior.output + prev.output; - state.globstar = true; + if (version.length > MAX_LENGTH) { + throw new TypeError( + `version is longer than ${MAX_LENGTH} characters` + ) + } - consume(value + advance()); + debug('SemVer', version, options) + this.options = options + this.loose = !!options.loose + // this isn't actually relevant for versions, but keep it so that we + // don't run into trouble passing this.options around. + this.includePrerelease = !!options.includePrerelease - push({ type: 'slash', value: '/', output: '' }); - continue; - } + const m = version.trim().match(options.loose ? re[t.LOOSE] : re[t.FULL]) - if (prior.type === 'bos' && rest[0] === '/') { - prev.type = 'globstar'; - prev.value += value; - prev.output = `(?:^|${SLASH_LITERAL}|${globstar(opts)}${SLASH_LITERAL})`; - state.output = prev.output; - state.globstar = true; - consume(value + advance()); - push({ type: 'slash', value: '/', output: '' }); - continue; - } + if (!m) { + throw new TypeError(`Invalid Version: ${version}`) + } - // remove single star from output - state.output = state.output.slice(0, -prev.output.length); + this.raw = version - // reset previous token to globstar - prev.type = 'globstar'; - prev.output = globstar(opts); - prev.value += value; + // these are actually numbers + this.major = +m[1] + this.minor = +m[2] + this.patch = +m[3] - // reset output with globstar - state.output += prev.output; - state.globstar = true; - consume(value); - continue; + if (this.major > MAX_SAFE_INTEGER || this.major < 0) { + throw new TypeError('Invalid major version') } - const token = { type: 'star', value, output: star }; - - if (opts.bash === true) { - token.output = '.*?'; - if (prev.type === 'bos' || prev.type === 'slash') { - token.output = nodot + token.output; - } - push(token); - continue; + if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) { + throw new TypeError('Invalid minor version') } - if (prev && (prev.type === 'bracket' || prev.type === 'paren') && opts.regex === true) { - token.output = value; - push(token); - continue; + if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) { + throw new TypeError('Invalid patch version') } - if (state.index === state.start || prev.type === 'slash' || prev.type === 'dot') { - if (prev.type === 'dot') { - state.output += NO_DOT_SLASH; - prev.output += NO_DOT_SLASH; - - } else if (opts.dot === true) { - state.output += NO_DOTS_SLASH; - prev.output += NO_DOTS_SLASH; - - } else { - state.output += nodot; - prev.output += nodot; - } - - if (peek() !== '*') { - state.output += ONE_CHAR; - prev.output += ONE_CHAR; - } + // numberify any prerelease numeric ids + if (!m[4]) { + this.prerelease = [] + } else { + this.prerelease = m[4].split('.').map((id) => { + if (/^[0-9]+$/.test(id)) { + const num = +id + if (num >= 0 && num < MAX_SAFE_INTEGER) { + return num + } + } + return id + }) } - push(token); - } - - while (state.brackets > 0) { - if (opts.strictBrackets === true) throw new SyntaxError(syntaxError('closing', ']')); - state.output = utils.escapeLast(state.output, '['); - decrement('brackets'); - } - - while (state.parens > 0) { - if (opts.strictBrackets === true) throw new SyntaxError(syntaxError('closing', ')')); - state.output = utils.escapeLast(state.output, '('); - decrement('parens'); + this.build = m[5] ? m[5].split('.') : [] + this.format() } - while (state.braces > 0) { - if (opts.strictBrackets === true) throw new SyntaxError(syntaxError('closing', '}')); - state.output = utils.escapeLast(state.output, '{'); - decrement('braces'); + format () { + this.version = `${this.major}.${this.minor}.${this.patch}` + if (this.prerelease.length) { + this.version += `-${this.prerelease.join('.')}` + } + return this.version } - if (opts.strictSlashes !== true && (prev.type === 'star' || prev.type === 'bracket')) { - push({ type: 'maybe_slash', value: '', output: `${SLASH_LITERAL}?` }); + toString () { + return this.version } - // rebuild the output if we had to backtrack at any point - if (state.backtrack === true) { - state.output = ''; - - for (const token of state.tokens) { - state.output += token.output != null ? token.output : token.value; - - if (token.suffix) { - state.output += token.suffix; + compare (other) { + debug('SemVer.compare', this.version, this.options, other) + if (!(other instanceof SemVer)) { + if (typeof other === 'string' && other === this.version) { + return 0 } + other = new SemVer(other, this.options) } - } - - return state; -}; -/** - * Fast paths for creating regular expressions for common glob patterns. - * This can significantly speed up processing and has very little downside - * impact when none of the fast paths match. - */ + if (other.version === this.version) { + return 0 + } -parse.fastpaths = (input, options) => { - const opts = { ...options }; - const max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH; - const len = input.length; - if (len > max) { - throw new SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`); + return this.compareMain(other) || this.comparePre(other) } - input = REPLACEMENTS[input] || input; - const win32 = utils.isWindows(options); - - // create constants based on platform, for windows or posix - const { - DOT_LITERAL, - SLASH_LITERAL, - ONE_CHAR, - DOTS_SLASH, - NO_DOT, - NO_DOTS, - NO_DOTS_SLASH, - STAR, - START_ANCHOR - } = constants.globChars(win32); - - const nodot = opts.dot ? NO_DOTS : NO_DOT; - const slashDot = opts.dot ? NO_DOTS_SLASH : NO_DOT; - const capture = opts.capture ? '' : '?:'; - const state = { negated: false, prefix: '' }; - let star = opts.bash === true ? '.*?' : STAR; + compareMain (other) { + if (!(other instanceof SemVer)) { + other = new SemVer(other, this.options) + } - if (opts.capture) { - star = `(${star})`; + if (this.major < other.major) { + return -1 + } + if (this.major > other.major) { + return 1 + } + if (this.minor < other.minor) { + return -1 + } + if (this.minor > other.minor) { + return 1 + } + if (this.patch < other.patch) { + return -1 + } + if (this.patch > other.patch) { + return 1 + } + return 0 } - const globstar = opts => { - if (opts.noglobstar === true) return star; - return `(${capture}(?:(?!${START_ANCHOR}${opts.dot ? DOTS_SLASH : DOT_LITERAL}).)*?)`; - }; + comparePre (other) { + if (!(other instanceof SemVer)) { + other = new SemVer(other, this.options) + } - const create = str => { - switch (str) { - case '*': - return `${nodot}${ONE_CHAR}${star}`; + // NOT having a prerelease is > having one + if (this.prerelease.length && !other.prerelease.length) { + return -1 + } else if (!this.prerelease.length && other.prerelease.length) { + return 1 + } else if (!this.prerelease.length && !other.prerelease.length) { + return 0 + } - case '.*': - return `${DOT_LITERAL}${ONE_CHAR}${star}`; + let i = 0 + do { + const a = this.prerelease[i] + const b = other.prerelease[i] + debug('prerelease compare', i, a, b) + if (a === undefined && b === undefined) { + return 0 + } else if (b === undefined) { + return 1 + } else if (a === undefined) { + return -1 + } else if (a === b) { + continue + } else { + return compareIdentifiers(a, b) + } + } while (++i) + } - case '*.*': - return `${nodot}${star}${DOT_LITERAL}${ONE_CHAR}${star}`; + compareBuild (other) { + if (!(other instanceof SemVer)) { + other = new SemVer(other, this.options) + } - case '*/*': - return `${nodot}${star}${SLASH_LITERAL}${ONE_CHAR}${slashDot}${star}`; + let i = 0 + do { + const a = this.build[i] + const b = other.build[i] + debug('build compare', i, a, b) + if (a === undefined && b === undefined) { + return 0 + } else if (b === undefined) { + return 1 + } else if (a === undefined) { + return -1 + } else if (a === b) { + continue + } else { + return compareIdentifiers(a, b) + } + } while (++i) + } - case '**': - return nodot + globstar(opts); + // preminor will bump the version up to the next minor release, and immediately + // down to pre-release. premajor and prepatch work the same way. + inc (release, identifier, identifierBase) { + if (release.startsWith('pre')) { + if (!identifier && identifierBase === false) { + throw new Error('invalid increment argument: identifier is empty') + } + // Avoid an invalid semver results + if (identifier) { + const match = `-${identifier}`.match(this.options.loose ? re[t.PRERELEASELOOSE] : re[t.PRERELEASE]) + if (!match || match[1] !== identifier) { + throw new Error(`invalid identifier: ${identifier}`) + } + } + } - case '**/*': - return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${slashDot}${ONE_CHAR}${star}`; + switch (release) { + case 'premajor': + this.prerelease.length = 0 + this.patch = 0 + this.minor = 0 + this.major++ + this.inc('pre', identifier, identifierBase) + break + case 'preminor': + this.prerelease.length = 0 + this.patch = 0 + this.minor++ + this.inc('pre', identifier, identifierBase) + break + case 'prepatch': + // If this is already a prerelease, it will bump to the next version + // drop any prereleases that might already exist, since they are not + // relevant at this point. + this.prerelease.length = 0 + this.inc('patch', identifier, identifierBase) + this.inc('pre', identifier, identifierBase) + break + // If the input is a non-prerelease version, this acts the same as + // prepatch. + case 'prerelease': + if (this.prerelease.length === 0) { + this.inc('patch', identifier, identifierBase) + } + this.inc('pre', identifier, identifierBase) + break + case 'release': + if (this.prerelease.length === 0) { + throw new Error(`version ${this.raw} is not a prerelease`) + } + this.prerelease.length = 0 + break - case '**/*.*': - return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${slashDot}${star}${DOT_LITERAL}${ONE_CHAR}${star}`; + case 'major': + // If this is a pre-major version, bump up to the same major version. + // Otherwise increment major. + // 1.0.0-5 bumps to 1.0.0 + // 1.1.0 bumps to 2.0.0 + if ( + this.minor !== 0 || + this.patch !== 0 || + this.prerelease.length === 0 + ) { + this.major++ + } + this.minor = 0 + this.patch = 0 + this.prerelease = [] + break + case 'minor': + // If this is a pre-minor version, bump up to the same minor version. + // Otherwise increment minor. + // 1.2.0-5 bumps to 1.2.0 + // 1.2.1 bumps to 1.3.0 + if (this.patch !== 0 || this.prerelease.length === 0) { + this.minor++ + } + this.patch = 0 + this.prerelease = [] + break + case 'patch': + // If this is not a pre-release version, it will increment the patch. + // If it is a pre-release it will bump up to the same patch version. + // 1.2.0-5 patches to 1.2.0 + // 1.2.0 patches to 1.2.1 + if (this.prerelease.length === 0) { + this.patch++ + } + this.prerelease = [] + break + // This probably shouldn't be used publicly. + // 1.0.0 'pre' would become 1.0.0-0 which is the wrong direction. + case 'pre': { + const base = Number(identifierBase) ? 1 : 0 - case '**/.*': - return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${DOT_LITERAL}${ONE_CHAR}${star}`; + if (this.prerelease.length === 0) { + this.prerelease = [base] + } else { + let i = this.prerelease.length + while (--i >= 0) { + if (typeof this.prerelease[i] === 'number') { + this.prerelease[i]++ + i = -2 + } + } + if (i === -1) { + // didn't increment anything + if (identifier === this.prerelease.join('.') && identifierBase === false) { + throw new Error('invalid increment argument: identifier already exists') + } + this.prerelease.push(base) + } + } + if (identifier) { + // 1.2.0-beta.1 bumps to 1.2.0-beta.2, + // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0 + let prerelease = [identifier, base] + if (identifierBase === false) { + prerelease = [identifier] + } + if (compareIdentifiers(this.prerelease[0], identifier) === 0) { + if (isNaN(this.prerelease[1])) { + this.prerelease = prerelease + } + } else { + this.prerelease = prerelease + } + } + break + } + default: + throw new Error(`invalid increment argument: ${release}`) + } + this.raw = this.format() + if (this.build.length) { + this.raw += `+${this.build.join('.')}` + } + return this + } +} - default: { - const match = /^(.*?)\.(\w+)$/.exec(str); - if (!match) return; +module.exports = SemVer - const source = create(match[1]); - if (!source) return; - return source + DOT_LITERAL + match[2]; - } - } - }; +/***/ }), - const output = utils.removePrefix(input, state); - let source = create(output); +/***/ 3938: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - if (source && opts.strictSlashes !== true) { - source += `${SLASH_LITERAL}?`; - } - return source; -}; -module.exports = parse; +const parse = __nccwpck_require__(844) +const clean = (version, options) => { + const s = parse(version.trim().replace(/^[=v]+/, ''), options) + return s ? s.version : null +} +module.exports = clean /***/ }), -/***/ 9511: +/***/ 6907: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -const path = __nccwpck_require__(6928); -const scan = __nccwpck_require__(3676); -const parse = __nccwpck_require__(5638); -const utils = __nccwpck_require__(9116); -const constants = __nccwpck_require__(4952); -const isObject = val => val && typeof val === 'object' && !Array.isArray(val); +const eq = __nccwpck_require__(3413) +const neq = __nccwpck_require__(6595) +const gt = __nccwpck_require__(9448) +const gte = __nccwpck_require__(7989) +const lt = __nccwpck_require__(8991) +const lte = __nccwpck_require__(812) -/** - * Creates a matcher function from one or more glob patterns. The - * returned function takes a string to match as its first argument, - * and returns true if the string is a match. The returned matcher - * function also takes a boolean as the second argument that, when true, - * returns an object with additional information. - * - * ```js - * const picomatch = require('picomatch'); - * // picomatch(glob[, options]); - * - * const isMatch = picomatch('*.!(*a)'); - * console.log(isMatch('a.a')); //=> false - * console.log(isMatch('a.b')); //=> true - * ``` - * @name picomatch - * @param {String|Array} `globs` One or more glob patterns. - * @param {Object=} `options` - * @return {Function=} Returns a matcher function. - * @api public - */ +const cmp = (a, op, b, loose) => { + switch (op) { + case '===': + if (typeof a === 'object') { + a = a.version + } + if (typeof b === 'object') { + b = b.version + } + return a === b -const picomatch = (glob, options, returnState = false) => { - if (Array.isArray(glob)) { - const fns = glob.map(input => picomatch(input, options, returnState)); - const arrayMatcher = str => { - for (const isMatch of fns) { - const state = isMatch(str); - if (state) return state; + case '!==': + if (typeof a === 'object') { + a = a.version } - return false; - }; - return arrayMatcher; - } + if (typeof b === 'object') { + b = b.version + } + return a !== b - const isState = isObject(glob) && glob.tokens && glob.input; + case '': + case '=': + case '==': + return eq(a, b, loose) - if (glob === '' || (typeof glob !== 'string' && !isState)) { - throw new TypeError('Expected pattern to be a non-empty string'); - } + case '!=': + return neq(a, b, loose) - const opts = options || {}; - const posix = utils.isWindows(options); - const regex = isState - ? picomatch.compileRe(glob, options) - : picomatch.makeRe(glob, options, false, true); + case '>': + return gt(a, b, loose) - const state = regex.state; - delete regex.state; + case '>=': + return gte(a, b, loose) - let isIgnored = () => false; - if (opts.ignore) { - const ignoreOpts = { ...options, ignore: null, onMatch: null, onResult: null }; - isIgnored = picomatch(opts.ignore, ignoreOpts, returnState); - } + case '<': + return lt(a, b, loose) - const matcher = (input, returnObject = false) => { - const { isMatch, match, output } = picomatch.test(input, regex, options, { glob, posix }); - const result = { glob, state, regex, posix, input, output, match, isMatch }; + case '<=': + return lte(a, b, loose) - if (typeof opts.onResult === 'function') { - opts.onResult(result); - } + default: + throw new TypeError(`Invalid operator: ${op}`) + } +} +module.exports = cmp - if (isMatch === false) { - result.isMatch = false; - return returnObject ? result : false; - } - if (isIgnored(input)) { - if (typeof opts.onIgnore === 'function') { - opts.onIgnore(result); - } - result.isMatch = false; - return returnObject ? result : false; - } +/***/ }), - if (typeof opts.onMatch === 'function') { - opts.onMatch(result); - } - return returnObject ? result : true; - }; +/***/ 3086: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - if (returnState) { - matcher.state = state; - } - return matcher; -}; -/** - * Test `input` with the given `regex`. This is used by the main - * `picomatch()` function to test the input string. - * - * ```js - * const picomatch = require('picomatch'); - * // picomatch.test(input, regex[, options]); - * - * console.log(picomatch.test('foo/bar', /^(?:([^/]*?)\/([^/]*?))$/)); - * // { isMatch: true, match: [ 'foo/', 'foo', 'bar' ], output: 'foo/bar' } - * ``` - * @param {String} `input` String to test. - * @param {RegExp} `regex` - * @return {Object} Returns an object with matching info. - * @api public - */ +const SemVer = __nccwpck_require__(1776) +const parse = __nccwpck_require__(844) +const { safeRe: re, t } = __nccwpck_require__(2330) -picomatch.test = (input, regex, options, { glob, posix } = {}) => { - if (typeof input !== 'string') { - throw new TypeError('Expected input to be a string'); +const coerce = (version, options) => { + if (version instanceof SemVer) { + return version } - if (input === '') { - return { isMatch: false, output: '' }; + if (typeof version === 'number') { + version = String(version) } - const opts = options || {}; - const format = opts.format || (posix ? utils.toPosixSlashes : null); - let match = input === glob; - let output = (match && format) ? format(input) : input; - - if (match === false) { - output = format ? format(input) : input; - match = output === glob; + if (typeof version !== 'string') { + return null } - if (match === false || opts.capture === true) { - if (opts.matchBase === true || opts.basename === true) { - match = picomatch.matchBase(input, regex, options, posix); - } else { - match = regex.exec(output); + options = options || {} + + let match = null + if (!options.rtl) { + match = version.match(options.includePrerelease ? re[t.COERCEFULL] : re[t.COERCE]) + } else { + // Find the right-most coercible string that does not share + // a terminus with a more left-ward coercible string. + // Eg, '1.2.3.4' wants to coerce '2.3.4', not '3.4' or '4' + // With includePrerelease option set, '1.2.3.4-rc' wants to coerce '2.3.4-rc', not '2.3.4' + // + // Walk through the string checking with a /g regexp + // Manually set the index so as to pick up overlapping matches. + // Stop when we get a match that ends at the string end, since no + // coercible string can be more right-ward without the same terminus. + const coerceRtlRegex = options.includePrerelease ? re[t.COERCERTLFULL] : re[t.COERCERTL] + let next + while ((next = coerceRtlRegex.exec(version)) && + (!match || match.index + match[0].length !== version.length) + ) { + if (!match || + next.index + next[0].length !== match.index + match[0].length) { + match = next + } + coerceRtlRegex.lastIndex = next.index + next[1].length + next[2].length } + // leave it in a clean state + coerceRtlRegex.lastIndex = -1 } - return { isMatch: Boolean(match), match, output }; -}; + if (match === null) { + return null + } -/** - * Match the basename of a filepath. - * - * ```js - * const picomatch = require('picomatch'); - * // picomatch.matchBase(input, glob[, options]); - * console.log(picomatch.matchBase('foo/bar.js', '*.js'); // true - * ``` - * @param {String} `input` String to test. - * @param {RegExp|String} `glob` Glob pattern or regex created by [.makeRe](#makeRe). - * @return {Boolean} - * @api public - */ + const major = match[2] + const minor = match[3] || '0' + const patch = match[4] || '0' + const prerelease = options.includePrerelease && match[5] ? `-${match[5]}` : '' + const build = options.includePrerelease && match[6] ? `+${match[6]}` : '' -picomatch.matchBase = (input, glob, options, posix = utils.isWindows(options)) => { - const regex = glob instanceof RegExp ? glob : picomatch.makeRe(glob, options); - return regex.test(path.basename(input)); -}; + return parse(`${major}.${minor}.${patch}${prerelease}${build}`, options) +} +module.exports = coerce -/** - * Returns true if **any** of the given glob `patterns` match the specified `string`. - * - * ```js - * const picomatch = require('picomatch'); - * // picomatch.isMatch(string, patterns[, options]); - * - * console.log(picomatch.isMatch('a.a', ['b.*', '*.a'])); //=> true - * console.log(picomatch.isMatch('a.a', 'b.*')); //=> false - * ``` - * @param {String|Array} str The string to test. - * @param {String|Array} patterns One or more glob patterns to use for matching. - * @param {Object} [options] See available [options](#options). - * @return {Boolean} Returns true if any patterns match `str` - * @api public - */ -picomatch.isMatch = (str, patterns, options) => picomatch(patterns, options)(str); +/***/ }), -/** - * Parse a glob pattern to create the source string for a regular - * expression. - * - * ```js - * const picomatch = require('picomatch'); - * const result = picomatch.parse(pattern[, options]); - * ``` - * @param {String} `pattern` - * @param {Object} `options` - * @return {Object} Returns an object with useful properties and output to be used as a regex source string. - * @api public - */ +/***/ 2761: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -picomatch.parse = (pattern, options) => { - if (Array.isArray(pattern)) return pattern.map(p => picomatch.parse(p, options)); - return parse(pattern, { ...options, fastpaths: false }); -}; -/** - * Scan a glob pattern to separate the pattern into segments. - * - * ```js - * const picomatch = require('picomatch'); - * // picomatch.scan(input[, options]); - * - * const result = picomatch.scan('!./foo/*.js'); - * console.log(result); - * { prefix: '!./', - * input: '!./foo/*.js', - * start: 3, - * base: 'foo', - * glob: '*.js', - * isBrace: false, - * isBracket: false, - * isGlob: true, - * isExtglob: false, - * isGlobstar: false, - * negated: true } - * ``` - * @param {String} `input` Glob pattern to scan. - * @param {Object} `options` - * @return {Object} Returns an object with - * @api public - */ -picomatch.scan = (input, options) => scan(input, options); +const SemVer = __nccwpck_require__(1776) +const compareBuild = (a, b, loose) => { + const versionA = new SemVer(a, loose) + const versionB = new SemVer(b, loose) + return versionA.compare(versionB) || versionA.compareBuild(versionB) +} +module.exports = compareBuild -/** - * Compile a regular expression from the `state` object returned by the - * [parse()](#parse) method. - * - * @param {Object} `state` - * @param {Object} `options` - * @param {Boolean} `returnOutput` Intended for implementors, this argument allows you to return the raw output from the parser. - * @param {Boolean} `returnState` Adds the state to a `state` property on the returned regex. Useful for implementors and debugging. - * @return {RegExp} - * @api public - */ -picomatch.compileRe = (state, options, returnOutput = false, returnState = false) => { - if (returnOutput === true) { - return state.output; - } +/***/ }), - const opts = options || {}; - const prepend = opts.contains ? '' : '^'; - const append = opts.contains ? '' : '$'; +/***/ 9463: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - let source = `${prepend}(?:${state.output})${append}`; - if (state && state.negated === true) { - source = `^(?!${source}).*$`; - } - const regex = picomatch.toRegex(source, options); - if (returnState === true) { - regex.state = state; + +const compare = __nccwpck_require__(7180) +const compareLoose = (a, b) => compare(a, b, true) +module.exports = compareLoose + + +/***/ }), + +/***/ 7180: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + + + +const SemVer = __nccwpck_require__(1776) +const compare = (a, b, loose) => + new SemVer(a, loose).compare(new SemVer(b, loose)) + +module.exports = compare + + +/***/ }), + +/***/ 4652: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + + + +const parse = __nccwpck_require__(844) + +const diff = (version1, version2) => { + const v1 = parse(version1, null, true) + const v2 = parse(version2, null, true) + const comparison = v1.compare(v2) + + if (comparison === 0) { + return null } - return regex; -}; + const v1Higher = comparison > 0 + const highVersion = v1Higher ? v1 : v2 + const lowVersion = v1Higher ? v2 : v1 + const highHasPre = !!highVersion.prerelease.length + const lowHasPre = !!lowVersion.prerelease.length -/** - * Create a regular expression from a parsed glob pattern. - * - * ```js - * const picomatch = require('picomatch'); - * const state = picomatch.parse('*.js'); - * // picomatch.compileRe(state[, options]); - * - * console.log(picomatch.compileRe(state)); - * //=> /^(?:(?!\.)(?=.)[^/]*?\.js)$/ - * ``` - * @param {String} `state` The object returned from the `.parse` method. - * @param {Object} `options` - * @param {Boolean} `returnOutput` Implementors may use this argument to return the compiled output, instead of a regular expression. This is not exposed on the options to prevent end-users from mutating the result. - * @param {Boolean} `returnState` Implementors may use this argument to return the state from the parsed glob with the returned regular expression. - * @return {RegExp} Returns a regex created from the given pattern. - * @api public - */ + if (lowHasPre && !highHasPre) { + // Going from prerelease -> no prerelease requires some special casing -picomatch.makeRe = (input, options = {}, returnOutput = false, returnState = false) => { - if (!input || typeof input !== 'string') { - throw new TypeError('Expected a non-empty string'); + // If the low version has only a major, then it will always be a major + // Some examples: + // 1.0.0-1 -> 1.0.0 + // 1.0.0-1 -> 1.1.1 + // 1.0.0-1 -> 2.0.0 + if (!lowVersion.patch && !lowVersion.minor) { + return 'major' + } + + // If the main part has no difference + if (lowVersion.compareMain(highVersion) === 0) { + if (lowVersion.minor && !lowVersion.patch) { + return 'minor' + } + return 'patch' + } } - let parsed = { negated: false, fastpaths: true }; + // add the `pre` prefix if we are going to a prerelease version + const prefix = highHasPre ? 'pre' : '' - if (options.fastpaths !== false && (input[0] === '.' || input[0] === '*')) { - parsed.output = parse.fastpaths(input, options); + if (v1.major !== v2.major) { + return prefix + 'major' } - if (!parsed.output) { - parsed = parse(input, options); + if (v1.minor !== v2.minor) { + return prefix + 'minor' } - return picomatch.compileRe(parsed, options, returnOutput, returnState); -}; + if (v1.patch !== v2.patch) { + return prefix + 'patch' + } -/** - * Create a regular expression from the given regex source string. - * - * ```js - * const picomatch = require('picomatch'); - * // picomatch.toRegex(source[, options]); - * - * const { output } = picomatch.parse('*.js'); - * console.log(picomatch.toRegex(output)); - * //=> /^(?:(?!\.)(?=.)[^/]*?\.js)$/ - * ``` - * @param {String} `source` Regular expression source string. - * @param {Object} `options` - * @return {RegExp} - * @api public - */ + // high and low are prereleases + return 'prerelease' +} -picomatch.toRegex = (source, options) => { - try { - const opts = options || {}; - return new RegExp(source, opts.flags || (opts.nocase ? 'i' : '')); - } catch (err) { - if (options && options.debug === true) throw err; - return /$^/; - } -}; +module.exports = diff -/** - * Picomatch constants. - * @return {Object} - */ -picomatch.constants = constants; +/***/ }), -/** - * Expose "picomatch" - */ +/***/ 3413: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -module.exports = picomatch; + + +const compare = __nccwpck_require__(7180) +const eq = (a, b, loose) => compare(a, b, loose) === 0 +module.exports = eq /***/ }), -/***/ 3676: +/***/ 9448: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -const utils = __nccwpck_require__(9116); -const { - CHAR_ASTERISK, /* * */ - CHAR_AT, /* @ */ - CHAR_BACKWARD_SLASH, /* \ */ - CHAR_COMMA, /* , */ - CHAR_DOT, /* . */ - CHAR_EXCLAMATION_MARK, /* ! */ - CHAR_FORWARD_SLASH, /* / */ - CHAR_LEFT_CURLY_BRACE, /* { */ - CHAR_LEFT_PARENTHESES, /* ( */ - CHAR_LEFT_SQUARE_BRACKET, /* [ */ - CHAR_PLUS, /* + */ - CHAR_QUESTION_MARK, /* ? */ - CHAR_RIGHT_CURLY_BRACE, /* } */ - CHAR_RIGHT_PARENTHESES, /* ) */ - CHAR_RIGHT_SQUARE_BRACKET /* ] */ -} = __nccwpck_require__(4952); +const compare = __nccwpck_require__(7180) +const gt = (a, b, loose) => compare(a, b, loose) > 0 +module.exports = gt -const isPathSeparator = code => { - return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH; -}; -const depth = token => { - if (token.isPrefix !== true) { - token.depth = token.isGlobstar ? Infinity : 1; - } -}; +/***/ }), -/** - * Quickly scans a glob pattern and returns an object with a handful of - * useful properties, like `isGlob`, `path` (the leading non-glob, if it exists), - * `glob` (the actual pattern), `negated` (true if the path starts with `!` but not - * with `!(`) and `negatedExtglob` (true if the path starts with `!(`). - * - * ```js - * const pm = require('picomatch'); - * console.log(pm.scan('foo/bar/*.js')); - * { isGlob: true, input: 'foo/bar/*.js', base: 'foo/bar', glob: '*.js' } - * ``` - * @param {String} `str` - * @param {Object} `options` - * @return {Object} Returns an object with tokens and regex source string. - * @api public - */ +/***/ 7989: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -const scan = (input, options) => { - const opts = options || {}; - const length = input.length - 1; - const scanToEnd = opts.parts === true || opts.scanToEnd === true; - const slashes = []; - const tokens = []; - const parts = []; - let str = input; - let index = -1; - let start = 0; - let lastIndex = 0; - let isBrace = false; - let isBracket = false; - let isGlob = false; - let isExtglob = false; - let isGlobstar = false; - let braceEscaped = false; - let backslashes = false; - let negated = false; - let negatedExtglob = false; - let finished = false; - let braces = 0; - let prev; - let code; - let token = { value: '', depth: 0, isGlob: false }; +const compare = __nccwpck_require__(7180) +const gte = (a, b, loose) => compare(a, b, loose) >= 0 +module.exports = gte - const eos = () => index >= length; - const peek = () => str.charCodeAt(index + 1); - const advance = () => { - prev = code; - return str.charCodeAt(++index); - }; - while (index < length) { - code = advance(); - let next; +/***/ }), - if (code === CHAR_BACKWARD_SLASH) { - backslashes = token.backslashes = true; - code = advance(); +/***/ 795: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - if (code === CHAR_LEFT_CURLY_BRACE) { - braceEscaped = true; - } - continue; - } - if (braceEscaped === true || code === CHAR_LEFT_CURLY_BRACE) { - braces++; - while (eos() !== true && (code = advance())) { - if (code === CHAR_BACKWARD_SLASH) { - backslashes = token.backslashes = true; - advance(); - continue; - } +const SemVer = __nccwpck_require__(1776) - if (code === CHAR_LEFT_CURLY_BRACE) { - braces++; - continue; - } +const inc = (version, release, options, identifier, identifierBase) => { + if (typeof (options) === 'string') { + identifierBase = identifier + identifier = options + options = undefined + } - if (braceEscaped !== true && code === CHAR_DOT && (code = advance()) === CHAR_DOT) { - isBrace = token.isBrace = true; - isGlob = token.isGlob = true; - finished = true; + try { + return new SemVer( + version instanceof SemVer ? version.version : version, + options + ).inc(release, identifier, identifierBase).version + } catch (er) { + return null + } +} +module.exports = inc - if (scanToEnd === true) { - continue; - } - break; - } +/***/ }), - if (braceEscaped !== true && code === CHAR_COMMA) { - isBrace = token.isBrace = true; - isGlob = token.isGlob = true; - finished = true; +/***/ 8991: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - if (scanToEnd === true) { - continue; - } - break; - } - if (code === CHAR_RIGHT_CURLY_BRACE) { - braces--; +const compare = __nccwpck_require__(7180) +const lt = (a, b, loose) => compare(a, b, loose) < 0 +module.exports = lt - if (braces === 0) { - braceEscaped = false; - isBrace = token.isBrace = true; - finished = true; - break; - } - } - } - if (scanToEnd === true) { - continue; - } +/***/ }), - break; - } +/***/ 812: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - if (code === CHAR_FORWARD_SLASH) { - slashes.push(index); - tokens.push(token); - token = { value: '', depth: 0, isGlob: false }; - if (finished === true) continue; - if (prev === CHAR_DOT && index === (start + 1)) { - start += 2; - continue; - } - lastIndex = index + 1; - continue; - } +const compare = __nccwpck_require__(7180) +const lte = (a, b, loose) => compare(a, b, loose) <= 0 +module.exports = lte - if (opts.noext !== true) { - const isExtglobChar = code === CHAR_PLUS - || code === CHAR_AT - || code === CHAR_ASTERISK - || code === CHAR_QUESTION_MARK - || code === CHAR_EXCLAMATION_MARK; - if (isExtglobChar === true && peek() === CHAR_LEFT_PARENTHESES) { - isGlob = token.isGlob = true; - isExtglob = token.isExtglob = true; - finished = true; - if (code === CHAR_EXCLAMATION_MARK && index === start) { - negatedExtglob = true; - } +/***/ }), - if (scanToEnd === true) { - while (eos() !== true && (code = advance())) { - if (code === CHAR_BACKWARD_SLASH) { - backslashes = token.backslashes = true; - code = advance(); - continue; - } +/***/ 6366: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - if (code === CHAR_RIGHT_PARENTHESES) { - isGlob = token.isGlob = true; - finished = true; - break; - } - } - continue; - } - break; - } - } - if (code === CHAR_ASTERISK) { - if (prev === CHAR_ASTERISK) isGlobstar = token.isGlobstar = true; - isGlob = token.isGlob = true; - finished = true; - if (scanToEnd === true) { - continue; - } - break; - } +const SemVer = __nccwpck_require__(1776) +const major = (a, loose) => new SemVer(a, loose).major +module.exports = major - if (code === CHAR_QUESTION_MARK) { - isGlob = token.isGlob = true; - finished = true; - if (scanToEnd === true) { - continue; - } - break; - } +/***/ }), - if (code === CHAR_LEFT_SQUARE_BRACKET) { - while (eos() !== true && (next = advance())) { - if (next === CHAR_BACKWARD_SLASH) { - backslashes = token.backslashes = true; - advance(); - continue; - } +/***/ 4410: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - if (next === CHAR_RIGHT_SQUARE_BRACKET) { - isBracket = token.isBracket = true; - isGlob = token.isGlob = true; - finished = true; - break; - } - } - if (scanToEnd === true) { - continue; - } - break; - } +const SemVer = __nccwpck_require__(1776) +const minor = (a, loose) => new SemVer(a, loose).minor +module.exports = minor - if (opts.nonegate !== true && code === CHAR_EXCLAMATION_MARK && index === start) { - negated = token.negated = true; - start++; - continue; - } - if (opts.noparen !== true && code === CHAR_LEFT_PARENTHESES) { - isGlob = token.isGlob = true; +/***/ }), - if (scanToEnd === true) { - while (eos() !== true && (code = advance())) { - if (code === CHAR_LEFT_PARENTHESES) { - backslashes = token.backslashes = true; - code = advance(); - continue; - } +/***/ 6595: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - if (code === CHAR_RIGHT_PARENTHESES) { - finished = true; - break; - } - } - continue; - } - break; - } - if (isGlob === true) { - finished = true; - if (scanToEnd === true) { - continue; - } +const compare = __nccwpck_require__(7180) +const neq = (a, b, loose) => compare(a, b, loose) !== 0 +module.exports = neq - break; - } - } - if (opts.noext === true) { - isExtglob = false; - isGlob = false; - } +/***/ }), - let base = str; - let prefix = ''; - let glob = ''; +/***/ 844: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - if (start > 0) { - prefix = str.slice(0, start); - str = str.slice(start); - lastIndex -= start; - } - if (base && isGlob === true && lastIndex > 0) { - base = str.slice(0, lastIndex); - glob = str.slice(lastIndex); - } else if (isGlob === true) { - base = ''; - glob = str; - } else { - base = str; - } - if (base && base !== '' && base !== '/' && base !== str) { - if (isPathSeparator(base.charCodeAt(base.length - 1))) { - base = base.slice(0, -1); +const SemVer = __nccwpck_require__(1776) +const parse = (version, options, throwErrors = false) => { + if (version instanceof SemVer) { + return version + } + try { + return new SemVer(version, options) + } catch (er) { + if (!throwErrors) { + return null } + throw er } +} - if (opts.unescape === true) { - if (glob) glob = utils.removeBackslashes(glob); +module.exports = parse - if (base && backslashes === true) { - base = utils.removeBackslashes(base); - } - } - const state = { - prefix, - input, - start, - base, - glob, - isBrace, - isBracket, - isGlob, - isExtglob, - isGlobstar, - negated, - negatedExtglob - }; +/***/ }), - if (opts.tokens === true) { - state.maxDepth = 0; - if (!isPathSeparator(code)) { - tokens.push(token); - } - state.tokens = tokens; - } +/***/ 1817: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - if (opts.parts === true || opts.tokens === true) { - let prevIndex; - for (let idx = 0; idx < slashes.length; idx++) { - const n = prevIndex ? prevIndex + 1 : start; - const i = slashes[idx]; - const value = input.slice(n, i); - if (opts.tokens) { - if (idx === 0 && start !== 0) { - tokens[idx].isPrefix = true; - tokens[idx].value = prefix; - } else { - tokens[idx].value = value; - } - depth(tokens[idx]); - state.maxDepth += tokens[idx].depth; - } - if (idx !== 0 || value !== '') { - parts.push(value); - } - prevIndex = i; - } - if (prevIndex && prevIndex + 1 < input.length) { - const value = input.slice(prevIndex + 1); - parts.push(value); +const SemVer = __nccwpck_require__(1776) +const patch = (a, loose) => new SemVer(a, loose).patch +module.exports = patch - if (opts.tokens) { - tokens[tokens.length - 1].value = value; - depth(tokens[tokens.length - 1]); - state.maxDepth += tokens[tokens.length - 1].depth; - } - } - state.slashes = slashes; - state.parts = parts; - } +/***/ }), - return state; -}; +/***/ 9877: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -module.exports = scan; + + +const parse = __nccwpck_require__(844) +const prerelease = (version, options) => { + const parsed = parse(version, options) + return (parsed && parsed.prerelease.length) ? parsed.prerelease : null +} +module.exports = prerelease /***/ }), -/***/ 9116: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { +/***/ 4486: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -const path = __nccwpck_require__(6928); -const win32 = process.platform === 'win32'; -const { - REGEX_BACKSLASH, - REGEX_REMOVE_BACKSLASH, - REGEX_SPECIAL_CHARS, - REGEX_SPECIAL_CHARS_GLOBAL -} = __nccwpck_require__(4952); +const compare = __nccwpck_require__(7180) +const rcompare = (a, b, loose) => compare(b, a, loose) +module.exports = rcompare -exports.isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val); -exports.hasRegexChars = str => REGEX_SPECIAL_CHARS.test(str); -exports.isRegexChar = str => str.length === 1 && exports.hasRegexChars(str); -exports.escapeRegex = str => str.replace(REGEX_SPECIAL_CHARS_GLOBAL, '\\$1'); -exports.toPosixSlashes = str => str.replace(REGEX_BACKSLASH, '/'); -exports.removeBackslashes = str => { - return str.replace(REGEX_REMOVE_BACKSLASH, match => { - return match === '\\' ? '' : match; - }); -}; +/***/ }), -exports.supportsLookbehinds = () => { - const segs = process.version.slice(1).split('.').map(Number); - if (segs.length === 3 && segs[0] >= 9 || (segs[0] === 8 && segs[1] >= 10)) { - return true; - } - return false; -}; +/***/ 6841: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -exports.isWindows = options => { - if (options && typeof options.windows === 'boolean') { - return options.windows; - } - return win32 === true || path.sep === '\\'; -}; -exports.escapeLast = (input, char, lastIdx) => { - const idx = input.lastIndexOf(char, lastIdx); - if (idx === -1) return input; - if (input[idx - 1] === '\\') return exports.escapeLast(input, char, idx - 1); - return `${input.slice(0, idx)}\\${input.slice(idx)}`; -}; -exports.removePrefix = (input, state = {}) => { - let output = input; - if (output.startsWith('./')) { - output = output.slice(2); - state.prefix = './'; - } - return output; -}; +const compareBuild = __nccwpck_require__(2761) +const rsort = (list, loose) => list.sort((a, b) => compareBuild(b, a, loose)) +module.exports = rsort -exports.wrapOutput = (input, state = {}, options = {}) => { - const prepend = options.contains ? '' : '^'; - const append = options.contains ? '' : '$'; - let output = `${prepend}(?:${input})${append}`; - if (state.negated === true) { - output = `(?:^(?!${output}).*$)`; +/***/ }), + +/***/ 8370: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + + + +const Range = __nccwpck_require__(1699) +const satisfies = (version, range, options) => { + try { + range = new Range(range, options) + } catch (er) { + return false } - return output; -}; + return range.test(version) +} +module.exports = satisfies + + +/***/ }), + +/***/ 4019: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + + + +const compareBuild = __nccwpck_require__(2761) +const sort = (list, loose) => list.sort((a, b) => compareBuild(a, b, loose)) +module.exports = sort + + +/***/ }), + +/***/ 6613: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + + + +const parse = __nccwpck_require__(844) +const valid = (version, options) => { + const v = parse(version, options) + return v ? v.version : null +} +module.exports = valid /***/ }), -/***/ 6230: +/***/ 1737: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + + + +// just pre-load all the stuff that index.js lazily exports +const internalRe = __nccwpck_require__(2330) +const constants = __nccwpck_require__(470) +const SemVer = __nccwpck_require__(1776) +const identifiers = __nccwpck_require__(6247) +const parse = __nccwpck_require__(844) +const valid = __nccwpck_require__(6613) +const clean = __nccwpck_require__(3938) +const inc = __nccwpck_require__(795) +const diff = __nccwpck_require__(4652) +const major = __nccwpck_require__(6366) +const minor = __nccwpck_require__(4410) +const patch = __nccwpck_require__(1817) +const prerelease = __nccwpck_require__(9877) +const compare = __nccwpck_require__(7180) +const rcompare = __nccwpck_require__(4486) +const compareLoose = __nccwpck_require__(9463) +const compareBuild = __nccwpck_require__(2761) +const sort = __nccwpck_require__(4019) +const rsort = __nccwpck_require__(6841) +const gt = __nccwpck_require__(9448) +const lt = __nccwpck_require__(8991) +const eq = __nccwpck_require__(3413) +const neq = __nccwpck_require__(6595) +const gte = __nccwpck_require__(7989) +const lte = __nccwpck_require__(812) +const cmp = __nccwpck_require__(6907) +const coerce = __nccwpck_require__(3086) +const Comparator = __nccwpck_require__(5388) +const Range = __nccwpck_require__(1699) +const satisfies = __nccwpck_require__(8370) +const toComparators = __nccwpck_require__(2816) +const maxSatisfying = __nccwpck_require__(2840) +const minSatisfying = __nccwpck_require__(7586) +const minVersion = __nccwpck_require__(937) +const validRange = __nccwpck_require__(1694) +const outside = __nccwpck_require__(703) +const gtr = __nccwpck_require__(6663) +const ltr = __nccwpck_require__(6002) +const intersects = __nccwpck_require__(896) +const simplifyRange = __nccwpck_require__(3393) +const subset = __nccwpck_require__(6652) +module.exports = { + parse, + valid, + clean, + inc, + diff, + major, + minor, + patch, + prerelease, + compare, + rcompare, + compareLoose, + compareBuild, + sort, + rsort, + gt, + lt, + eq, + neq, + gte, + lte, + cmp, + coerce, + Comparator, + Range, + satisfies, + toComparators, + maxSatisfying, + minSatisfying, + minVersion, + validRange, + outside, + gtr, + ltr, + intersects, + simplifyRange, + subset, + SemVer, + re: internalRe.re, + src: internalRe.src, + tokens: internalRe.t, + SEMVER_SPEC_VERSION: constants.SEMVER_SPEC_VERSION, + RELEASE_TYPES: constants.RELEASE_TYPES, + compareIdentifiers: identifiers.compareIdentifiers, + rcompareIdentifiers: identifiers.rcompareIdentifiers, +} + + +/***/ }), + +/***/ 470: /***/ ((module) => { -/*! queue-microtask. MIT License. Feross Aboukhadijeh */ -let promise -module.exports = typeof queueMicrotask === 'function' - ? queueMicrotask.bind(typeof window !== 'undefined' ? window : global) - // reuse resolved promise, and allocate it lazily - : cb => (promise || (promise = Promise.resolve())) - .then(cb) - .catch(err => setTimeout(() => { throw err }, 0)) + +// Note: this is the semver.org version of the spec that it implements +// Not necessarily the package version of this code. +const SEMVER_SPEC_VERSION = '2.0.0' + +const MAX_LENGTH = 256 +const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || +/* istanbul ignore next */ 9007199254740991 + +// Max safe segment length for coercion. +const MAX_SAFE_COMPONENT_LENGTH = 16 + +// Max safe length for a build identifier. The max length minus 6 characters for +// the shortest version with a build 0.0.0+BUILD. +const MAX_SAFE_BUILD_LENGTH = MAX_LENGTH - 6 + +const RELEASE_TYPES = [ + 'major', + 'premajor', + 'minor', + 'preminor', + 'patch', + 'prepatch', + 'prerelease', +] + +module.exports = { + MAX_LENGTH, + MAX_SAFE_COMPONENT_LENGTH, + MAX_SAFE_BUILD_LENGTH, + MAX_SAFE_INTEGER, + RELEASE_TYPES, + SEMVER_SPEC_VERSION, + FLAG_INCLUDE_PRERELEASE: 0b001, + FLAG_LOOSE: 0b010, +} /***/ }), -/***/ 3070: +/***/ 8284: /***/ ((module) => { -"use strict"; -function reusify (Constructor) { - var head = new Constructor() - var tail = head +const debug = ( + typeof process === 'object' && + process.env && + process.env.NODE_DEBUG && + /\bsemver\b/i.test(process.env.NODE_DEBUG) +) ? (...args) => console.error('SEMVER', ...args) + : () => {} - function get () { - var current = head +module.exports = debug - if (current.next) { - head = current.next - } else { - head = new Constructor() - tail = head - } - current.next = null +/***/ }), - return current - } +/***/ 6247: +/***/ ((module) => { - function release (obj) { - tail.next = obj - tail = obj + + +const numeric = /^[0-9]+$/ +const compareIdentifiers = (a, b) => { + if (typeof a === 'number' && typeof b === 'number') { + return a === b ? 0 : a < b ? -1 : 1 } - return { - get: get, - release: release + const anum = numeric.test(a) + const bnum = numeric.test(b) + + if (anum && bnum) { + a = +a + b = +b } + + return a === b ? 0 + : (anum && !bnum) ? -1 + : (bnum && !anum) ? 1 + : a < b ? -1 + : 1 } -module.exports = reusify +const rcompareIdentifiers = (a, b) => compareIdentifiers(b, a) + +module.exports = { + compareIdentifiers, + rcompareIdentifiers, +} /***/ }), -/***/ 5172: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -/*! run-parallel. MIT License. Feross Aboukhadijeh */ -module.exports = runParallel +/***/ 5630: +/***/ ((module) => { -const queueMicrotask = __nccwpck_require__(6230) -function runParallel (tasks, cb) { - let results, pending, keys - let isSync = true - if (Array.isArray(tasks)) { - results = [] - pending = tasks.length - } else { - keys = Object.keys(tasks) - results = {} - pending = keys.length +class LRUCache { + constructor () { + this.max = 1000 + this.map = new Map() } - function done (err) { - function end () { - if (cb) cb(err, results) - cb = null + get (key) { + const value = this.map.get(key) + if (value === undefined) { + return undefined + } else { + // Remove the key from the map and add it to the end + this.map.delete(key) + this.map.set(key, value) + return value } - if (isSync) queueMicrotask(end) - else end() } - function each (i, err, result) { - results[i] = result - if (--pending === 0 || err) { - done(err) - } + delete (key) { + return this.map.delete(key) } - if (!pending) { - // empty - done(null) - } else if (keys) { - // object - keys.forEach(function (key) { - tasks[key](function (err, result) { each(key, err, result) }) - }) - } else { - // array - tasks.forEach(function (task, i) { - task(function (err, result) { each(i, err, result) }) - }) - } + set (key, value) { + const deleted = this.delete(key) - isSync = false + if (!deleted && value !== undefined) { + // If cache is full, delete the least recently used item + if (this.map.size >= this.max) { + const firstKey = this.map.keys().next().value + this.delete(firstKey) + } + + this.map.set(key, value) + } + + return this + } } +module.exports = LRUCache + /***/ }), -/***/ 3764: -/***/ ((module, exports) => { +/***/ 207: +/***/ ((module) => { + -exports = module.exports = SemVer -var debug -/* istanbul ignore next */ -if (typeof process === 'object' && - process.env && - process.env.NODE_DEBUG && - /\bsemver\b/i.test(process.env.NODE_DEBUG)) { - debug = function () { - var args = Array.prototype.slice.call(arguments, 0) - args.unshift('SEMVER') - console.log.apply(console, args) +// parse out just the options we care about +const looseOption = Object.freeze({ loose: true }) +const emptyOpts = Object.freeze({ }) +const parseOptions = options => { + if (!options) { + return emptyOpts } -} else { - debug = function () {} + + if (typeof options !== 'object') { + return looseOption + } + + return options } +module.exports = parseOptions -// Note: this is the semver.org version of the spec that it implements -// Not necessarily the package version of this code. -exports.SEMVER_SPEC_VERSION = '2.0.0' -var MAX_LENGTH = 256 -var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || - /* istanbul ignore next */ 9007199254740991 +/***/ }), -// Max safe segment length for coercion. -var MAX_SAFE_COMPONENT_LENGTH = 16 +/***/ 2330: +/***/ ((module, exports, __nccwpck_require__) => { -var MAX_SAFE_BUILD_LENGTH = MAX_LENGTH - 6 -// The actual regexps go on exports.re -var re = exports.re = [] -var safeRe = exports.safeRe = [] -var src = exports.src = [] -var t = exports.tokens = {} -var R = 0 -function tok (n) { - t[n] = R++ -} +const { + MAX_SAFE_COMPONENT_LENGTH, + MAX_SAFE_BUILD_LENGTH, + MAX_LENGTH, +} = __nccwpck_require__(470) +const debug = __nccwpck_require__(8284) +exports = module.exports = {} -var LETTERDASHNUMBER = '[a-zA-Z0-9-]' +// The actual regexps go on exports.re +const re = exports.re = [] +const safeRe = exports.safeRe = [] +const src = exports.src = [] +const safeSrc = exports.safeSrc = [] +const t = exports.t = {} +let R = 0 + +const LETTERDASHNUMBER = '[a-zA-Z0-9-]' // Replace some greedy regex tokens to prevent regex dos issues. These regex are // used internally via the safeRe object since all inputs in this library get @@ -14270,90 +10703,90 @@ var LETTERDASHNUMBER = '[a-zA-Z0-9-]' // regexes are exported for userland consumption and lower level usage. A // future breaking change could export the safer regex only with a note that // all input should have extra whitespace removed. -var safeRegexReplacements = [ +const safeRegexReplacements = [ ['\\s', 1], ['\\d', MAX_LENGTH], [LETTERDASHNUMBER, MAX_SAFE_BUILD_LENGTH], ] -function makeSafeRe (value) { - for (var i = 0; i < safeRegexReplacements.length; i++) { - var token = safeRegexReplacements[i][0] - var max = safeRegexReplacements[i][1] +const makeSafeRegex = (value) => { + for (const [token, max] of safeRegexReplacements) { value = value - .split(token + '*').join(token + '{0,' + max + '}') - .split(token + '+').join(token + '{1,' + max + '}') + .split(`${token}*`).join(`${token}{0,${max}}`) + .split(`${token}+`).join(`${token}{1,${max}}`) } return value } +const createToken = (name, value, isGlobal) => { + const safe = makeSafeRegex(value) + const index = R++ + debug(name, index, value) + t[name] = index + src[index] = value + safeSrc[index] = safe + re[index] = new RegExp(value, isGlobal ? 'g' : undefined) + safeRe[index] = new RegExp(safe, isGlobal ? 'g' : undefined) +} + // The following Regular Expressions can be used for tokenizing, // validating, and parsing SemVer version strings. // ## Numeric Identifier // A single `0`, or a non-zero digit followed by zero or more digits. -tok('NUMERICIDENTIFIER') -src[t.NUMERICIDENTIFIER] = '0|[1-9]\\d*' -tok('NUMERICIDENTIFIERLOOSE') -src[t.NUMERICIDENTIFIERLOOSE] = '\\d+' +createToken('NUMERICIDENTIFIER', '0|[1-9]\\d*') +createToken('NUMERICIDENTIFIERLOOSE', '\\d+') // ## Non-numeric Identifier // Zero or more digits, followed by a letter or hyphen, and then zero or // more letters, digits, or hyphens. -tok('NONNUMERICIDENTIFIER') -src[t.NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-]' + LETTERDASHNUMBER + '*' +createToken('NONNUMERICIDENTIFIER', `\\d*[a-zA-Z-]${LETTERDASHNUMBER}*`) // ## Main Version // Three dot-separated numeric identifiers. -tok('MAINVERSION') -src[t.MAINVERSION] = '(' + src[t.NUMERICIDENTIFIER] + ')\\.' + - '(' + src[t.NUMERICIDENTIFIER] + ')\\.' + - '(' + src[t.NUMERICIDENTIFIER] + ')' +createToken('MAINVERSION', `(${src[t.NUMERICIDENTIFIER]})\\.` + + `(${src[t.NUMERICIDENTIFIER]})\\.` + + `(${src[t.NUMERICIDENTIFIER]})`) -tok('MAINVERSIONLOOSE') -src[t.MAINVERSIONLOOSE] = '(' + src[t.NUMERICIDENTIFIERLOOSE] + ')\\.' + - '(' + src[t.NUMERICIDENTIFIERLOOSE] + ')\\.' + - '(' + src[t.NUMERICIDENTIFIERLOOSE] + ')' +createToken('MAINVERSIONLOOSE', `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.` + + `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.` + + `(${src[t.NUMERICIDENTIFIERLOOSE]})`) // ## Pre-release Version Identifier // A numeric identifier, or a non-numeric identifier. +// Non-numeric identifiers include numeric identifiers but can be longer. +// Therefore non-numeric identifiers must go first. -tok('PRERELEASEIDENTIFIER') -src[t.PRERELEASEIDENTIFIER] = '(?:' + src[t.NUMERICIDENTIFIER] + - '|' + src[t.NONNUMERICIDENTIFIER] + ')' +createToken('PRERELEASEIDENTIFIER', `(?:${src[t.NONNUMERICIDENTIFIER] +}|${src[t.NUMERICIDENTIFIER]})`) -tok('PRERELEASEIDENTIFIERLOOSE') -src[t.PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[t.NUMERICIDENTIFIERLOOSE] + - '|' + src[t.NONNUMERICIDENTIFIER] + ')' +createToken('PRERELEASEIDENTIFIERLOOSE', `(?:${src[t.NONNUMERICIDENTIFIER] +}|${src[t.NUMERICIDENTIFIERLOOSE]})`) // ## Pre-release Version // Hyphen, followed by one or more dot-separated pre-release version // identifiers. -tok('PRERELEASE') -src[t.PRERELEASE] = '(?:-(' + src[t.PRERELEASEIDENTIFIER] + - '(?:\\.' + src[t.PRERELEASEIDENTIFIER] + ')*))' +createToken('PRERELEASE', `(?:-(${src[t.PRERELEASEIDENTIFIER] +}(?:\\.${src[t.PRERELEASEIDENTIFIER]})*))`) -tok('PRERELEASELOOSE') -src[t.PRERELEASELOOSE] = '(?:-?(' + src[t.PRERELEASEIDENTIFIERLOOSE] + - '(?:\\.' + src[t.PRERELEASEIDENTIFIERLOOSE] + ')*))' +createToken('PRERELEASELOOSE', `(?:-?(${src[t.PRERELEASEIDENTIFIERLOOSE] +}(?:\\.${src[t.PRERELEASEIDENTIFIERLOOSE]})*))`) // ## Build Metadata Identifier // Any combination of digits, letters, or hyphens. -tok('BUILDIDENTIFIER') -src[t.BUILDIDENTIFIER] = LETTERDASHNUMBER + '+' +createToken('BUILDIDENTIFIER', `${LETTERDASHNUMBER}+`) // ## Build Metadata // Plus sign, followed by one or more period-separated build metadata // identifiers. -tok('BUILD') -src[t.BUILD] = '(?:\\+(' + src[t.BUILDIDENTIFIER] + - '(?:\\.' + src[t.BUILDIDENTIFIER] + ')*))' +createToken('BUILD', `(?:\\+(${src[t.BUILDIDENTIFIER] +}(?:\\.${src[t.BUILDIDENTIFIER]})*))`) // ## Full Version String // A main version, followed optionally by a pre-release version and @@ -14364,1352 +10797,717 @@ src[t.BUILD] = '(?:\\+(' + src[t.BUILDIDENTIFIER] + // capturing group, because it should not ever be used in version // comparison. -tok('FULL') -tok('FULLPLAIN') -src[t.FULLPLAIN] = 'v?' + src[t.MAINVERSION] + - src[t.PRERELEASE] + '?' + - src[t.BUILD] + '?' +createToken('FULLPLAIN', `v?${src[t.MAINVERSION] +}${src[t.PRERELEASE]}?${ + src[t.BUILD]}?`) -src[t.FULL] = '^' + src[t.FULLPLAIN] + '$' +createToken('FULL', `^${src[t.FULLPLAIN]}$`) // like full, but allows v1.2.3 and =1.2.3, which people do sometimes. // also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty // common in the npm registry. -tok('LOOSEPLAIN') -src[t.LOOSEPLAIN] = '[v=\\s]*' + src[t.MAINVERSIONLOOSE] + - src[t.PRERELEASELOOSE] + '?' + - src[t.BUILD] + '?' +createToken('LOOSEPLAIN', `[v=\\s]*${src[t.MAINVERSIONLOOSE] +}${src[t.PRERELEASELOOSE]}?${ + src[t.BUILD]}?`) -tok('LOOSE') -src[t.LOOSE] = '^' + src[t.LOOSEPLAIN] + '$' +createToken('LOOSE', `^${src[t.LOOSEPLAIN]}$`) -tok('GTLT') -src[t.GTLT] = '((?:<|>)?=?)' +createToken('GTLT', '((?:<|>)?=?)') // Something like "2.*" or "1.2.x". // Note that "x.x" is a valid xRange identifer, meaning "any version" // Only the first item is strictly required. -tok('XRANGEIDENTIFIERLOOSE') -src[t.XRANGEIDENTIFIERLOOSE] = src[t.NUMERICIDENTIFIERLOOSE] + '|x|X|\\*' -tok('XRANGEIDENTIFIER') -src[t.XRANGEIDENTIFIER] = src[t.NUMERICIDENTIFIER] + '|x|X|\\*' - -tok('XRANGEPLAIN') -src[t.XRANGEPLAIN] = '[v=\\s]*(' + src[t.XRANGEIDENTIFIER] + ')' + - '(?:\\.(' + src[t.XRANGEIDENTIFIER] + ')' + - '(?:\\.(' + src[t.XRANGEIDENTIFIER] + ')' + - '(?:' + src[t.PRERELEASE] + ')?' + - src[t.BUILD] + '?' + - ')?)?' - -tok('XRANGEPLAINLOOSE') -src[t.XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[t.XRANGEIDENTIFIERLOOSE] + ')' + - '(?:\\.(' + src[t.XRANGEIDENTIFIERLOOSE] + ')' + - '(?:\\.(' + src[t.XRANGEIDENTIFIERLOOSE] + ')' + - '(?:' + src[t.PRERELEASELOOSE] + ')?' + - src[t.BUILD] + '?' + - ')?)?' - -tok('XRANGE') -src[t.XRANGE] = '^' + src[t.GTLT] + '\\s*' + src[t.XRANGEPLAIN] + '$' -tok('XRANGELOOSE') -src[t.XRANGELOOSE] = '^' + src[t.GTLT] + '\\s*' + src[t.XRANGEPLAINLOOSE] + '$' +createToken('XRANGEIDENTIFIERLOOSE', `${src[t.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`) +createToken('XRANGEIDENTIFIER', `${src[t.NUMERICIDENTIFIER]}|x|X|\\*`) -// Coercion. -// Extract anything that could conceivably be a part of a valid semver -tok('COERCE') -src[t.COERCE] = '(^|[^\\d])' + - '(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '})' + - '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' + - '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' + - '(?:$|[^\\d])' -tok('COERCERTL') -re[t.COERCERTL] = new RegExp(src[t.COERCE], 'g') -safeRe[t.COERCERTL] = new RegExp(makeSafeRe(src[t.COERCE]), 'g') +createToken('XRANGEPLAIN', `[v=\\s]*(${src[t.XRANGEIDENTIFIER]})` + + `(?:\\.(${src[t.XRANGEIDENTIFIER]})` + + `(?:\\.(${src[t.XRANGEIDENTIFIER]})` + + `(?:${src[t.PRERELEASE]})?${ + src[t.BUILD]}?` + + `)?)?`) + +createToken('XRANGEPLAINLOOSE', `[v=\\s]*(${src[t.XRANGEIDENTIFIERLOOSE]})` + + `(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` + + `(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` + + `(?:${src[t.PRERELEASELOOSE]})?${ + src[t.BUILD]}?` + + `)?)?`) + +createToken('XRANGE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAIN]}$`) +createToken('XRANGELOOSE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAINLOOSE]}$`) + +// Coercion. +// Extract anything that could conceivably be a part of a valid semver +createToken('COERCEPLAIN', `${'(^|[^\\d])' + + '(\\d{1,'}${MAX_SAFE_COMPONENT_LENGTH}})` + + `(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?` + + `(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?`) +createToken('COERCE', `${src[t.COERCEPLAIN]}(?:$|[^\\d])`) +createToken('COERCEFULL', src[t.COERCEPLAIN] + + `(?:${src[t.PRERELEASE]})?` + + `(?:${src[t.BUILD]})?` + + `(?:$|[^\\d])`) +createToken('COERCERTL', src[t.COERCE], true) +createToken('COERCERTLFULL', src[t.COERCEFULL], true) // Tilde ranges. // Meaning is "reasonably at or greater than" -tok('LONETILDE') -src[t.LONETILDE] = '(?:~>?)' +createToken('LONETILDE', '(?:~>?)') -tok('TILDETRIM') -src[t.TILDETRIM] = '(\\s*)' + src[t.LONETILDE] + '\\s+' -re[t.TILDETRIM] = new RegExp(src[t.TILDETRIM], 'g') -safeRe[t.TILDETRIM] = new RegExp(makeSafeRe(src[t.TILDETRIM]), 'g') -var tildeTrimReplace = '$1~' +createToken('TILDETRIM', `(\\s*)${src[t.LONETILDE]}\\s+`, true) +exports.tildeTrimReplace = '$1~' -tok('TILDE') -src[t.TILDE] = '^' + src[t.LONETILDE] + src[t.XRANGEPLAIN] + '$' -tok('TILDELOOSE') -src[t.TILDELOOSE] = '^' + src[t.LONETILDE] + src[t.XRANGEPLAINLOOSE] + '$' +createToken('TILDE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAIN]}$`) +createToken('TILDELOOSE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAINLOOSE]}$`) // Caret ranges. // Meaning is "at least and backwards compatible with" -tok('LONECARET') -src[t.LONECARET] = '(?:\\^)' +createToken('LONECARET', '(?:\\^)') -tok('CARETTRIM') -src[t.CARETTRIM] = '(\\s*)' + src[t.LONECARET] + '\\s+' -re[t.CARETTRIM] = new RegExp(src[t.CARETTRIM], 'g') -safeRe[t.CARETTRIM] = new RegExp(makeSafeRe(src[t.CARETTRIM]), 'g') -var caretTrimReplace = '$1^' +createToken('CARETTRIM', `(\\s*)${src[t.LONECARET]}\\s+`, true) +exports.caretTrimReplace = '$1^' -tok('CARET') -src[t.CARET] = '^' + src[t.LONECARET] + src[t.XRANGEPLAIN] + '$' -tok('CARETLOOSE') -src[t.CARETLOOSE] = '^' + src[t.LONECARET] + src[t.XRANGEPLAINLOOSE] + '$' +createToken('CARET', `^${src[t.LONECARET]}${src[t.XRANGEPLAIN]}$`) +createToken('CARETLOOSE', `^${src[t.LONECARET]}${src[t.XRANGEPLAINLOOSE]}$`) // A simple gt/lt/eq thing, or just "" to indicate "any version" -tok('COMPARATORLOOSE') -src[t.COMPARATORLOOSE] = '^' + src[t.GTLT] + '\\s*(' + src[t.LOOSEPLAIN] + ')$|^$' -tok('COMPARATOR') -src[t.COMPARATOR] = '^' + src[t.GTLT] + '\\s*(' + src[t.FULLPLAIN] + ')$|^$' +createToken('COMPARATORLOOSE', `^${src[t.GTLT]}\\s*(${src[t.LOOSEPLAIN]})$|^$`) +createToken('COMPARATOR', `^${src[t.GTLT]}\\s*(${src[t.FULLPLAIN]})$|^$`) // An expression to strip any whitespace between the gtlt and the thing // it modifies, so that `> 1.2.3` ==> `>1.2.3` -tok('COMPARATORTRIM') -src[t.COMPARATORTRIM] = '(\\s*)' + src[t.GTLT] + - '\\s*(' + src[t.LOOSEPLAIN] + '|' + src[t.XRANGEPLAIN] + ')' - -// this one has to use the /g flag -re[t.COMPARATORTRIM] = new RegExp(src[t.COMPARATORTRIM], 'g') -safeRe[t.COMPARATORTRIM] = new RegExp(makeSafeRe(src[t.COMPARATORTRIM]), 'g') -var comparatorTrimReplace = '$1$2$3' +createToken('COMPARATORTRIM', `(\\s*)${src[t.GTLT] +}\\s*(${src[t.LOOSEPLAIN]}|${src[t.XRANGEPLAIN]})`, true) +exports.comparatorTrimReplace = '$1$2$3' // Something like `1.2.3 - 1.2.4` // Note that these all use the loose form, because they'll be // checked against either the strict or loose comparator form // later. -tok('HYPHENRANGE') -src[t.HYPHENRANGE] = '^\\s*(' + src[t.XRANGEPLAIN] + ')' + - '\\s+-\\s+' + - '(' + src[t.XRANGEPLAIN] + ')' + - '\\s*$' - -tok('HYPHENRANGELOOSE') -src[t.HYPHENRANGELOOSE] = '^\\s*(' + src[t.XRANGEPLAINLOOSE] + ')' + - '\\s+-\\s+' + - '(' + src[t.XRANGEPLAINLOOSE] + ')' + - '\\s*$' +createToken('HYPHENRANGE', `^\\s*(${src[t.XRANGEPLAIN]})` + + `\\s+-\\s+` + + `(${src[t.XRANGEPLAIN]})` + + `\\s*$`) + +createToken('HYPHENRANGELOOSE', `^\\s*(${src[t.XRANGEPLAINLOOSE]})` + + `\\s+-\\s+` + + `(${src[t.XRANGEPLAINLOOSE]})` + + `\\s*$`) // Star ranges basically just allow anything at all. -tok('STAR') -src[t.STAR] = '(<|>)?=?\\s*\\*' +createToken('STAR', '(<|>)?=?\\s*\\*') +// >=0.0.0 is like a star +createToken('GTE0', '^\\s*>=\\s*0\\.0\\.0\\s*$') +createToken('GTE0PRE', '^\\s*>=\\s*0\\.0\\.0-0\\s*$') -// Compile to actual regexp objects. -// All are flag-free, unless they were created above with a flag. -for (var i = 0; i < R; i++) { - debug(i, src[i]) - if (!re[i]) { - re[i] = new RegExp(src[i]) - // Replace all greedy whitespace to prevent regex dos issues. These regex are - // used internally via the safeRe object since all inputs in this library get - // normalized first to trim and collapse all extra whitespace. The original - // regexes are exported for userland consumption and lower level usage. A - // future breaking change could export the safer regex only with a note that - // all input should have extra whitespace removed. - safeRe[i] = new RegExp(makeSafeRe(src[i])) - } -} +/***/ }), -exports.parse = parse -function parse (version, options) { - if (!options || typeof options !== 'object') { - options = { - loose: !!options, - includePrerelease: false - } - } +/***/ 6663: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - if (version instanceof SemVer) { - return version - } - if (typeof version !== 'string') { - return null - } - if (version.length > MAX_LENGTH) { - return null - } +// Determine if version is greater than all the versions possible in the range. +const outside = __nccwpck_require__(703) +const gtr = (version, range, options) => outside(version, range, '>', options) +module.exports = gtr - var r = options.loose ? safeRe[t.LOOSE] : safeRe[t.FULL] - if (!r.test(version)) { - return null - } - try { - return new SemVer(version, options) - } catch (er) { - return null - } -} +/***/ }), -exports.valid = valid -function valid (version, options) { - var v = parse(version, options) - return v ? v.version : null -} +/***/ 896: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -exports.clean = clean -function clean (version, options) { - var s = parse(version.trim().replace(/^[=v]+/, ''), options) - return s ? s.version : null -} -exports.SemVer = SemVer -function SemVer (version, options) { - if (!options || typeof options !== 'object') { - options = { - loose: !!options, - includePrerelease: false - } - } - if (version instanceof SemVer) { - if (version.loose === options.loose) { - return version - } else { - version = version.version - } - } else if (typeof version !== 'string') { - throw new TypeError('Invalid Version: ' + version) - } +const Range = __nccwpck_require__(1699) +const intersects = (r1, r2, options) => { + r1 = new Range(r1, options) + r2 = new Range(r2, options) + return r1.intersects(r2, options) +} +module.exports = intersects - if (version.length > MAX_LENGTH) { - throw new TypeError('version is longer than ' + MAX_LENGTH + ' characters') - } - if (!(this instanceof SemVer)) { - return new SemVer(version, options) - } +/***/ }), - debug('SemVer', version, options) - this.options = options - this.loose = !!options.loose +/***/ 6002: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - var m = version.trim().match(options.loose ? safeRe[t.LOOSE] : safeRe[t.FULL]) - if (!m) { - throw new TypeError('Invalid Version: ' + version) - } - this.raw = version +const outside = __nccwpck_require__(703) +// Determine if version is less than all the versions possible in the range +const ltr = (version, range, options) => outside(version, range, '<', options) +module.exports = ltr - // these are actually numbers - this.major = +m[1] - this.minor = +m[2] - this.patch = +m[3] - if (this.major > MAX_SAFE_INTEGER || this.major < 0) { - throw new TypeError('Invalid major version') - } +/***/ }), - if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) { - throw new TypeError('Invalid minor version') - } +/***/ 2840: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) { - throw new TypeError('Invalid patch version') - } - // numberify any prerelease numeric ids - if (!m[4]) { - this.prerelease = [] - } else { - this.prerelease = m[4].split('.').map(function (id) { - if (/^[0-9]+$/.test(id)) { - var num = +id - if (num >= 0 && num < MAX_SAFE_INTEGER) { - return num - } - } - return id - }) - } - this.build = m[5] ? m[5].split('.') : [] - this.format() -} +const SemVer = __nccwpck_require__(1776) +const Range = __nccwpck_require__(1699) -SemVer.prototype.format = function () { - this.version = this.major + '.' + this.minor + '.' + this.patch - if (this.prerelease.length) { - this.version += '-' + this.prerelease.join('.') +const maxSatisfying = (versions, range, options) => { + let max = null + let maxSV = null + let rangeObj = null + try { + rangeObj = new Range(range, options) + } catch (er) { + return null } - return this.version -} - -SemVer.prototype.toString = function () { - return this.version + versions.forEach((v) => { + if (rangeObj.test(v)) { + // satisfies(v, range, options) + if (!max || maxSV.compare(v) === -1) { + // compare(max, v, true) + max = v + maxSV = new SemVer(max, options) + } + } + }) + return max } +module.exports = maxSatisfying -SemVer.prototype.compare = function (other) { - debug('SemVer.compare', this.version, this.options, other) - if (!(other instanceof SemVer)) { - other = new SemVer(other, this.options) - } - return this.compareMain(other) || this.comparePre(other) -} +/***/ }), -SemVer.prototype.compareMain = function (other) { - if (!(other instanceof SemVer)) { - other = new SemVer(other, this.options) - } +/***/ 7586: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - return compareIdentifiers(this.major, other.major) || - compareIdentifiers(this.minor, other.minor) || - compareIdentifiers(this.patch, other.patch) -} -SemVer.prototype.comparePre = function (other) { - if (!(other instanceof SemVer)) { - other = new SemVer(other, this.options) - } - // NOT having a prerelease is > having one - if (this.prerelease.length && !other.prerelease.length) { - return -1 - } else if (!this.prerelease.length && other.prerelease.length) { - return 1 - } else if (!this.prerelease.length && !other.prerelease.length) { - return 0 +const SemVer = __nccwpck_require__(1776) +const Range = __nccwpck_require__(1699) +const minSatisfying = (versions, range, options) => { + let min = null + let minSV = null + let rangeObj = null + try { + rangeObj = new Range(range, options) + } catch (er) { + return null } - - var i = 0 - do { - var a = this.prerelease[i] - var b = other.prerelease[i] - debug('prerelease compare', i, a, b) - if (a === undefined && b === undefined) { - return 0 - } else if (b === undefined) { - return 1 - } else if (a === undefined) { - return -1 - } else if (a === b) { - continue - } else { - return compareIdentifiers(a, b) + versions.forEach((v) => { + if (rangeObj.test(v)) { + // satisfies(v, range, options) + if (!min || minSV.compare(v) === 1) { + // compare(min, v, true) + min = v + minSV = new SemVer(min, options) + } } - } while (++i) + }) + return min } +module.exports = minSatisfying -SemVer.prototype.compareBuild = function (other) { - if (!(other instanceof SemVer)) { - other = new SemVer(other, this.options) - } - var i = 0 - do { - var a = this.build[i] - var b = other.build[i] - debug('prerelease compare', i, a, b) - if (a === undefined && b === undefined) { - return 0 - } else if (b === undefined) { - return 1 - } else if (a === undefined) { - return -1 - } else if (a === b) { - continue - } else { - return compareIdentifiers(a, b) - } - } while (++i) -} +/***/ }), -// preminor will bump the version up to the next minor release, and immediately -// down to pre-release. premajor and prepatch work the same way. -SemVer.prototype.inc = function (release, identifier) { - switch (release) { - case 'premajor': - this.prerelease.length = 0 - this.patch = 0 - this.minor = 0 - this.major++ - this.inc('pre', identifier) - break - case 'preminor': - this.prerelease.length = 0 - this.patch = 0 - this.minor++ - this.inc('pre', identifier) - break - case 'prepatch': - // If this is already a prerelease, it will bump to the next version - // drop any prereleases that might already exist, since they are not - // relevant at this point. - this.prerelease.length = 0 - this.inc('patch', identifier) - this.inc('pre', identifier) - break - // If the input is a non-prerelease version, this acts the same as - // prepatch. - case 'prerelease': - if (this.prerelease.length === 0) { - this.inc('patch', identifier) - } - this.inc('pre', identifier) - break +/***/ 937: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - case 'major': - // If this is a pre-major version, bump up to the same major version. - // Otherwise increment major. - // 1.0.0-5 bumps to 1.0.0 - // 1.1.0 bumps to 2.0.0 - if (this.minor !== 0 || - this.patch !== 0 || - this.prerelease.length === 0) { - this.major++ - } - this.minor = 0 - this.patch = 0 - this.prerelease = [] - break - case 'minor': - // If this is a pre-minor version, bump up to the same minor version. - // Otherwise increment minor. - // 1.2.0-5 bumps to 1.2.0 - // 1.2.1 bumps to 1.3.0 - if (this.patch !== 0 || this.prerelease.length === 0) { - this.minor++ - } - this.patch = 0 - this.prerelease = [] - break - case 'patch': - // If this is not a pre-release version, it will increment the patch. - // If it is a pre-release it will bump up to the same patch version. - // 1.2.0-5 patches to 1.2.0 - // 1.2.0 patches to 1.2.1 - if (this.prerelease.length === 0) { - this.patch++ - } - this.prerelease = [] - break - // This probably shouldn't be used publicly. - // 1.0.0 "pre" would become 1.0.0-0 which is the wrong direction. - case 'pre': - if (this.prerelease.length === 0) { - this.prerelease = [0] - } else { - var i = this.prerelease.length - while (--i >= 0) { - if (typeof this.prerelease[i] === 'number') { - this.prerelease[i]++ - i = -2 - } - } - if (i === -1) { - // didn't increment anything - this.prerelease.push(0) - } - } - if (identifier) { - // 1.2.0-beta.1 bumps to 1.2.0-beta.2, - // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0 - if (this.prerelease[0] === identifier) { - if (isNaN(this.prerelease[1])) { - this.prerelease = [identifier, 0] - } - } else { - this.prerelease = [identifier, 0] - } - } - break - default: - throw new Error('invalid increment argument: ' + release) - } - this.format() - this.raw = this.version - return this -} -exports.inc = inc -function inc (version, release, loose, identifier) { - if (typeof (loose) === 'string') { - identifier = loose - loose = undefined +const SemVer = __nccwpck_require__(1776) +const Range = __nccwpck_require__(1699) +const gt = __nccwpck_require__(9448) + +const minVersion = (range, loose) => { + range = new Range(range, loose) + + let minver = new SemVer('0.0.0') + if (range.test(minver)) { + return minver } - try { - return new SemVer(version, loose).inc(release, identifier).version - } catch (er) { - return null + minver = new SemVer('0.0.0-0') + if (range.test(minver)) { + return minver } -} -exports.diff = diff -function diff (version1, version2) { - if (eq(version1, version2)) { - return null - } else { - var v1 = parse(version1) - var v2 = parse(version2) - var prefix = '' - if (v1.prerelease.length || v2.prerelease.length) { - prefix = 'pre' - var defaultResult = 'prerelease' - } - for (var key in v1) { - if (key === 'major' || key === 'minor' || key === 'patch') { - if (v1[key] !== v2[key]) { - return prefix + key - } + minver = null + for (let i = 0; i < range.set.length; ++i) { + const comparators = range.set[i] + + let setMin = null + comparators.forEach((comparator) => { + // Clone to avoid manipulating the comparator's semver object. + const compver = new SemVer(comparator.semver.version) + switch (comparator.operator) { + case '>': + if (compver.prerelease.length === 0) { + compver.patch++ + } else { + compver.prerelease.push(0) + } + compver.raw = compver.format() + /* fallthrough */ + case '': + case '>=': + if (!setMin || gt(compver, setMin)) { + setMin = compver + } + break + case '<': + case '<=': + /* Ignore maximum versions */ + break + /* istanbul ignore next */ + default: + throw new Error(`Unexpected operation: ${comparator.operator}`) } + }) + if (setMin && (!minver || gt(minver, setMin))) { + minver = setMin } - return defaultResult // may be undefined } -} - -exports.compareIdentifiers = compareIdentifiers -var numeric = /^[0-9]+$/ -function compareIdentifiers (a, b) { - var anum = numeric.test(a) - var bnum = numeric.test(b) - - if (anum && bnum) { - a = +a - b = +b + if (minver && range.test(minver)) { + return minver } - return a === b ? 0 - : (anum && !bnum) ? -1 - : (bnum && !anum) ? 1 - : a < b ? -1 - : 1 -} - -exports.rcompareIdentifiers = rcompareIdentifiers -function rcompareIdentifiers (a, b) { - return compareIdentifiers(b, a) + return null } +module.exports = minVersion -exports.major = major -function major (a, loose) { - return new SemVer(a, loose).major -} -exports.minor = minor -function minor (a, loose) { - return new SemVer(a, loose).minor -} +/***/ }), -exports.patch = patch -function patch (a, loose) { - return new SemVer(a, loose).patch -} +/***/ 703: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -exports.compare = compare -function compare (a, b, loose) { - return new SemVer(a, loose).compare(new SemVer(b, loose)) -} -exports.compareLoose = compareLoose -function compareLoose (a, b) { - return compare(a, b, true) -} -exports.compareBuild = compareBuild -function compareBuild (a, b, loose) { - var versionA = new SemVer(a, loose) - var versionB = new SemVer(b, loose) - return versionA.compare(versionB) || versionA.compareBuild(versionB) -} +const SemVer = __nccwpck_require__(1776) +const Comparator = __nccwpck_require__(5388) +const { ANY } = Comparator +const Range = __nccwpck_require__(1699) +const satisfies = __nccwpck_require__(8370) +const gt = __nccwpck_require__(9448) +const lt = __nccwpck_require__(8991) +const lte = __nccwpck_require__(812) +const gte = __nccwpck_require__(7989) -exports.rcompare = rcompare -function rcompare (a, b, loose) { - return compare(b, a, loose) -} +const outside = (version, range, hilo, options) => { + version = new SemVer(version, options) + range = new Range(range, options) -exports.sort = sort -function sort (list, loose) { - return list.sort(function (a, b) { - return exports.compareBuild(a, b, loose) - }) -} + let gtfn, ltefn, ltfn, comp, ecomp + switch (hilo) { + case '>': + gtfn = gt + ltefn = lte + ltfn = lt + comp = '>' + ecomp = '>=' + break + case '<': + gtfn = lt + ltefn = gte + ltfn = gt + comp = '<' + ecomp = '<=' + break + default: + throw new TypeError('Must provide a hilo val of "<" or ">"') + } -exports.rsort = rsort -function rsort (list, loose) { - return list.sort(function (a, b) { - return exports.compareBuild(b, a, loose) - }) -} + // If it satisfies the range it is not outside + if (satisfies(version, range, options)) { + return false + } -exports.gt = gt -function gt (a, b, loose) { - return compare(a, b, loose) > 0 -} + // From now on, variable terms are as if we're in "gtr" mode. + // but note that everything is flipped for the "ltr" function. -exports.lt = lt -function lt (a, b, loose) { - return compare(a, b, loose) < 0 -} + for (let i = 0; i < range.set.length; ++i) { + const comparators = range.set[i] -exports.eq = eq -function eq (a, b, loose) { - return compare(a, b, loose) === 0 -} + let high = null + let low = null -exports.neq = neq -function neq (a, b, loose) { - return compare(a, b, loose) !== 0 -} + comparators.forEach((comparator) => { + if (comparator.semver === ANY) { + comparator = new Comparator('>=0.0.0') + } + high = high || comparator + low = low || comparator + if (gtfn(comparator.semver, high.semver, options)) { + high = comparator + } else if (ltfn(comparator.semver, low.semver, options)) { + low = comparator + } + }) -exports.gte = gte -function gte (a, b, loose) { - return compare(a, b, loose) >= 0 -} + // If the edge version comparator has a operator then our version + // isn't outside it + if (high.operator === comp || high.operator === ecomp) { + return false + } -exports.lte = lte -function lte (a, b, loose) { - return compare(a, b, loose) <= 0 + // If the lowest version comparator has an operator and our version + // is less than it then it isn't higher than the range + if ((!low.operator || low.operator === comp) && + ltefn(version, low.semver)) { + return false + } else if (low.operator === ecomp && ltfn(version, low.semver)) { + return false + } + } + return true } -exports.cmp = cmp -function cmp (a, op, b, loose) { - switch (op) { - case '===': - if (typeof a === 'object') - a = a.version - if (typeof b === 'object') - b = b.version - return a === b - - case '!==': - if (typeof a === 'object') - a = a.version - if (typeof b === 'object') - b = b.version - return a !== b - - case '': - case '=': - case '==': - return eq(a, b, loose) - - case '!=': - return neq(a, b, loose) - - case '>': - return gt(a, b, loose) +module.exports = outside - case '>=': - return gte(a, b, loose) - case '<': - return lt(a, b, loose) +/***/ }), - case '<=': - return lte(a, b, loose) +/***/ 3393: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - default: - throw new TypeError('Invalid operator: ' + op) - } -} -exports.Comparator = Comparator -function Comparator (comp, options) { - if (!options || typeof options !== 'object') { - options = { - loose: !!options, - includePrerelease: false - } - } - if (comp instanceof Comparator) { - if (comp.loose === !!options.loose) { - return comp +// given a set of versions and a range, create a "simplified" range +// that includes the same versions that the original range does +// If the original range is shorter than the simplified one, return that. +const satisfies = __nccwpck_require__(8370) +const compare = __nccwpck_require__(7180) +module.exports = (versions, range, options) => { + const set = [] + let first = null + let prev = null + const v = versions.sort((a, b) => compare(a, b, options)) + for (const version of v) { + const included = satisfies(version, range, options) + if (included) { + prev = version + if (!first) { + first = version + } } else { - comp = comp.value + if (prev) { + set.push([first, prev]) + } + prev = null + first = null } } - - if (!(this instanceof Comparator)) { - return new Comparator(comp, options) + if (first) { + set.push([first, null]) } - comp = comp.trim().split(/\s+/).join(' ') - debug('comparator', comp, options) - this.options = options - this.loose = !!options.loose - this.parse(comp) - - if (this.semver === ANY) { - this.value = '' - } else { - this.value = this.operator + this.semver.version + const ranges = [] + for (const [min, max] of set) { + if (min === max) { + ranges.push(min) + } else if (!max && min === v[0]) { + ranges.push('*') + } else if (!max) { + ranges.push(`>=${min}`) + } else if (min === v[0]) { + ranges.push(`<=${max}`) + } else { + ranges.push(`${min} - ${max}`) + } } - - debug('comp', this) + const simplified = ranges.join(' || ') + const original = typeof range.raw === 'string' ? range.raw : String(range) + return simplified.length < original.length ? simplified : range } -var ANY = {} -Comparator.prototype.parse = function (comp) { - var r = this.options.loose ? safeRe[t.COMPARATORLOOSE] : safeRe[t.COMPARATOR] - var m = comp.match(r) - if (!m) { - throw new TypeError('Invalid comparator: ' + comp) - } +/***/ }), - this.operator = m[1] !== undefined ? m[1] : '' - if (this.operator === '=') { - this.operator = '' - } +/***/ 6652: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - // if it literally is just '>' or '' then allow anything. - if (!m[2]) { - this.semver = ANY - } else { - this.semver = new SemVer(m[2], this.options.loose) - } -} -Comparator.prototype.toString = function () { - return this.value -} -Comparator.prototype.test = function (version) { - debug('Comparator.test', version, this.options.loose) +const Range = __nccwpck_require__(1699) +const Comparator = __nccwpck_require__(5388) +const { ANY } = Comparator +const satisfies = __nccwpck_require__(8370) +const compare = __nccwpck_require__(7180) + +// Complex range `r1 || r2 || ...` is a subset of `R1 || R2 || ...` iff: +// - Every simple range `r1, r2, ...` is a null set, OR +// - Every simple range `r1, r2, ...` which is not a null set is a subset of +// some `R1, R2, ...` +// +// Simple range `c1 c2 ...` is a subset of simple range `C1 C2 ...` iff: +// - If c is only the ANY comparator +// - If C is only the ANY comparator, return true +// - Else if in prerelease mode, return false +// - else replace c with `[>=0.0.0]` +// - If C is only the ANY comparator +// - if in prerelease mode, return true +// - else replace C with `[>=0.0.0]` +// - Let EQ be the set of = comparators in c +// - If EQ is more than one, return true (null set) +// - Let GT be the highest > or >= comparator in c +// - Let LT be the lowest < or <= comparator in c +// - If GT and LT, and GT.semver > LT.semver, return true (null set) +// - If any C is a = range, and GT or LT are set, return false +// - If EQ +// - If GT, and EQ does not satisfy GT, return true (null set) +// - If LT, and EQ does not satisfy LT, return true (null set) +// - If EQ satisfies every C, return true +// - Else return false +// - If GT +// - If GT.semver is lower than any > or >= comp in C, return false +// - If GT is >=, and GT.semver does not satisfy every C, return false +// - If GT.semver has a prerelease, and not in prerelease mode +// - If no C has a prerelease and the GT.semver tuple, return false +// - If LT +// - If LT.semver is greater than any < or <= comp in C, return false +// - If LT is <=, and LT.semver does not satisfy every C, return false +// - If LT.semver has a prerelease, and not in prerelease mode +// - If no C has a prerelease and the LT.semver tuple, return false +// - Else return true - if (this.semver === ANY || version === ANY) { +const subset = (sub, dom, options = {}) => { + if (sub === dom) { return true } - if (typeof version === 'string') { - try { - version = new SemVer(version, this.options) - } catch (er) { + sub = new Range(sub, options) + dom = new Range(dom, options) + let sawNonNull = false + + OUTER: for (const simpleSub of sub.set) { + for (const simpleDom of dom.set) { + const isSub = simpleSubset(simpleSub, simpleDom, options) + sawNonNull = sawNonNull || isSub !== null + if (isSub) { + continue OUTER + } + } + // the null set is a subset of everything, but null simple ranges in + // a complex range should be ignored. so if we saw a non-null range, + // then we know this isn't a subset, but if EVERY simple range was null, + // then it is a subset. + if (sawNonNull) { return false } } - - return cmp(version, this.operator, this.semver, this.options) + return true } -Comparator.prototype.intersects = function (comp, options) { - if (!(comp instanceof Comparator)) { - throw new TypeError('a Comparator is required') - } +const minimumVersionWithPreRelease = [new Comparator('>=0.0.0-0')] +const minimumVersion = [new Comparator('>=0.0.0')] - if (!options || typeof options !== 'object') { - options = { - loose: !!options, - includePrerelease: false - } +const simpleSubset = (sub, dom, options) => { + if (sub === dom) { + return true } - var rangeTmp - - if (this.operator === '') { - if (this.value === '') { + if (sub.length === 1 && sub[0].semver === ANY) { + if (dom.length === 1 && dom[0].semver === ANY) { return true + } else if (options.includePrerelease) { + sub = minimumVersionWithPreRelease + } else { + sub = minimumVersion } - rangeTmp = new Range(comp.value, options) - return satisfies(this.value, rangeTmp, options) - } else if (comp.operator === '') { - if (comp.value === '') { + } + + if (dom.length === 1 && dom[0].semver === ANY) { + if (options.includePrerelease) { return true - } - rangeTmp = new Range(this.value, options) - return satisfies(comp.semver, rangeTmp, options) - } - - var sameDirectionIncreasing = - (this.operator === '>=' || this.operator === '>') && - (comp.operator === '>=' || comp.operator === '>') - var sameDirectionDecreasing = - (this.operator === '<=' || this.operator === '<') && - (comp.operator === '<=' || comp.operator === '<') - var sameSemVer = this.semver.version === comp.semver.version - var differentDirectionsInclusive = - (this.operator === '>=' || this.operator === '<=') && - (comp.operator === '>=' || comp.operator === '<=') - var oppositeDirectionsLessThan = - cmp(this.semver, '<', comp.semver, options) && - ((this.operator === '>=' || this.operator === '>') && - (comp.operator === '<=' || comp.operator === '<')) - var oppositeDirectionsGreaterThan = - cmp(this.semver, '>', comp.semver, options) && - ((this.operator === '<=' || this.operator === '<') && - (comp.operator === '>=' || comp.operator === '>')) - - return sameDirectionIncreasing || sameDirectionDecreasing || - (sameSemVer && differentDirectionsInclusive) || - oppositeDirectionsLessThan || oppositeDirectionsGreaterThan -} - -exports.Range = Range -function Range (range, options) { - if (!options || typeof options !== 'object') { - options = { - loose: !!options, - includePrerelease: false - } - } - - if (range instanceof Range) { - if (range.loose === !!options.loose && - range.includePrerelease === !!options.includePrerelease) { - return range } else { - return new Range(range.raw, options) + dom = minimumVersion } } - if (range instanceof Comparator) { - return new Range(range.value, options) + const eqSet = new Set() + let gt, lt + for (const c of sub) { + if (c.operator === '>' || c.operator === '>=') { + gt = higherGT(gt, c, options) + } else if (c.operator === '<' || c.operator === '<=') { + lt = lowerLT(lt, c, options) + } else { + eqSet.add(c.semver) + } } - if (!(this instanceof Range)) { - return new Range(range, options) + if (eqSet.size > 1) { + return null } - this.options = options - this.loose = !!options.loose - this.includePrerelease = !!options.includePrerelease - - // First reduce all whitespace as much as possible so we do not have to rely - // on potentially slow regexes like \s*. This is then stored and used for - // future error messages as well. - this.raw = range - .trim() - .split(/\s+/) - .join(' ') - - // First, split based on boolean or || - this.set = this.raw.split('||').map(function (range) { - return this.parseRange(range.trim()) - }, this).filter(function (c) { - // throw out any that are not relevant for whatever reason - return c.length - }) - - if (!this.set.length) { - throw new TypeError('Invalid SemVer Range: ' + this.raw) + let gtltComp + if (gt && lt) { + gtltComp = compare(gt.semver, lt.semver, options) + if (gtltComp > 0) { + return null + } else if (gtltComp === 0 && (gt.operator !== '>=' || lt.operator !== '<=')) { + return null + } } - this.format() -} - -Range.prototype.format = function () { - this.range = this.set.map(function (comps) { - return comps.join(' ').trim() - }).join('||').trim() - return this.range -} - -Range.prototype.toString = function () { - return this.range -} - -Range.prototype.parseRange = function (range) { - var loose = this.options.loose - // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4` - var hr = loose ? safeRe[t.HYPHENRANGELOOSE] : safeRe[t.HYPHENRANGE] - range = range.replace(hr, hyphenReplace) - debug('hyphen replace', range) - // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5` - range = range.replace(safeRe[t.COMPARATORTRIM], comparatorTrimReplace) - debug('comparator trim', range, safeRe[t.COMPARATORTRIM]) - - // `~ 1.2.3` => `~1.2.3` - range = range.replace(safeRe[t.TILDETRIM], tildeTrimReplace) - - // `^ 1.2.3` => `^1.2.3` - range = range.replace(safeRe[t.CARETTRIM], caretTrimReplace) - - // normalize spaces - range = range.split(/\s+/).join(' ') - - // At this point, the range is completely trimmed and - // ready to be split into comparators. + // will iterate one or zero times + for (const eq of eqSet) { + if (gt && !satisfies(eq, String(gt), options)) { + return null + } - var compRe = loose ? safeRe[t.COMPARATORLOOSE] : safeRe[t.COMPARATOR] - var set = range.split(' ').map(function (comp) { - return parseComparator(comp, this.options) - }, this).join(' ').split(/\s+/) - if (this.options.loose) { - // in loose mode, throw out any that are not valid comparators - set = set.filter(function (comp) { - return !!comp.match(compRe) - }) - } - set = set.map(function (comp) { - return new Comparator(comp, this.options) - }, this) + if (lt && !satisfies(eq, String(lt), options)) { + return null + } - return set -} + for (const c of dom) { + if (!satisfies(eq, String(c), options)) { + return false + } + } -Range.prototype.intersects = function (range, options) { - if (!(range instanceof Range)) { - throw new TypeError('a Range is required') + return true } - return this.set.some(function (thisComparators) { - return ( - isSatisfiable(thisComparators, options) && - range.set.some(function (rangeComparators) { - return ( - isSatisfiable(rangeComparators, options) && - thisComparators.every(function (thisComparator) { - return rangeComparators.every(function (rangeComparator) { - return thisComparator.intersects(rangeComparator, options) - }) - }) - ) - }) - ) - }) -} - -// take a set of comparators and determine whether there -// exists a version which can satisfy it -function isSatisfiable (comparators, options) { - var result = true - var remainingComparators = comparators.slice() - var testComparator = remainingComparators.pop() - - while (result && remainingComparators.length) { - result = remainingComparators.every(function (otherComparator) { - return testComparator.intersects(otherComparator, options) - }) - - testComparator = remainingComparators.pop() + let higher, lower + let hasDomLT, hasDomGT + // if the subset has a prerelease, we need a comparator in the superset + // with the same tuple and a prerelease, or it's not a subset + let needDomLTPre = lt && + !options.includePrerelease && + lt.semver.prerelease.length ? lt.semver : false + let needDomGTPre = gt && + !options.includePrerelease && + gt.semver.prerelease.length ? gt.semver : false + // exception: <1.2.3-0 is the same as <1.2.3 + if (needDomLTPre && needDomLTPre.prerelease.length === 1 && + lt.operator === '<' && needDomLTPre.prerelease[0] === 0) { + needDomLTPre = false } - return result -} - -// Mostly just for testing and legacy API reasons -exports.toComparators = toComparators -function toComparators (range, options) { - return new Range(range, options).set.map(function (comp) { - return comp.map(function (c) { - return c.value - }).join(' ').trim().split(' ') - }) -} - -// comprised of xranges, tildes, stars, and gtlt's at this point. -// already replaced the hyphen ranges -// turn into a set of JUST comparators. -function parseComparator (comp, options) { - debug('comp', comp, options) - comp = replaceCarets(comp, options) - debug('caret', comp) - comp = replaceTildes(comp, options) - debug('tildes', comp) - comp = replaceXRanges(comp, options) - debug('xrange', comp) - comp = replaceStars(comp, options) - debug('stars', comp) - return comp -} - -function isX (id) { - return !id || id.toLowerCase() === 'x' || id === '*' -} - -// ~, ~> --> * (any, kinda silly) -// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0 -// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0 -// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0 -// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0 -// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0 -function replaceTildes (comp, options) { - return comp.trim().split(/\s+/).map(function (comp) { - return replaceTilde(comp, options) - }).join(' ') -} - -function replaceTilde (comp, options) { - var r = options.loose ? safeRe[t.TILDELOOSE] : safeRe[t.TILDE] - return comp.replace(r, function (_, M, m, p, pr) { - debug('tilde', comp, _, M, m, p, pr) - var ret - - if (isX(M)) { - ret = '' - } else if (isX(m)) { - ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' - } else if (isX(p)) { - // ~1.2 == >=1.2.0 <1.3.0 - ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' - } else if (pr) { - debug('replaceTilde pr', pr) - ret = '>=' + M + '.' + m + '.' + p + '-' + pr + - ' <' + M + '.' + (+m + 1) + '.0' - } else { - // ~1.2.3 == >=1.2.3 <1.3.0 - ret = '>=' + M + '.' + m + '.' + p + - ' <' + M + '.' + (+m + 1) + '.0' - } - - debug('tilde return', ret) - return ret - }) -} - -// ^ --> * (any, kinda silly) -// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0 -// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0 -// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0 -// ^1.2.3 --> >=1.2.3 <2.0.0 -// ^1.2.0 --> >=1.2.0 <2.0.0 -function replaceCarets (comp, options) { - return comp.trim().split(/\s+/).map(function (comp) { - return replaceCaret(comp, options) - }).join(' ') -} - -function replaceCaret (comp, options) { - debug('caret', comp, options) - var r = options.loose ? safeRe[t.CARETLOOSE] : safeRe[t.CARET] - return comp.replace(r, function (_, M, m, p, pr) { - debug('caret', comp, _, M, m, p, pr) - var ret - - if (isX(M)) { - ret = '' - } else if (isX(m)) { - ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' - } else if (isX(p)) { - if (M === '0') { - ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' - } else { - ret = '>=' + M + '.' + m + '.0 <' + (+M + 1) + '.0.0' - } - } else if (pr) { - debug('replaceCaret pr', pr) - if (M === '0') { - if (m === '0') { - ret = '>=' + M + '.' + m + '.' + p + '-' + pr + - ' <' + M + '.' + m + '.' + (+p + 1) - } else { - ret = '>=' + M + '.' + m + '.' + p + '-' + pr + - ' <' + M + '.' + (+m + 1) + '.0' + for (const c of dom) { + hasDomGT = hasDomGT || c.operator === '>' || c.operator === '>=' + hasDomLT = hasDomLT || c.operator === '<' || c.operator === '<=' + if (gt) { + if (needDomGTPre) { + if (c.semver.prerelease && c.semver.prerelease.length && + c.semver.major === needDomGTPre.major && + c.semver.minor === needDomGTPre.minor && + c.semver.patch === needDomGTPre.patch) { + needDomGTPre = false } - } else { - ret = '>=' + M + '.' + m + '.' + p + '-' + pr + - ' <' + (+M + 1) + '.0.0' } - } else { - debug('no pr') - if (M === '0') { - if (m === '0') { - ret = '>=' + M + '.' + m + '.' + p + - ' <' + M + '.' + m + '.' + (+p + 1) - } else { - ret = '>=' + M + '.' + m + '.' + p + - ' <' + M + '.' + (+m + 1) + '.0' + if (c.operator === '>' || c.operator === '>=') { + higher = higherGT(gt, c, options) + if (higher === c && higher !== gt) { + return false } - } else { - ret = '>=' + M + '.' + m + '.' + p + - ' <' + (+M + 1) + '.0.0' + } else if (gt.operator === '>=' && !satisfies(gt.semver, String(c), options)) { + return false } } - - debug('caret return', ret) - return ret - }) -} - -function replaceXRanges (comp, options) { - debug('replaceXRanges', comp, options) - return comp.split(/\s+/).map(function (comp) { - return replaceXRange(comp, options) - }).join(' ') -} - -function replaceXRange (comp, options) { - comp = comp.trim() - var r = options.loose ? safeRe[t.XRANGELOOSE] : safeRe[t.XRANGE] - return comp.replace(r, function (ret, gtlt, M, m, p, pr) { - debug('xRange', comp, ret, gtlt, M, m, p, pr) - var xM = isX(M) - var xm = xM || isX(m) - var xp = xm || isX(p) - var anyX = xp - - if (gtlt === '=' && anyX) { - gtlt = '' - } - - // if we're including prereleases in the match, then we need - // to fix this to -0, the lowest possible prerelease value - pr = options.includePrerelease ? '-0' : '' - - if (xM) { - if (gtlt === '>' || gtlt === '<') { - // nothing is allowed - ret = '<0.0.0-0' - } else { - // nothing is forbidden - ret = '*' - } - } else if (gtlt && anyX) { - // we know patch is an x, because we have any x at all. - // replace X with 0 - if (xm) { - m = 0 - } - p = 0 - - if (gtlt === '>') { - // >1 => >=2.0.0 - // >1.2 => >=1.3.0 - // >1.2.3 => >= 1.2.4 - gtlt = '>=' - if (xm) { - M = +M + 1 - m = 0 - p = 0 - } else { - m = +m + 1 - p = 0 + if (lt) { + if (needDomLTPre) { + if (c.semver.prerelease && c.semver.prerelease.length && + c.semver.major === needDomLTPre.major && + c.semver.minor === needDomLTPre.minor && + c.semver.patch === needDomLTPre.patch) { + needDomLTPre = false } - } else if (gtlt === '<=') { - // <=0.7.x is actually <0.8.0, since any 0.7.x should - // pass. Similarly, <=7.x is actually <8.0.0, etc. - gtlt = '<' - if (xm) { - M = +M + 1 - } else { - m = +m + 1 + } + if (c.operator === '<' || c.operator === '<=') { + lower = lowerLT(lt, c, options) + if (lower === c && lower !== lt) { + return false } + } else if (lt.operator === '<=' && !satisfies(lt.semver, String(c), options)) { + return false } - - ret = gtlt + M + '.' + m + '.' + p + pr - } else if (xm) { - ret = '>=' + M + '.0.0' + pr + ' <' + (+M + 1) + '.0.0' + pr - } else if (xp) { - ret = '>=' + M + '.' + m + '.0' + pr + - ' <' + M + '.' + (+m + 1) + '.0' + pr } - - debug('xRange return', ret) - - return ret - }) -} - -// Because * is AND-ed with everything else in the comparator, -// and '' means "any version", just remove the *s entirely. -function replaceStars (comp, options) { - debug('replaceStars', comp, options) - // Looseness is ignored here. star is always as loose as it gets! - return comp.trim().replace(safeRe[t.STAR], '') -} - -// This function is passed to string.replace(re[t.HYPHENRANGE]) -// M, m, patch, prerelease, build -// 1.2 - 3.4.5 => >=1.2.0 <=3.4.5 -// 1.2.3 - 3.4 => >=1.2.0 <3.5.0 Any 3.4.x will do -// 1.2 - 3.4 => >=1.2.0 <3.5.0 -function hyphenReplace ($0, - from, fM, fm, fp, fpr, fb, - to, tM, tm, tp, tpr, tb) { - if (isX(fM)) { - from = '' - } else if (isX(fm)) { - from = '>=' + fM + '.0.0' - } else if (isX(fp)) { - from = '>=' + fM + '.' + fm + '.0' - } else { - from = '>=' + from - } - - if (isX(tM)) { - to = '' - } else if (isX(tm)) { - to = '<' + (+tM + 1) + '.0.0' - } else if (isX(tp)) { - to = '<' + tM + '.' + (+tm + 1) + '.0' - } else if (tpr) { - to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr - } else { - to = '<=' + to - } - - return (from + ' ' + to).trim() -} - -// if ANY of the sets match ALL of its comparators, then pass -Range.prototype.test = function (version) { - if (!version) { - return false - } - - if (typeof version === 'string') { - try { - version = new SemVer(version, this.options) - } catch (er) { + if (!c.operator && (lt || gt) && gtltComp !== 0) { return false } } - for (var i = 0; i < this.set.length; i++) { - if (testSet(this.set[i], version, this.options)) { - return true - } + // if there was a < or >, and nothing in the dom, then must be false + // UNLESS it was limited by another range in the other direction. + // Eg, >1.0.0 <1.0.1 is still a subset of <2.0.0 + if (gt && hasDomLT && !lt && gtltComp !== 0) { + return false } - return false -} -function testSet (set, version, options) { - for (var i = 0; i < set.length; i++) { - if (!set[i].test(version)) { - return false - } + if (lt && hasDomGT && !gt && gtltComp !== 0) { + return false } - if (version.prerelease.length && !options.includePrerelease) { - // Find the set of versions that are allowed to have prereleases - // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0 - // That should allow `1.2.3-pr.2` to pass. - // However, `1.2.4-alpha.notready` should NOT be allowed, - // even though it's within the range set by the comparators. - for (i = 0; i < set.length; i++) { - debug(set[i].semver) - if (set[i].semver === ANY) { - continue - } - - if (set[i].semver.prerelease.length > 0) { - var allowed = set[i].semver - if (allowed.major === version.major && - allowed.minor === version.minor && - allowed.patch === version.patch) { - return true - } - } - } - - // Version has a -pre, but it's not one of the ones we like. + // we needed a prerelease range in a specific tuple, but didn't get one + // then this isn't a subset. eg >=1.2.3-pre is not a subset of >=1.0.0, + // because it includes prereleases in the 1.2.3 tuple + if (needDomGTPre || needDomLTPre) { return false } return true } -exports.satisfies = satisfies -function satisfies (version, range, options) { - try { - range = new Range(range, options) - } catch (er) { - return false +// >=1.2.3 is lower than >1.2.3 +const higherGT = (a, b, options) => { + if (!a) { + return b } - return range.test(version) + const comp = compare(a.semver, b.semver, options) + return comp > 0 ? a + : comp < 0 ? b + : b.operator === '>' && a.operator === '>=' ? b + : a } -exports.maxSatisfying = maxSatisfying -function maxSatisfying (versions, range, options) { - var max = null - var maxSV = null - try { - var rangeObj = new Range(range, options) - } catch (er) { - return null +// <=1.2.3 is higher than <1.2.3 +const lowerLT = (a, b, options) => { + if (!a) { + return b } - versions.forEach(function (v) { - if (rangeObj.test(v)) { - // satisfies(v, range, options) - if (!max || maxSV.compare(v) === -1) { - // compare(max, v, true) - max = v - maxSV = new SemVer(max, options) - } - } - }) - return max + const comp = compare(a.semver, b.semver, options) + return comp < 0 ? a + : comp > 0 ? b + : b.operator === '<' && a.operator === '<=' ? b + : a } -exports.minSatisfying = minSatisfying -function minSatisfying (versions, range, options) { - var min = null - var minSV = null - try { - var rangeObj = new Range(range, options) - } catch (er) { - return null - } - versions.forEach(function (v) { - if (rangeObj.test(v)) { - // satisfies(v, range, options) - if (!min || minSV.compare(v) === 1) { - // compare(min, v, true) - min = v - minSV = new SemVer(min, options) - } - } - }) - return min -} +module.exports = subset -exports.minVersion = minVersion -function minVersion (range, loose) { - range = new Range(range, loose) - var minver = new SemVer('0.0.0') - if (range.test(minver)) { - return minver - } +/***/ }), - minver = new SemVer('0.0.0-0') - if (range.test(minver)) { - return minver - } +/***/ 2816: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - minver = null - for (var i = 0; i < range.set.length; ++i) { - var comparators = range.set[i] - comparators.forEach(function (comparator) { - // Clone to avoid manipulating the comparator's semver object. - var compver = new SemVer(comparator.semver.version) - switch (comparator.operator) { - case '>': - if (compver.prerelease.length === 0) { - compver.patch++ - } else { - compver.prerelease.push(0) - } - compver.raw = compver.format() - /* fallthrough */ - case '': - case '>=': - if (!minver || gt(minver, compver)) { - minver = compver - } - break - case '<': - case '<=': - /* Ignore maximum versions */ - break - /* istanbul ignore next */ - default: - throw new Error('Unexpected operation: ' + comparator.operator) - } - }) - } - if (minver && range.test(minver)) { - return minver - } +const Range = __nccwpck_require__(1699) - return null -} +// Mostly just for testing and legacy API reasons +const toComparators = (range, options) => + new Range(range, options).set + .map(comp => comp.map(c => c.value).join(' ').trim().split(' ')) + +module.exports = toComparators -exports.validRange = validRange -function validRange (range, options) { + +/***/ }), + +/***/ 1694: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + + + +const Range = __nccwpck_require__(1699) +const validRange = (range, options) => { try { // Return '*' instead of '' so that truthiness works. // This will throw if it's invalid anyway @@ -15718,11152 +11516,11832 @@ function validRange (range, options) { return null } } +module.exports = validRange -// Determine if version is less than all the versions possible in the range -exports.ltr = ltr -function ltr (version, range, options) { - return outside(version, range, '<', options) -} -// Determine if version is greater than all the versions possible in the range. -exports.gtr = gtr -function gtr (version, range, options) { - return outside(version, range, '>', options) -} +/***/ }), -exports.outside = outside -function outside (version, range, hilo, options) { - version = new SemVer(version, options) - range = new Range(range, options) +/***/ 6707: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - var gtfn, ltefn, ltfn, comp, ecomp - switch (hilo) { - case '>': - gtfn = gt - ltefn = lte - ltfn = lt - comp = '>' - ecomp = '>=' - break - case '<': - gtfn = lt - ltefn = gte - ltfn = gt - comp = '<' - ecomp = '<=' - break - default: - throw new TypeError('Must provide a hilo val of "<" or ">"') - } - // If it satisifes the range it is not outside - if (satisfies(version, range, options)) { - return false - } +const shebangRegex = __nccwpck_require__(8630); - // From now on, variable terms are as if we're in "gtr" mode. - // but note that everything is flipped for the "ltr" function. +module.exports = (string = '') => { + const match = string.match(shebangRegex); - for (var i = 0; i < range.set.length; ++i) { - var comparators = range.set[i] + if (!match) { + return null; + } - var high = null - var low = null + const [path, argument] = match[0].replace(/#! ?/, '').split(' '); + const binary = path.split('/').pop(); - comparators.forEach(function (comparator) { - if (comparator.semver === ANY) { - comparator = new Comparator('>=0.0.0') - } - high = high || comparator - low = low || comparator - if (gtfn(comparator.semver, high.semver, options)) { - high = comparator - } else if (ltfn(comparator.semver, low.semver, options)) { - low = comparator - } - }) + if (binary === 'env') { + return argument; + } - // If the edge version comparator has a operator then our version - // isn't outside it - if (high.operator === comp || high.operator === ecomp) { - return false - } + return argument ? `${binary} ${argument}` : binary; +}; - // If the lowest version comparator has an operator and our version - // is less than it then it isn't higher than the range - if ((!low.operator || low.operator === comp) && - ltefn(version, low.semver)) { - return false - } else if (low.operator === ecomp && ltfn(version, low.semver)) { - return false - } - } - return true -} -exports.prerelease = prerelease -function prerelease (version, options) { - var parsed = parse(version, options) - return (parsed && parsed.prerelease.length) ? parsed.prerelease : null -} +/***/ }), -exports.intersects = intersects -function intersects (r1, r2, options) { - r1 = new Range(r1, options) - r2 = new Range(r2, options) - return r1.intersects(r2) -} +/***/ 8630: +/***/ ((module) => { -exports.coerce = coerce -function coerce (version, options) { - if (version instanceof SemVer) { - return version - } - if (typeof version === 'number') { - version = String(version) - } +module.exports = /^#!(.*)/; - if (typeof version !== 'string') { - return null - } - options = options || {} +/***/ }), - var match = null - if (!options.rtl) { - match = version.match(safeRe[t.COERCE]) +/***/ 9834: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +// +// ShellJS +// Unix shell commands on top of Node's API +// +// Copyright (c) 2012 Artur Adib +// http://github.com/shelljs/shelljs +// + +var common = __nccwpck_require__(8400); + +module.exports = common.shell; + +//@ +//@ All commands run synchronously, unless otherwise stated. +//@ All commands accept standard bash globbing characters (`*`, `?`, etc.), +//@ compatible with [`fast-glob`](https://www.npmjs.com/package/fast-glob). +//@ +//@ For less-commonly used commands and features, please check out our [wiki +//@ page](https://github.com/shelljs/shelljs/wiki). +//@ + +// Include the docs for all the default commands +//@commands + +// Load all default commands. We import these for their side effect of loading +// using the plugin architecture via `common.register()`. +__nccwpck_require__(3049); +__nccwpck_require__(3046); +__nccwpck_require__(6884); +__nccwpck_require__(5405); +__nccwpck_require__(1642); +__nccwpck_require__(473); +__nccwpck_require__(2016); +__nccwpck_require__(1927); +__nccwpck_require__(2107); // A hint to the bundler to keep exec-child.js +__nccwpck_require__(9638); +__nccwpck_require__(573); +__nccwpck_require__(1787); +__nccwpck_require__(507); +__nccwpck_require__(4800); +__nccwpck_require__(850); +__nccwpck_require__(7314); +__nccwpck_require__(9844); +__nccwpck_require__(7653); +__nccwpck_require__(566); +__nccwpck_require__(6900); +__nccwpck_require__(7253); +__nccwpck_require__(2501); +__nccwpck_require__(1581); +__nccwpck_require__(8211); +__nccwpck_require__(1356); +__nccwpck_require__(4565); +__nccwpck_require__(7196); +__nccwpck_require__(6867); +__nccwpck_require__(9646); +__nccwpck_require__(8568); +__nccwpck_require__(9500); + +//@ +//@ ### exit(code) +//@ +//@ Exits the current process with the given exit `code`. +module.exports.exit = function exit(code) { + common.state.error = null; + common.state.errorCode = 0; + if (code) { + common.error('exit', { + continue: true, + code, + prefix: '', + silent: true, + fatal: false, + }); + process.exit(code); } else { - // Find the right-most coercible string that does not share - // a terminus with a more left-ward coercible string. - // Eg, '1.2.3.4' wants to coerce '2.3.4', not '3.4' or '4' - // - // Walk through the string checking with a /g regexp - // Manually set the index so as to pick up overlapping matches. - // Stop when we get a match that ends at the string end, since no - // coercible string can be more right-ward without the same terminus. - var next - while ((next = safeRe[t.COERCERTL].exec(version)) && - (!match || match.index + match[0].length !== version.length) - ) { - if (!match || - next.index + next[0].length !== match.index + match[0].length) { - match = next - } - safeRe[t.COERCERTL].lastIndex = next.index + next[1].length + next[2].length - } - // leave it in a clean state - safeRe[t.COERCERTL].lastIndex = -1 + process.exit(); } +}; - if (match === null) { - return null - } +//@include ./src/error.js +module.exports.error = __nccwpck_require__(123); - return parse(match[2] + - '.' + (match[3] || '0') + - '.' + (match[4] || '0'), options) -} +//@include ./src/errorCode.js +module.exports.errorCode = __nccwpck_require__(9650); +//@include ./src/common.js +module.exports.ShellString = common.ShellString; -/***/ }), +//@ +//@ ### env['VAR_NAME'] +//@ +//@ Object containing environment variables (both getter and setter). Shortcut +//@ to `process.env`. +module.exports.env = process.env; -/***/ 2514: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +//@ +//@ ### Pipes +//@ +//@ Examples: +//@ +//@ ```javascript +//@ grep('foo', 'file1.txt', 'file2.txt').sed(/o/g, 'a').to('output.txt'); +//@ echo("files with o's in the name:\n" + ls().grep('o')); +//@ cat('test.js').exec('node'); // pipe to exec() call +//@ ``` +//@ +//@ Commands can send their output to another command in a pipe-like fashion. +//@ `sed`, `grep`, `cat`, `exec`, `to`, and `toEnd` can appear on the right-hand +//@ side of a pipe. Pipes can be chained. -"use strict"; +//@ +//@ ## Configuration +//@ +module.exports.config = common.config; -const ANY = Symbol('SemVer ANY') -// hoisted class for cyclic dependency -class Comparator { - static get ANY () { - return ANY - } +//@ +//@ ### config.silent +//@ +//@ Example: +//@ +//@ ```javascript +//@ var sh = require('shelljs'); +//@ var silentState = sh.config.silent; // save old silent state +//@ sh.config.silent = true; +//@ /* ... */ +//@ sh.config.silent = silentState; // restore old silent state +//@ ``` +//@ +//@ Suppresses all command output if `true`, except for `echo()` calls. +//@ Default is `false`. - constructor (comp, options) { - options = parseOptions(options) +//@ +//@ ### config.fatal +//@ +//@ Example: +//@ +//@ ```javascript +//@ require('shelljs/global'); +//@ config.fatal = true; // or set('-e'); +//@ cp('this_file_does_not_exist', '/dev/null'); // throws Error here +//@ /* more commands... */ +//@ ``` +//@ +//@ If `true`, the script will throw a Javascript error when any shell.js +//@ command encounters an error. Default is `false`. This is analogous to +//@ Bash's `set -e`. - if (comp instanceof Comparator) { - if (comp.loose === !!options.loose) { - return comp - } else { - comp = comp.value - } - } +//@ +//@ ### config.verbose +//@ +//@ Example: +//@ +//@ ```javascript +//@ config.verbose = true; // or set('-v'); +//@ cd('dir/'); +//@ rm('-rf', 'foo.txt', 'bar.txt'); +//@ exec('echo hello'); +//@ ``` +//@ +//@ Will print each command as follows: +//@ +//@ ``` +//@ cd dir/ +//@ rm -rf foo.txt bar.txt +//@ exec echo hello +//@ ``` - comp = comp.trim().split(/\s+/).join(' ') - debug('comparator', comp, options) - this.options = options - this.loose = !!options.loose - this.parse(comp) +//@ +//@ ### config.globOptions (deprecated) +//@ +//@ **Deprecated**: we recommend that you do not edit `config.globOptions`. +//@ Support for this configuration option may be changed or removed in a future +//@ ShellJS release. +//@ +//@ **Breaking change**: ShellJS v0.8.x uses `node-glob`. Starting with ShellJS +//@ v0.9.x, `config.globOptions` is compatible with `fast-glob`. +//@ +//@ Example: +//@ +//@ ```javascript +//@ config.globOptions = {nodir: true}; +//@ ``` +//@ +//@ `config.globOptions` changes how ShellJS expands glob (wildcard) +//@ expressions. See +//@ [fast-glob](https://github.com/mrmlnc/fast-glob?tab=readme-ov-file#options-3) +//@ for available options. Be aware that modifying `config.globOptions` **may +//@ break ShellJS functionality.** - if (this.semver === ANY) { - this.value = '' - } else { - this.value = this.operator + this.semver.version - } +//@ +//@ ### config.reset() +//@ +//@ Example: +//@ +//@ ```javascript +//@ var shell = require('shelljs'); +//@ // Make changes to shell.config, and do stuff... +//@ /* ... */ +//@ shell.config.reset(); // reset to original state +//@ // Do more stuff, but with original settings +//@ /* ... */ +//@ ``` +//@ +//@ Reset `shell.config` to the defaults: +//@ +//@ ```javascript +//@ { +//@ fatal: false, +//@ globOptions: {}, +//@ maxdepth: 255, +//@ noglob: false, +//@ silent: false, +//@ verbose: false, +//@ } +//@ ``` - debug('comp', this) - } - parse (comp) { - const r = this.options.loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR] - const m = comp.match(r) +/***/ }), - if (!m) { - throw new TypeError(`Invalid comparator: ${comp}`) - } +/***/ 3049: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - this.operator = m[1] !== undefined ? m[1] : '' - if (this.operator === '=') { - this.operator = '' - } +var fs = __nccwpck_require__(9896); +var common = __nccwpck_require__(8400); - // if it literally is just '>' or '' then allow anything. - if (!m[2]) { - this.semver = ANY - } else { - this.semver = new SemVer(m[2], this.options.loose) - } - } +common.register('cat', _cat, { + canReceivePipe: true, + cmdOptions: { + 'n': 'number', + }, +}); - toString () { - return this.value - } +//@ +//@ ### cat([options,] file [, file ...]) +//@ ### cat([options,] file_array) +//@ +//@ Available options: +//@ +//@ + `-n`: number all output lines +//@ +//@ Examples: +//@ +//@ ```javascript +//@ var str = cat('file*.txt'); +//@ var str = cat('file1', 'file2'); +//@ var str = cat(['file1', 'file2']); // same as above +//@ ``` +//@ +//@ Returns a [ShellString](#shellstringstr) containing the given file, or a +//@ concatenated string containing the files if more than one file is given (a +//@ new line character is introduced between each file). +function _cat(options, files) { + var cat = common.readFromPipe(); - test (version) { - debug('Comparator.test', version, this.options.loose) + if (!files && !cat) common.error('no paths given'); - if (this.semver === ANY || version === ANY) { - return true - } + files = [].slice.call(arguments, 1); - if (typeof version === 'string') { - try { - version = new SemVer(version, this.options) - } catch (er) { - return false - } + files.forEach(function (file) { + if (!fs.existsSync(file)) { + common.error('no such file or directory: ' + file); + } else if (common.statFollowLinks(file).isDirectory()) { + common.error(file + ': Is a directory'); } - return cmp(version, this.operator, this.semver, this.options) - } + cat += fs.readFileSync(file, 'utf8'); + }); - intersects (comp, options) { - if (!(comp instanceof Comparator)) { - throw new TypeError('a Comparator is required') - } + if (options.number) { + cat = addNumbers(cat); + } - if (this.operator === '') { - if (this.value === '') { - return true - } - return new Range(comp.value, options).test(this.value) - } else if (comp.operator === '') { - if (comp.value === '') { - return true - } - return new Range(this.value, options).test(comp.semver) - } + return cat; +} +module.exports = _cat; - options = parseOptions(options) +function addNumbers(cat) { + var lines = cat.split('\n'); + var lastLine = lines.pop(); - // Special cases where nothing can possibly be lower - if (options.includePrerelease && - (this.value === '<0.0.0-0' || comp.value === '<0.0.0-0')) { - return false - } - if (!options.includePrerelease && - (this.value.startsWith('<0.0.0') || comp.value.startsWith('<0.0.0'))) { - return false - } + lines = lines.map(function (line, i) { + return numberedLine(i + 1, line); + }); - // Same direction increasing (> or >=) - if (this.operator.startsWith('>') && comp.operator.startsWith('>')) { - return true - } - // Same direction decreasing (< or <=) - if (this.operator.startsWith('<') && comp.operator.startsWith('<')) { - return true - } - // same SemVer and both sides are inclusive (<= or >=) - if ( - (this.semver.version === comp.semver.version) && - this.operator.includes('=') && comp.operator.includes('=')) { - return true - } - // opposite directions less than - if (cmp(this.semver, '<', comp.semver, options) && - this.operator.startsWith('>') && comp.operator.startsWith('<')) { - return true - } - // opposite directions greater than - if (cmp(this.semver, '>', comp.semver, options) && - this.operator.startsWith('<') && comp.operator.startsWith('>')) { - return true - } - return false + if (lastLine.length) { + lastLine = numberedLine(lines.length + 1, lastLine); } -} + lines.push(lastLine); -module.exports = Comparator + return lines.join('\n'); +} -const parseOptions = __nccwpck_require__(9373) -const { safeRe: re, t } = __nccwpck_require__(3032) -const cmp = __nccwpck_require__(1941) -const debug = __nccwpck_require__(6018) -const SemVer = __nccwpck_require__(2478) -const Range = __nccwpck_require__(8037) +function numberedLine(n, line) { + // GNU cat use six pad start number + tab. See http://lingrok.org/xref/coreutils/src/cat.c#57 + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart + var number = (' ' + n).slice(-6) + '\t'; + return number + line; +} /***/ }), -/***/ 8037: +/***/ 3046: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; - +var os = __nccwpck_require__(857); +var common = __nccwpck_require__(8400); -const SPACE_CHARACTERS = /\s+/g +common.register('cd', _cd, {}); -// hoisted class for cyclic dependency -class Range { - constructor (range, options) { - options = parseOptions(options) +//@ +//@ ### cd([dir]) +//@ +//@ Changes to directory `dir` for the duration of the script. Changes to home +//@ directory if no argument is supplied. Returns a +//@ [ShellString](#shellstringstr) to indicate success or failure. +function _cd(options, dir) { + if (!dir) dir = os.homedir(); - if (range instanceof Range) { - if ( - range.loose === !!options.loose && - range.includePrerelease === !!options.includePrerelease - ) { - return range - } else { - return new Range(range.raw, options) - } + if (dir === '-') { + if (!process.env.OLDPWD) { + common.error('could not find previous directory'); + } else { + dir = process.env.OLDPWD; } + } - if (range instanceof Comparator) { - // just put it in the set and return - this.raw = range.value - this.set = [[range]] - this.formatted = undefined - return this + try { + var curDir = process.cwd(); + process.chdir(dir); + process.env.OLDPWD = curDir; + } catch (e) { + // something went wrong, let's figure out the error + var err; + try { + common.statFollowLinks(dir); // if this succeeds, it must be some sort of file + err = 'not a directory: ' + dir; + } catch (e2) { + err = 'no such file or directory: ' + dir; } + if (err) common.error(err); + } + return ''; +} +module.exports = _cd; - this.options = options - this.loose = !!options.loose - this.includePrerelease = !!options.includePrerelease - - // First reduce all whitespace as much as possible so we do not have to rely - // on potentially slow regexes like \s*. This is then stored and used for - // future error messages as well. - this.raw = range.trim().replace(SPACE_CHARACTERS, ' ') - // First, split on || - this.set = this.raw - .split('||') - // map the range to a 2d array of comparators - .map(r => this.parseRange(r.trim())) - // throw out any comparator lists that are empty - // this generally means that it was not a valid range, which is allowed - // in loose mode, but will still throw if the WHOLE range is invalid. - .filter(c => c.length) +/***/ }), - if (!this.set.length) { - throw new TypeError(`Invalid SemVer Range: ${this.raw}`) - } +/***/ 6884: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - // if we have any that are not the null set, throw out null sets. - if (this.set.length > 1) { - // keep the first one, in case they're all null sets - const first = this.set[0] - this.set = this.set.filter(c => !isNullSet(c[0])) - if (this.set.length === 0) { - this.set = [first] - } else if (this.set.length > 1) { - // if we have any that are *, then the range is just * - for (const c of this.set) { - if (c.length === 1 && isAny(c[0])) { - this.set = [c] - break - } - } - } - } +var fs = __nccwpck_require__(9896); +var path = __nccwpck_require__(6928); +var common = __nccwpck_require__(8400); - this.formatted = undefined - } +var PERMS = (function (base) { + return { + OTHER_EXEC: base.EXEC, + OTHER_WRITE: base.WRITE, + OTHER_READ: base.READ, - get range () { - if (this.formatted === undefined) { - this.formatted = '' - for (let i = 0; i < this.set.length; i++) { - if (i > 0) { - this.formatted += '||' - } - const comps = this.set[i] - for (let k = 0; k < comps.length; k++) { - if (k > 0) { - this.formatted += ' ' - } - this.formatted += comps[k].toString().trim() - } - } - } - return this.formatted - } + GROUP_EXEC: base.EXEC << 3, + GROUP_WRITE: base.WRITE << 3, + GROUP_READ: base.READ << 3, - format () { - return this.range - } + OWNER_EXEC: base.EXEC << 6, + OWNER_WRITE: base.WRITE << 6, + OWNER_READ: base.READ << 6, - toString () { - return this.range - } + // Literal octal numbers are apparently not allowed in "strict" javascript. + STICKY: parseInt('01000', 8), + SETGID: parseInt('02000', 8), + SETUID: parseInt('04000', 8), - parseRange (range) { - // memoize range parsing for performance. - // this is a very hot path, and fully deterministic. - const memoOpts = - (this.options.includePrerelease && FLAG_INCLUDE_PRERELEASE) | - (this.options.loose && FLAG_LOOSE) - const memoKey = memoOpts + ':' + range - const cached = cache.get(memoKey) - if (cached) { - return cached - } + TYPE_MASK: parseInt('0770000', 8), + }; +}({ + EXEC: 1, + WRITE: 2, + READ: 4, +})); - const loose = this.options.loose - // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4` - const hr = loose ? re[t.HYPHENRANGELOOSE] : re[t.HYPHENRANGE] - range = range.replace(hr, hyphenReplace(this.options.includePrerelease)) - debug('hyphen replace', range) +common.register('chmod', _chmod, { +}); - // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5` - range = range.replace(re[t.COMPARATORTRIM], comparatorTrimReplace) - debug('comparator trim', range) +//@ +//@ ### chmod([options,] octal_mode || octal_string, file) +//@ ### chmod([options,] symbolic_mode, file) +//@ +//@ Available options: +//@ +//@ + `-v`: output a diagnostic for every file processed//@ +//@ + `-c`: like verbose, but report only when a change is made//@ +//@ + `-R`: change files and directories recursively//@ +//@ +//@ Examples: +//@ +//@ ```javascript +//@ chmod(755, '/Users/brandon'); +//@ chmod('755', '/Users/brandon'); // same as above +//@ chmod('u+x', '/Users/brandon'); +//@ chmod('-R', 'a-w', '/Users/brandon'); +//@ ``` +//@ +//@ Alters the permissions of a file or directory by either specifying the +//@ absolute permissions in octal form or expressing the changes in symbols. +//@ This command tries to mimic the POSIX behavior as much as possible. +//@ Notable exceptions: +//@ +//@ + In symbolic modes, `a-r` and `-r` are identical. No consideration is +//@ given to the `umask`. +//@ + There is no "quiet" option, since default behavior is to run silent. +//@ + Windows OS uses a very different permission model than POSIX. `chmod()` +//@ does its best on Windows, but there are limits to how file permissions can +//@ be set. Note that WSL (Windows subsystem for Linux) **does** follow POSIX, +//@ so cross-platform compatibility should not be a concern there. +//@ +//@ Returns a [ShellString](#shellstringstr) indicating success or failure. +function _chmod(options, mode, filePattern) { + if (!filePattern) { + if (options.length > 0 && options.charAt(0) === '-') { + // Special case where the specified file permissions started with - to subtract perms, which + // get picked up by the option parser as command flags. + // If we are down by one argument and options starts with -, shift everything over. + [].unshift.call(arguments, ''); + } else { + common.error('You must specify a file.'); + } + } - // `~ 1.2.3` => `~1.2.3` - range = range.replace(re[t.TILDETRIM], tildeTrimReplace) - debug('tilde trim', range) + options = common.parseOptions(options, { + 'R': 'recursive', + 'c': 'changes', + 'v': 'verbose', + }); - // `^ 1.2.3` => `^1.2.3` - range = range.replace(re[t.CARETTRIM], caretTrimReplace) - debug('caret trim', range) + filePattern = [].slice.call(arguments, 2); - // At this point, the range is completely trimmed and - // ready to be split into comparators. + var files; - let rangeList = range - .split(' ') - .map(comp => parseComparator(comp, this.options)) - .join(' ') - .split(/\s+/) - // >=0.0.0 is equivalent to * - .map(comp => replaceGTE0(comp, this.options)) + // TODO: replace this with a call to common.expand() + if (options.recursive) { + files = []; + filePattern.forEach(function addFile(expandedFile) { + var stat = common.statNoFollowLinks(expandedFile); - if (loose) { - // in loose mode, throw out any that are not valid comparators - rangeList = rangeList.filter(comp => { - debug('loose invalid filter', comp, this.options) - return !!comp.match(re[t.COMPARATORLOOSE]) - }) - } - debug('range list', rangeList) + if (!stat.isSymbolicLink()) { + files.push(expandedFile); - // if any comparators are the null set, then replace with JUST null set - // if more than one comparator, remove any * comparators - // also, don't include the same comparator more than once - const rangeMap = new Map() - const comparators = rangeList.map(comp => new Comparator(comp, this.options)) - for (const comp of comparators) { - if (isNullSet(comp)) { - return [comp] + if (stat.isDirectory()) { // intentionally does not follow symlinks. + fs.readdirSync(expandedFile).forEach(function (child) { + addFile(expandedFile + '/' + child); + }); + } } - rangeMap.set(comp.value, comp) - } - if (rangeMap.size > 1 && rangeMap.has('')) { - rangeMap.delete('') - } - - const result = [...rangeMap.values()] - cache.set(memoKey, result) - return result - } - - intersects (range, options) { - if (!(range instanceof Range)) { - throw new TypeError('a Range is required') - } - - return this.set.some((thisComparators) => { - return ( - isSatisfiable(thisComparators, options) && - range.set.some((rangeComparators) => { - return ( - isSatisfiable(rangeComparators, options) && - thisComparators.every((thisComparator) => { - return rangeComparators.every((rangeComparator) => { - return thisComparator.intersects(rangeComparator, options) - }) - }) - ) - }) - ) - }) + }); + } else { + files = filePattern; } - // if ANY of the sets match ALL of its comparators, then pass - test (version) { - if (!version) { - return false - } - - if (typeof version === 'string') { - try { - version = new SemVer(version, this.options) - } catch (er) { - return false - } + files.forEach(function innerChmod(file) { + file = path.resolve(file); + if (!fs.existsSync(file)) { + common.error('File not found: ' + file); } - for (let i = 0; i < this.set.length; i++) { - if (testSet(this.set[i], version, this.options)) { - return true - } + // When recursing, don't follow symlinks. + if (options.recursive && common.statNoFollowLinks(file).isSymbolicLink()) { + return; } - return false - } -} - -module.exports = Range -const LRU = __nccwpck_require__(6684) -const cache = new LRU() - -const parseOptions = __nccwpck_require__(9373) -const Comparator = __nccwpck_require__(2514) -const debug = __nccwpck_require__(6018) -const SemVer = __nccwpck_require__(2478) -const { - safeRe: re, - t, - comparatorTrimReplace, - tildeTrimReplace, - caretTrimReplace, -} = __nccwpck_require__(3032) -const { FLAG_INCLUDE_PRERELEASE, FLAG_LOOSE } = __nccwpck_require__(7108) + var stat = common.statFollowLinks(file); + var isDir = stat.isDirectory(); + var perms = stat.mode; + var type = perms & PERMS.TYPE_MASK; -const isNullSet = c => c.value === '<0.0.0-0' -const isAny = c => c.value === '' + var newPerms = perms; -// take a set of comparators and determine whether there -// exists a version which can satisfy it -const isSatisfiable = (comparators, options) => { - let result = true - const remainingComparators = comparators.slice() - let testComparator = remainingComparators.pop() + if (Number.isNaN(parseInt(mode, 8))) { + // parse options + mode.split(',').forEach(function (symbolicMode) { + var pattern = /([ugoa]*)([=+-])([rwxXst]*)/i; + var matches = pattern.exec(symbolicMode); - while (result && remainingComparators.length) { - result = remainingComparators.every((otherComparator) => { - return testComparator.intersects(otherComparator, options) - }) + if (matches) { + var applyTo = matches[1]; + var operator = matches[2]; + var change = matches[3]; - testComparator = remainingComparators.pop() - } + var changeOwner = applyTo.includes('u') || applyTo === 'a' || applyTo === ''; + var changeGroup = applyTo.includes('g') || applyTo === 'a' || applyTo === ''; + var changeOther = applyTo.includes('o') || applyTo === 'a' || applyTo === ''; - return result -} + var changeRead = change.includes('r'); + var changeWrite = change.includes('w'); + var changeExec = change.includes('x'); + var changeExecDir = change.includes('X'); + var changeSticky = change.includes('t'); + var changeSetuid = change.includes('s'); -// comprised of xranges, tildes, stars, and gtlt's at this point. -// already replaced the hyphen ranges -// turn into a set of JUST comparators. -const parseComparator = (comp, options) => { - comp = comp.replace(re[t.BUILD], '') - debug('comp', comp, options) - comp = replaceCarets(comp, options) - debug('caret', comp) - comp = replaceTildes(comp, options) - debug('tildes', comp) - comp = replaceXRanges(comp, options) - debug('xrange', comp) - comp = replaceStars(comp, options) - debug('stars', comp) - return comp -} + if (changeExecDir && isDir) { + changeExec = true; + } -const isX = id => !id || id.toLowerCase() === 'x' || id === '*' + var mask = 0; + if (changeOwner) { + mask |= (changeRead ? PERMS.OWNER_READ : 0) + (changeWrite ? PERMS.OWNER_WRITE : 0) + (changeExec ? PERMS.OWNER_EXEC : 0) + (changeSetuid ? PERMS.SETUID : 0); + } + if (changeGroup) { + mask |= (changeRead ? PERMS.GROUP_READ : 0) + (changeWrite ? PERMS.GROUP_WRITE : 0) + (changeExec ? PERMS.GROUP_EXEC : 0) + (changeSetuid ? PERMS.SETGID : 0); + } + if (changeOther) { + mask |= (changeRead ? PERMS.OTHER_READ : 0) + (changeWrite ? PERMS.OTHER_WRITE : 0) + (changeExec ? PERMS.OTHER_EXEC : 0); + } -// ~, ~> --> * (any, kinda silly) -// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0-0 -// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0-0 -// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0-0 -// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0-0 -// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0-0 -// ~0.0.1 --> >=0.0.1 <0.1.0-0 -const replaceTildes = (comp, options) => { - return comp - .trim() - .split(/\s+/) - .map((c) => replaceTilde(c, options)) - .join(' ') -} + // Sticky bit is special - it's not tied to user, group or other. + if (changeSticky) { + mask |= PERMS.STICKY; + } -const replaceTilde = (comp, options) => { - const r = options.loose ? re[t.TILDELOOSE] : re[t.TILDE] - return comp.replace(r, (_, M, m, p, pr) => { - debug('tilde', comp, _, M, m, p, pr) - let ret + switch (operator) { + case '+': + newPerms |= mask; + break; - if (isX(M)) { - ret = '' - } else if (isX(m)) { - ret = `>=${M}.0.0 <${+M + 1}.0.0-0` - } else if (isX(p)) { - // ~1.2 == >=1.2.0 <1.3.0-0 - ret = `>=${M}.${m}.0 <${M}.${+m + 1}.0-0` - } else if (pr) { - debug('replaceTilde pr', pr) - ret = `>=${M}.${m}.${p}-${pr - } <${M}.${+m + 1}.0-0` - } else { - // ~1.2.3 == >=1.2.3 <1.3.0-0 - ret = `>=${M}.${m}.${p - } <${M}.${+m + 1}.0-0` - } + case '-': + newPerms &= ~mask; + break; - debug('tilde return', ret) - return ret - }) -} + case '=': + newPerms = type + mask; -// ^ --> * (any, kinda silly) -// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0-0 -// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0-0 -// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0-0 -// ^1.2.3 --> >=1.2.3 <2.0.0-0 -// ^1.2.0 --> >=1.2.0 <2.0.0-0 -// ^0.0.1 --> >=0.0.1 <0.0.2-0 -// ^0.1.0 --> >=0.1.0 <0.2.0-0 -const replaceCarets = (comp, options) => { - return comp - .trim() - .split(/\s+/) - .map((c) => replaceCaret(c, options)) - .join(' ') -} + // According to POSIX, when using = to explicitly set the + // permissions, setuid and setgid can never be cleared. + if (common.statFollowLinks(file).isDirectory()) { + newPerms |= (PERMS.SETUID + PERMS.SETGID) & perms; + } + break; + default: + common.error('Could not recognize operator: `' + operator + '`'); + } -const replaceCaret = (comp, options) => { - debug('caret', comp, options) - const r = options.loose ? re[t.CARETLOOSE] : re[t.CARET] - const z = options.includePrerelease ? '-0' : '' - return comp.replace(r, (_, M, m, p, pr) => { - debug('caret', comp, _, M, m, p, pr) - let ret + if (options.verbose) { + console.log(file + ' -> ' + newPerms.toString(8)); + } - if (isX(M)) { - ret = '' - } else if (isX(m)) { - ret = `>=${M}.0.0${z} <${+M + 1}.0.0-0` - } else if (isX(p)) { - if (M === '0') { - ret = `>=${M}.${m}.0${z} <${M}.${+m + 1}.0-0` - } else { - ret = `>=${M}.${m}.0${z} <${+M + 1}.0.0-0` - } - } else if (pr) { - debug('replaceCaret pr', pr) - if (M === '0') { - if (m === '0') { - ret = `>=${M}.${m}.${p}-${pr - } <${M}.${m}.${+p + 1}-0` + if (perms !== newPerms) { + if (!options.verbose && options.changes) { + console.log(file + ' -> ' + newPerms.toString(8)); + } + fs.chmodSync(file, newPerms); + perms = newPerms; // for the next round of changes! + } } else { - ret = `>=${M}.${m}.${p}-${pr - } <${M}.${+m + 1}.0-0` + common.error('Invalid symbolic mode change: ' + symbolicMode); } - } else { - ret = `>=${M}.${m}.${p}-${pr - } <${+M + 1}.0.0-0` - } + }); } else { - debug('no pr') - if (M === '0') { - if (m === '0') { - ret = `>=${M}.${m}.${p - }${z} <${M}.${m}.${+p + 1}-0` - } else { - ret = `>=${M}.${m}.${p - }${z} <${M}.${+m + 1}.0-0` - } - } else { - ret = `>=${M}.${m}.${p - } <${+M + 1}.0.0-0` - } - } + // they gave us a full number + newPerms = type + parseInt(mode, 8); - debug('caret return', ret) - return ret - }) -} + // POSIX rules are that setuid and setgid can only be added using numeric + // form, but not cleared. + if (common.statFollowLinks(file).isDirectory()) { + newPerms |= (PERMS.SETUID + PERMS.SETGID) & perms; + } -const replaceXRanges = (comp, options) => { - debug('replaceXRanges', comp, options) - return comp - .split(/\s+/) - .map((c) => replaceXRange(c, options)) - .join(' ') + fs.chmodSync(file, newPerms); + } + }); + return ''; } +module.exports = _chmod; -const replaceXRange = (comp, options) => { - comp = comp.trim() - const r = options.loose ? re[t.XRANGELOOSE] : re[t.XRANGE] - return comp.replace(r, (ret, gtlt, M, m, p, pr) => { - debug('xRange', comp, ret, gtlt, M, m, p, pr) - const xM = isX(M) - const xm = xM || isX(m) - const xp = xm || isX(p) - const anyX = xp - - if (gtlt === '=' && anyX) { - gtlt = '' - } - // if we're including prereleases in the match, then we need - // to fix this to -0, the lowest possible prerelease value - pr = options.includePrerelease ? '-0' : '' +/***/ }), - if (xM) { - if (gtlt === '>' || gtlt === '<') { - // nothing is allowed - ret = '<0.0.0-0' - } else { - // nothing is forbidden - ret = '*' - } - } else if (gtlt && anyX) { - // we know patch is an x, because we have any x at all. - // replace X with 0 - if (xm) { - m = 0 - } - p = 0 +/***/ 5405: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - if (gtlt === '>') { - // >1 => >=2.0.0 - // >1.2 => >=1.3.0 - gtlt = '>=' - if (xm) { - M = +M + 1 - m = 0 - p = 0 - } else { - m = +m + 1 - p = 0 - } - } else if (gtlt === '<=') { - // <=0.7.x is actually <0.8.0, since any 0.7.x should - // pass. Similarly, <=7.x is actually <8.0.0, etc. - gtlt = '<' - if (xm) { - M = +M + 1 - } else { - m = +m + 1 - } - } +var execa = __nccwpck_require__(2706); +var common = __nccwpck_require__(8400); - if (gtlt === '<') { - pr = '-0' - } +var DEFAULT_MAXBUFFER_SIZE = 20 * 1024 * 1024; +var COMMAND_NOT_FOUND_ERROR_CODE = 127; - ret = `${gtlt + M}.${m}.${p}${pr}` - } else if (xm) { - ret = `>=${M}.0.0${pr} <${+M + 1}.0.0-0` - } else if (xp) { - ret = `>=${M}.${m}.0${pr - } <${M}.${+m + 1}.0-0` - } +common.register('cmd', _cmd, { + cmdOptions: null, + globStart: 1, + canReceivePipe: true, + wrapOutput: true, +}); - debug('xRange return', ret) +function isCommandNotFound(execaResult) { + if (process.platform === 'win32') { + var str = 'is not recognized as an internal or external command'; + return execaResult.exitCode && execaResult.stderr.includes(str); + } + return execaResult.failed && execaResult.code === 'ENOENT'; +} - return ret - }) +function isExecaInternalError(result) { + if (typeof result.stdout !== 'string') return true; + if (typeof result.stderr !== 'string') return true; + if (typeof result.exitCode !== 'number') return true; + if (result.exitCode === 0 && result.failed) return true; + // Otherwise assume this executed correctly. The command may still have exited + // with non-zero status, but that's not due to anything execa did. + return false; } -// Because * is AND-ed with everything else in the comparator, -// and '' means "any version", just remove the *s entirely. -const replaceStars = (comp, options) => { - debug('replaceStars', comp, options) - // Looseness is ignored here. star is always as loose as it gets! - return comp - .trim() - .replace(re[t.STAR], '') -} +//@ +//@ ### cmd(arg1[, arg2, ...] [, options]) +//@ +//@ Available options: +//@ +//@ + `cwd: directoryPath`: change the current working directory only for this +//@ cmd() invocation. +//@ + `maxBuffer: num`: Raise or decrease the default buffer size for +//@ stdout/stderr. +//@ + `timeout`: Change the default timeout. +//@ +//@ Examples: +//@ +//@ ```javascript +//@ var version = cmd('node', '--version').stdout; +//@ cmd('git', 'commit', '-am', `Add suport for node ${version}`); +//@ console.log(cmd('echo', '1st arg', '2nd arg', '3rd arg').stdout) +//@ console.log(cmd('echo', 'this handles ;, |, &, etc. as literal characters').stdout) +//@ ``` +//@ +//@ Executes the given command synchronously. This is intended as an easier +//@ alternative for [exec()](#execcommand--options--callback), with better +//@ security around globbing, comamnd injection, and variable expansion. This is +//@ guaranteed to only run one external command, and won't give special +//@ treatment for any shell characters (ex. this treats `|` as a literal +//@ character, not as a shell pipeline). +//@ This returns a [ShellString](#shellstringstr). +//@ +//@ By default, this performs globbing on all platforms, but you can disable +//@ this with `set('-f')`. +//@ +//@ This **does not** support asynchronous mode. If you need asynchronous +//@ command execution, check out [execa](https://www.npmjs.com/package/execa) or +//@ the node builtin `child_process.execFile()` instead. +function _cmd(options, command, commandArgs, userOptions) { + if (!command) { + common.error('Must specify a non-empty string as a command'); + } -const replaceGTE0 = (comp, options) => { - debug('replaceGTE0', comp, options) - return comp - .trim() - .replace(re[options.includePrerelease ? t.GTE0PRE : t.GTE0], '') -} + // `options` will usually not have a value: it's added by our commandline flag + // parsing engine. + commandArgs = [].slice.call(arguments, 2); -// This function is passed to string.replace(re[t.HYPHENRANGE]) -// M, m, patch, prerelease, build -// 1.2 - 3.4.5 => >=1.2.0 <=3.4.5 -// 1.2.3 - 3.4 => >=1.2.0 <3.5.0-0 Any 3.4.x will do -// 1.2 - 3.4 => >=1.2.0 <3.5.0-0 -// TODO build? -const hyphenReplace = incPr => ($0, - from, fM, fm, fp, fpr, fb, - to, tM, tm, tp, tpr) => { - if (isX(fM)) { - from = '' - } else if (isX(fm)) { - from = `>=${fM}.0.0${incPr ? '-0' : ''}` - } else if (isX(fp)) { - from = `>=${fM}.${fm}.0${incPr ? '-0' : ''}` - } else if (fpr) { - from = `>=${from}` + // `userOptions` may or may not be provided. We need to check the last + // argument. If it's an object, assume it's meant to be passed as + // userOptions (since ShellStrings are already flattened to strings). + if (commandArgs.length === 0) { + userOptions = {}; } else { - from = `>=${from}${incPr ? '-0' : ''}` + var lastArg = commandArgs.pop(); + if (common.isObject(lastArg)) { + userOptions = lastArg; + } else { + userOptions = {}; + commandArgs.push(lastArg); + } } - if (isX(tM)) { - to = '' - } else if (isX(tm)) { - to = `<${+tM + 1}.0.0-0` - } else if (isX(tp)) { - to = `<${tM}.${+tm + 1}.0-0` - } else if (tpr) { - to = `<=${tM}.${tm}.${tp}-${tpr}` - } else if (incPr) { - to = `<${tM}.${tm}.${+tp + 1}-0` + var pipe = common.readFromPipe(); + + // Some of our defaults differ from execa's defaults. These can be overridden + // by the user. + var defaultOptions = { + maxBuffer: DEFAULT_MAXBUFFER_SIZE, + stripFinalNewline: false, // Preserve trailing newlines for consistency with unix. + reject: false, // Use ShellJS's error handling system. + }; + + // For other options, we forbid the user from overriding them (either for + // correctness or security). + var requiredOptions = { + input: pipe, + shell: false, + }; + + var execaOptions = + Object.assign(defaultOptions, userOptions, requiredOptions); + + var result = execa.sync(command, commandArgs, execaOptions); + var stdout; + var stderr; + var code; + if (isCommandNotFound(result)) { + // This can happen if `command` is not an executable binary, or possibly + // under other conditions. + stdout = ''; + stderr = "'" + command + "': command not found"; + code = COMMAND_NOT_FOUND_ERROR_CODE; + } else if (isExecaInternalError(result)) { + // Catch-all: execa tried to run `command` but it encountered some error + // (ex. maxBuffer, timeout). + stdout = result.stdout || ''; + stderr = result.stderr || + `'${command}' encountered an error during execution`; + code = result.exitCode !== undefined && result.exitCode > 0 ? result.exitCode : 1; } else { - to = `<=${to}` + // Normal exit: execa was able to execute `command` and get a return value. + stdout = result.stdout.toString(); + stderr = result.stderr.toString(); + code = result.exitCode; } - return `${from} ${to}`.trim() + // Pass `continue: true` so we can specify a value for stdout. + if (code) common.error(stderr, code, { silent: true, continue: true }); + return new common.ShellString(stdout, stderr, code); } +module.exports = _cmd; -const testSet = (set, version, options) => { - for (let i = 0; i < set.length; i++) { - if (!set[i].test(version)) { - return false - } - } - if (version.prerelease.length && !options.includePrerelease) { - // Find the set of versions that are allowed to have prereleases - // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0 - // That should allow `1.2.3-pr.2` to pass. - // However, `1.2.4-alpha.notready` should NOT be allowed, - // even though it's within the range set by the comparators. - for (let i = 0; i < set.length; i++) { - debug(set[i].semver) - if (set[i].semver === Comparator.ANY) { - continue - } +/***/ }), - if (set[i].semver.prerelease.length > 0) { - const allowed = set[i].semver - if (allowed.major === version.major && - allowed.minor === version.minor && - allowed.patch === version.patch) { - return true - } - } - } +/***/ 8400: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - // Version has a -pre, but it's not one of the ones we like. - return false - } +// Ignore warning about 'new String()' and use of the Buffer constructor +/* eslint no-new-wrappers: "off", + no-buffer-constructor: "off" */ - return true -} -/***/ }), +var os = __nccwpck_require__(857); +var fs = __nccwpck_require__(9896); +var glob = __nccwpck_require__(2206); -/***/ 2478: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +var shell = {}; +exports.shell = shell; -"use strict"; +var shellMethods = Object.create(shell); +exports.extend = Object.assign; -const debug = __nccwpck_require__(6018) -const { MAX_LENGTH, MAX_SAFE_INTEGER } = __nccwpck_require__(7108) -const { safeRe: re, t } = __nccwpck_require__(3032) +// Check if we're running under electron +var isElectron = Boolean(process.versions.electron); -const parseOptions = __nccwpck_require__(9373) -const { compareIdentifiers } = __nccwpck_require__(5341) -class SemVer { - constructor (version, options) { - options = parseOptions(options) +// Module globals (assume no execPath by default) +var DEFAULT_CONFIG = { + fatal: false, + globOptions: {}, + maxdepth: 255, + noglob: false, + silent: false, + verbose: false, + execPath: null, + bufLength: 64 * 1024, // 64KB +}; - if (version instanceof SemVer) { - if (version.loose === !!options.loose && - version.includePrerelease === !!options.includePrerelease) { - return version - } else { - version = version.version - } - } else if (typeof version !== 'string') { - throw new TypeError(`Invalid version. Must be a string. Got type "${typeof version}".`) +var config = { + reset() { + Object.assign(this, DEFAULT_CONFIG); + if (!isElectron) { + this.execPath = process.execPath; } + }, + resetForTesting() { + this.reset(); + this.silent = true; + }, +}; - if (version.length > MAX_LENGTH) { - throw new TypeError( - `version is longer than ${MAX_LENGTH} characters` - ) - } +config.reset(); +exports.config = config; - debug('SemVer', version, options) - this.options = options - this.loose = !!options.loose - // this isn't actually relevant for versions, but keep it so that we - // don't run into trouble passing this.options around. - this.includePrerelease = !!options.includePrerelease +// Note: commands should generally consider these as read-only values. +var state = { + error: null, + errorCode: 0, + currentCmd: 'shell.js', +}; +exports.state = state; - const m = version.trim().match(options.loose ? re[t.LOOSE] : re[t.FULL]) +delete process.env.OLDPWD; // initially, there's no previous directory - if (!m) { - throw new TypeError(`Invalid Version: ${version}`) - } +// Reliably test if something is any sort of javascript object +function isObject(a) { + return typeof a === 'object' && a !== null; +} +exports.isObject = isObject; - this.raw = version +function log() { + /* istanbul ignore next */ + if (!config.silent) { + console.error.apply(console, arguments); + } +} +exports.log = log; - // these are actually numbers - this.major = +m[1] - this.minor = +m[2] - this.patch = +m[3] +// Converts strings to be equivalent across all platforms. Primarily responsible +// for making sure we use '/' instead of '\' as path separators, but this may be +// expanded in the future if necessary +function convertErrorOutput(msg) { + if (typeof msg !== 'string') { + throw new TypeError('input must be a string'); + } + return msg.replace(/\\/g, '/'); +} +exports.convertErrorOutput = convertErrorOutput; - if (this.major > MAX_SAFE_INTEGER || this.major < 0) { - throw new TypeError('Invalid major version') - } +// An exception class to help propagate command errors (e.g., non-zero exit +// status) up to the top-level. {@param value} should be a ShellString. +class CommandError extends Error { + constructor(value) { + super(value.toString()); + this.returnValue = value; + } +} +exports.CommandError = CommandError; // visible for testing - if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) { - throw new TypeError('Invalid minor version') - } +// Shows error message. Throws if fatal is true (defaults to config.fatal, overridable with options.fatal) +function error(msg, _code, options) { + // Validate input + if (typeof msg !== 'string') throw new Error('msg must be a string'); - if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) { - throw new TypeError('Invalid patch version') - } + var DEFAULT_OPTIONS = { + continue: false, + code: 1, + prefix: state.currentCmd + ': ', + silent: false, + fatal: config.fatal, + }; - // numberify any prerelease numeric ids - if (!m[4]) { - this.prerelease = [] - } else { - this.prerelease = m[4].split('.').map((id) => { - if (/^[0-9]+$/.test(id)) { - const num = +id - if (num >= 0 && num < MAX_SAFE_INTEGER) { - return num - } - } - return id - }) - } + if (typeof _code === 'number' && isObject(options)) { + options.code = _code; + } else if (isObject(_code)) { // no 'code' + options = _code; + } else if (typeof _code === 'number') { // no 'options' + options = { code: _code }; + } else if (typeof _code !== 'number') { // only 'msg' + options = {}; + } + options = Object.assign({}, DEFAULT_OPTIONS, options); - this.build = m[5] ? m[5].split('.') : [] - this.format() + if (!state.errorCode) state.errorCode = options.code; + + var logEntry = convertErrorOutput(options.prefix + msg); + state.error = state.error ? state.error + '\n' : ''; + state.error += logEntry; + + // Throw an error, or log the entry + if (options.fatal) { + var err = new Error(logEntry); + err.code = options.code; + throw err; } + if (msg.length > 0 && !options.silent) log(logEntry); - format () { - this.version = `${this.major}.${this.minor}.${this.patch}` - if (this.prerelease.length) { - this.version += `-${this.prerelease.join('.')}` - } - return this.version + if (!options.continue) { + throw new CommandError(new ShellString('', state.error, state.errorCode)); } +} +exports.error = error; - toString () { - return this.version +//@ +//@ ### ShellString(str) +//@ +//@ Examples: +//@ +//@ ```javascript +//@ var foo = new ShellString('hello world'); +//@ ``` +//@ +//@ This is a dedicated type returned by most ShellJS methods, which wraps a +//@ string (or array) value. This has all the string (or array) methods, but +//@ also exposes extra methods: [`.to()`](#shellstringprototypetofile), +//@ [`.toEnd()`](#shellstringprototypetoendfile), and all the pipe-able methods +//@ (ex. `.cat()`, `.grep()`, etc.). This can be easily converted into a string +//@ by calling `.toString()`. +//@ +//@ This type also exposes the corresponding command's stdout, stderr, and +//@ return status code via the `.stdout` (string), `.stderr` (string), and +//@ `.code` (number) properties respectively. +function ShellString(stdout, stderr, code) { + var that; + if (stdout instanceof Array) { + that = stdout; + that.stdout = stdout.join('\n'); + if (stdout.length > 0) that.stdout += '\n'; + } else { + that = new String(stdout); + that.stdout = stdout; } + that.stderr = stderr; + that.code = code; + // A list of all commands that can appear on the right-hand side of a pipe + // (populated by calls to common.wrap()) + pipeMethods.forEach(function (cmd) { + that[cmd] = shellMethods[cmd].bind(that); + }); + return that; +} - compare (other) { - debug('SemVer.compare', this.version, this.options, other) - if (!(other instanceof SemVer)) { - if (typeof other === 'string' && other === this.version) { - return 0 - } - other = new SemVer(other, this.options) - } +exports.ShellString = ShellString; - if (other.version === this.version) { - return 0 - } +// Returns {'alice': true, 'bob': false} when passed a string and dictionary as follows: +// parseOptions('-a', {'a':'alice', 'b':'bob'}); +// Returns {'reference': 'string-value', 'bob': false} when passed two dictionaries of the form: +// parseOptions({'-r': 'string-value'}, {'r':'reference', 'b':'bob'}); +// Throws an error when passed a string that does not start with '-': +// parseOptions('a', {'a':'alice'}); // throws +function parseOptions(opt, map, errorOptions) { + errorOptions = errorOptions || {}; + // Validate input + if (typeof opt !== 'string' && !isObject(opt)) { + throw new TypeError('options must be strings or key-value pairs'); + } else if (!isObject(map)) { + throw new TypeError('parseOptions() internal error: map must be an object'); + } else if (!isObject(errorOptions)) { + throw new TypeError( + 'parseOptions() internal error: errorOptions must be object', + ); + } - return this.compareMain(other) || this.comparePre(other) + if (opt === '--') { + // This means there are no options. + return {}; } - compareMain (other) { - if (!(other instanceof SemVer)) { - other = new SemVer(other, this.options) + // All options are false by default + var options = {}; + Object.keys(map).forEach(function (letter) { + var optName = map[letter]; + if (optName[0] !== '!') { + options[optName] = false; } + }); - if (this.major < other.major) { - return -1 - } - if (this.major > other.major) { - return 1 - } - if (this.minor < other.minor) { - return -1 - } - if (this.minor > other.minor) { - return 1 - } - if (this.patch < other.patch) { - return -1 - } - if (this.patch > other.patch) { - return 1 - } - return 0 - } + if (opt === '') return options; // defaults - comparePre (other) { - if (!(other instanceof SemVer)) { - other = new SemVer(other, this.options) + if (typeof opt === 'string') { + if (opt[0] !== '-') { + throw new Error("Options string must start with a '-'"); } - // NOT having a prerelease is > having one - if (this.prerelease.length && !other.prerelease.length) { - return -1 - } else if (!this.prerelease.length && other.prerelease.length) { - return 1 - } else if (!this.prerelease.length && !other.prerelease.length) { - return 0 - } + // e.g. chars = ['R', 'f'] + var chars = opt.slice(1).split(''); - let i = 0 - do { - const a = this.prerelease[i] - const b = other.prerelease[i] - debug('prerelease compare', i, a, b) - if (a === undefined && b === undefined) { - return 0 - } else if (b === undefined) { - return 1 - } else if (a === undefined) { - return -1 - } else if (a === b) { - continue + chars.forEach(function (c) { + if (c in map) { + var optionName = map[c]; + if (optionName[0] === '!') { + options[optionName.slice(1)] = false; + } else { + options[optionName] = true; + } } else { - return compareIdentifiers(a, b) + error('option not recognized: ' + c, errorOptions); } - } while (++i) + }); + } else { // opt is an Object + Object.keys(opt).forEach(function (key) { + if (key[0] === '-') { + // key is a string of the form '-r', '-d', etc. + var c = key[1]; + if (c in map) { + var optionName = map[c]; + options[optionName] = opt[key]; // assign the given value + } else { + error('option not recognized: ' + c, errorOptions); + } + } else if (key in options) { + // key is a "long option", so it should be the same + options[key] = opt[key]; + } else { + error('option not recognized: {' + key + ':...}', errorOptions); + } + }); } + return options; +} +exports.parseOptions = parseOptions; - compareBuild (other) { - if (!(other instanceof SemVer)) { - other = new SemVer(other, this.options) +function globOptions() { + // These options are just to make fast-glob be compatible with POSIX (bash) + // wildcard behavior. + var defaultGlobOptions = { + onlyFiles: false, + followSymbolicLinks: false, + }; + + var newGlobOptions = Object.assign({}, config.globOptions); + var optionRenames = { + // node-glob's 'nodir' is not quote the same as fast-glob's 'onlyFiles'. + // Compatibility for this is implemented at the call site. + mark: 'markDirectories', + matchBase: 'baseNameMatch', + }; + Object.keys(optionRenames).forEach(function (oldKey) { + var newKey = optionRenames[oldKey]; + if (oldKey in config.globOptions) { + newGlobOptions[newKey] = config.globOptions[oldKey]; + } + }); + var invertedOptionRenames = { + nobrace: 'braceExpansion', + noglobstar: 'globstar', + noext: 'extglob', + nocase: 'caseSensitiveMatch', + }; + Object.keys(invertedOptionRenames).forEach(function (oldKey) { + var newKey = invertedOptionRenames[oldKey]; + if (oldKey in config.globOptions) { + newGlobOptions[newKey] = !config.globOptions[oldKey]; } + }); + return Object.assign({}, defaultGlobOptions, newGlobOptions); +} - let i = 0 - do { - const a = this.build[i] - const b = other.build[i] - debug('build compare', i, a, b) - if (a === undefined && b === undefined) { - return 0 - } else if (b === undefined) { - return 1 - } else if (a === undefined) { - return -1 - } else if (a === b) { - continue - } else { - return compareIdentifiers(a, b) - } - } while (++i) +// Expands wildcards with matching (ie. existing) file names. +// For example: +// expand(['file*.js']) = ['file1.js', 'file2.js', ...] +// (if the files 'file1.js', 'file2.js', etc, exist in the current dir) +function expand(list) { + if (!Array.isArray(list)) { + throw new TypeError('must be an array'); } - - // preminor will bump the version up to the next minor release, and immediately - // down to pre-release. premajor and prepatch work the same way. - inc (release, identifier, identifierBase) { - if (release.startsWith('pre')) { - if (!identifier && identifierBase === false) { - throw new Error('invalid increment argument: identifier is empty') + var expanded = []; + list.forEach(function (listEl) { + // Don't expand non-strings + if (typeof listEl !== 'string') { + expanded.push(listEl); + } else { + var ret; + var globOpts = globOptions(); + try { + ret = glob.sync(listEl, globOpts); + } catch (e) { + // if glob fails, interpret the string literally + ret = [listEl]; } - // Avoid an invalid semver results - if (identifier) { - const match = `-${identifier}`.match(this.options.loose ? re[t.PRERELEASELOOSE] : re[t.PRERELEASE]) - if (!match || match[1] !== identifier) { - throw new Error(`invalid identifier: ${identifier}`) - } + // if nothing matched, interpret the string literally + ret = ret.length > 0 ? ret.sort() : [listEl]; + if (globOpts.nodir) { + ret = ret.filter(function (file) { + return !statNoFollowLinks(file).isDirectory(); + }); } + expanded = expanded.concat(ret); } + }); + return expanded; +} +exports.expand = expand; - switch (release) { - case 'premajor': - this.prerelease.length = 0 - this.patch = 0 - this.minor = 0 - this.major++ - this.inc('pre', identifier, identifierBase) - break - case 'preminor': - this.prerelease.length = 0 - this.patch = 0 - this.minor++ - this.inc('pre', identifier, identifierBase) - break - case 'prepatch': - // If this is already a prerelease, it will bump to the next version - // drop any prereleases that might already exist, since they are not - // relevant at this point. - this.prerelease.length = 0 - this.inc('patch', identifier, identifierBase) - this.inc('pre', identifier, identifierBase) - break - // If the input is a non-prerelease version, this acts the same as - // prepatch. - case 'prerelease': - if (this.prerelease.length === 0) { - this.inc('patch', identifier, identifierBase) - } - this.inc('pre', identifier, identifierBase) - break - case 'release': - if (this.prerelease.length === 0) { - throw new Error(`version ${this.raw} is not a prerelease`) - } - this.prerelease.length = 0 - break - - case 'major': - // If this is a pre-major version, bump up to the same major version. - // Otherwise increment major. - // 1.0.0-5 bumps to 1.0.0 - // 1.1.0 bumps to 2.0.0 - if ( - this.minor !== 0 || - this.patch !== 0 || - this.prerelease.length === 0 - ) { - this.major++ - } - this.minor = 0 - this.patch = 0 - this.prerelease = [] - break - case 'minor': - // If this is a pre-minor version, bump up to the same minor version. - // Otherwise increment minor. - // 1.2.0-5 bumps to 1.2.0 - // 1.2.1 bumps to 1.3.0 - if (this.patch !== 0 || this.prerelease.length === 0) { - this.minor++ - } - this.patch = 0 - this.prerelease = [] - break - case 'patch': - // If this is not a pre-release version, it will increment the patch. - // If it is a pre-release it will bump up to the same patch version. - // 1.2.0-5 patches to 1.2.0 - // 1.2.0 patches to 1.2.1 - if (this.prerelease.length === 0) { - this.patch++ - } - this.prerelease = [] - break - // This probably shouldn't be used publicly. - // 1.0.0 'pre' would become 1.0.0-0 which is the wrong direction. - case 'pre': { - const base = Number(identifierBase) ? 1 : 0 +// Normalizes Buffer creation, using Buffer.alloc if possible. +// Also provides a good default buffer length for most use cases. +var buffer = typeof Buffer.alloc === 'function' ? + function (len) { + return Buffer.alloc(len || config.bufLength); + } : + function (len) { + return new Buffer(len || config.bufLength); + }; +exports.buffer = buffer; - if (this.prerelease.length === 0) { - this.prerelease = [base] - } else { - let i = this.prerelease.length - while (--i >= 0) { - if (typeof this.prerelease[i] === 'number') { - this.prerelease[i]++ - i = -2 - } - } - if (i === -1) { - // didn't increment anything - if (identifier === this.prerelease.join('.') && identifierBase === false) { - throw new Error('invalid increment argument: identifier already exists') - } - this.prerelease.push(base) - } - } - if (identifier) { - // 1.2.0-beta.1 bumps to 1.2.0-beta.2, - // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0 - let prerelease = [identifier, base] - if (identifierBase === false) { - prerelease = [identifier] - } - if (compareIdentifiers(this.prerelease[0], identifier) === 0) { - if (isNaN(this.prerelease[1])) { - this.prerelease = prerelease - } - } else { - this.prerelease = prerelease - } - } - break - } - default: - throw new Error(`invalid increment argument: ${release}`) - } - this.raw = this.format() - if (this.build.length) { - this.raw += `+${this.build.join('.')}` +// Normalizes _unlinkSync() across platforms to match Unix behavior, i.e. +// file can be unlinked even if it's read-only, see https://github.com/joyent/node/issues/3006 +function unlinkSync(file) { + try { + fs.unlinkSync(file); + } catch (e) { + // Try to override file permission + /* istanbul ignore next */ + if (e.code === 'EPERM') { + fs.chmodSync(file, '0666'); + fs.unlinkSync(file); + } else { + throw e; } - return this } } +exports.unlinkSync = unlinkSync; -module.exports = SemVer - - -/***/ }), - -/***/ 6152: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -"use strict"; - - -const parse = __nccwpck_require__(162) -const clean = (version, options) => { - const s = parse(version.trim().replace(/^[=v]+/, ''), options) - return s ? s.version : null +// wrappers around common.statFollowLinks and common.statNoFollowLinks that clarify intent +// and improve readability +function statFollowLinks() { + return fs.statSync.apply(fs, arguments); } -module.exports = clean +exports.statFollowLinks = statFollowLinks; +function statNoFollowLinks() { + return fs.lstatSync.apply(fs, arguments); +} +exports.statNoFollowLinks = statNoFollowLinks; -/***/ }), +// e.g. 'shelljs_a5f185d0443ca...' +function randomFileName() { + function randomHash(count) { + if (count === 1) { + return parseInt(16 * Math.random(), 10).toString(16); + } + var hash = ''; + for (var i = 0; i < count; i++) { + hash += randomHash(1); + } + return hash; + } -/***/ 1941: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + return 'shelljs_' + randomHash(20); +} +exports.randomFileName = randomFileName; -"use strict"; +// Common wrapper for all Unix-like commands that performs glob expansion, +// command-logging, and other nice things +function wrap(cmd, fn, options) { + options = options || {}; + return function () { + var retValue = null; + state.currentCmd = cmd; + state.error = null; + state.errorCode = 0; -const eq = __nccwpck_require__(4255) -const neq = __nccwpck_require__(9469) -const gt = __nccwpck_require__(9158) -const gte = __nccwpck_require__(9727) -const lt = __nccwpck_require__(4009) -const lte = __nccwpck_require__(4394) + try { + var args = [].slice.call(arguments, 0); -const cmp = (a, op, b, loose) => { - switch (op) { - case '===': - if (typeof a === 'object') { - a = a.version - } - if (typeof b === 'object') { - b = b.version + // Log the command to stderr, if appropriate + if (config.verbose) { + console.error.apply(console, [cmd].concat(args)); } - return a === b - case '!==': - if (typeof a === 'object') { - a = a.version - } - if (typeof b === 'object') { - b = b.version - } - return a !== b + // If this is coming from a pipe, let's set the pipedValue (otherwise, set + // it to the empty string) + state.pipedValue = (this && typeof this.stdout === 'string') ? this.stdout : ''; - case '': - case '=': - case '==': - return eq(a, b, loose) + if (options.unix === false) { // this branch is for exec() + retValue = fn.apply(this, args); + } else { // and this branch is for everything else + if (isObject(args[0]) && args[0].constructor.name === 'Object') { + // a no-op, allowing the syntax `touch({'-r': file}, ...)` + } else if (args.length === 0 || typeof args[0] !== 'string' || args[0].length <= 1 || args[0][0] !== '-') { + args.unshift(''); // only add dummy option if '-option' not already present + } - case '!=': - return neq(a, b, loose) + // flatten out arrays that are arguments, to make the syntax: + // `cp([file1, file2, file3], dest);` + // equivalent to: + // `cp(file1, file2, file3, dest);` + args = args.reduce(function (accum, cur) { + if (Array.isArray(cur)) { + return accum.concat(cur); + } + accum.push(cur); + return accum; + }, []); - case '>': - return gt(a, b, loose) + // Convert ShellStrings (basically just String objects) to regular strings + args = args.map(function (arg) { + if (isObject(arg) && arg.constructor.name === 'String') { + return arg.toString(); + } + return arg; + }); - case '>=': - return gte(a, b, loose) + // Expand the '~' if appropriate + var homeDir = os.homedir(); + args = args.map(function (arg) { + if (typeof arg === 'string' && arg.slice(0, 2) === '~/' || arg === '~') { + return arg.replace(/^~/, homeDir); + } + return arg; + }); - case '<': - return lt(a, b, loose) + // Perform glob-expansion on all arguments after globStart, but preserve + // the arguments before it (like regexes for sed and grep) + if (!config.noglob && options.allowGlobbing === true) { + args = args.slice(0, options.globStart).concat(expand(args.slice(options.globStart))); + } - case '<=': - return lte(a, b, loose) + try { + // parse options if options are provided + if (isObject(options.cmdOptions)) { + args[0] = parseOptions(args[0], options.cmdOptions); + } - default: - throw new TypeError(`Invalid operator: ${op}`) - } -} -module.exports = cmp + retValue = fn.apply(this, args); + } catch (e) { + /* istanbul ignore else */ + if (e instanceof CommandError) { + retValue = e.returnValue; + } else { + throw e; // this is probably a bug that should be thrown up the call stack + } + } + } + } catch (e) { + /* istanbul ignore next */ + if (!state.error) { + // If state.error hasn't been set it's an error thrown by Node, not us - probably a bug... + e.name = 'ShellJSInternalError'; + throw e; + } + if (config.fatal || options.handlesFatalDynamically) throw e; + } + if (options.wrapOutput && + (typeof retValue === 'string' || Array.isArray(retValue))) { + retValue = new ShellString(retValue, state.error, state.errorCode); + } -/***/ }), + state.currentCmd = 'shell.js'; + return retValue; + }; +} // wrap +exports.wrap = wrap; -/***/ 6536: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +// This returns all the input that is piped into the current command (or the +// empty string, if this isn't on the right-hand side of a pipe +function _readFromPipe() { + return state.pipedValue; +} +exports.readFromPipe = _readFromPipe; -"use strict"; +var DEFAULT_WRAP_OPTIONS = { + allowGlobbing: true, + canReceivePipe: false, + cmdOptions: null, + globStart: 1, + handlesFatalDynamically: false, + pipeOnly: false, + wrapOutput: true, + unix: true, +}; +// This is populated during plugin registration +var pipeMethods = []; -const SemVer = __nccwpck_require__(2478) -const parse = __nccwpck_require__(162) -const { safeRe: re, t } = __nccwpck_require__(3032) +// Register a new ShellJS command +function _register(name, implementation, wrapOptions) { + wrapOptions = wrapOptions || {}; -const coerce = (version, options) => { - if (version instanceof SemVer) { - return version - } + // Validate options + Object.keys(wrapOptions).forEach(function (option) { + if (!DEFAULT_WRAP_OPTIONS.hasOwnProperty(option)) { + throw new Error("Unknown option '" + option + "'"); + } + if (typeof wrapOptions[option] !== typeof DEFAULT_WRAP_OPTIONS[option]) { + throw new TypeError("Unsupported type '" + typeof wrapOptions[option] + + "' for option '" + option + "'"); + } + }); - if (typeof version === 'number') { - version = String(version) - } + // If an option isn't specified, use the default + wrapOptions = Object.assign({}, DEFAULT_WRAP_OPTIONS, wrapOptions); - if (typeof version !== 'string') { - return null + if (shell.hasOwnProperty(name)) { + throw new Error('Command `' + name + '` already exists'); } - options = options || {} - - let match = null - if (!options.rtl) { - match = version.match(options.includePrerelease ? re[t.COERCEFULL] : re[t.COERCE]) + if (wrapOptions.pipeOnly) { + wrapOptions.canReceivePipe = true; + shellMethods[name] = wrap(name, implementation, wrapOptions); } else { - // Find the right-most coercible string that does not share - // a terminus with a more left-ward coercible string. - // Eg, '1.2.3.4' wants to coerce '2.3.4', not '3.4' or '4' - // With includePrerelease option set, '1.2.3.4-rc' wants to coerce '2.3.4-rc', not '2.3.4' - // - // Walk through the string checking with a /g regexp - // Manually set the index so as to pick up overlapping matches. - // Stop when we get a match that ends at the string end, since no - // coercible string can be more right-ward without the same terminus. - const coerceRtlRegex = options.includePrerelease ? re[t.COERCERTLFULL] : re[t.COERCERTL] - let next - while ((next = coerceRtlRegex.exec(version)) && - (!match || match.index + match[0].length !== version.length) - ) { - if (!match || - next.index + next[0].length !== match.index + match[0].length) { - match = next - } - coerceRtlRegex.lastIndex = next.index + next[1].length + next[2].length - } - // leave it in a clean state - coerceRtlRegex.lastIndex = -1 + shell[name] = wrap(name, implementation, wrapOptions); } - if (match === null) { - return null + if (wrapOptions.canReceivePipe) { + pipeMethods.push(name); } - - const major = match[2] - const minor = match[3] || '0' - const patch = match[4] || '0' - const prerelease = options.includePrerelease && match[5] ? `-${match[5]}` : '' - const build = options.includePrerelease && match[6] ? `+${match[6]}` : '' - - return parse(`${major}.${minor}.${patch}${prerelease}${build}`, options) } -module.exports = coerce +exports.register = _register; /***/ }), -/***/ 175: +/***/ 1642: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; +var fs = __nccwpck_require__(9896); +var path = __nccwpck_require__(6928); +var common = __nccwpck_require__(8400); +common.register('cp', _cp, { + cmdOptions: { + 'f': '!no_force', + 'n': 'no_force', + 'u': 'update', + 'R': 'recursive', + 'r': 'recursive', + 'L': 'followsymlink', + 'P': 'noFollowsymlink', + 'p': 'preserve', + }, + wrapOutput: false, +}); -const SemVer = __nccwpck_require__(2478) -const compareBuild = (a, b, loose) => { - const versionA = new SemVer(a, loose) - const versionB = new SemVer(b, loose) - return versionA.compare(versionB) || versionA.compareBuild(versionB) -} -module.exports = compareBuild - - -/***/ }), - -/***/ 9621: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -"use strict"; - - -const compare = __nccwpck_require__(126) -const compareLoose = (a, b) => compare(a, b, true) -module.exports = compareLoose - - -/***/ }), +// Buffered file copy, synchronous +// (Using readFileSync() + writeFileSync() could easily cause a memory overflow +// with large files) +function copyFileSync(srcFile, destFile, options) { + if (!fs.existsSync(srcFile)) { + common.error('copyFileSync: no such file or directory: ' + srcFile); + } -/***/ 126: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + var isWindows = process.platform === 'win32'; -"use strict"; + // Check the mtimes of the files if the '-u' flag is provided + try { + if (options.update && common.statFollowLinks(srcFile).mtime < fs.statSync(destFile).mtime) { + return; + } + } catch (e) { + // If we're here, destFile probably doesn't exist, so just do a normal copy + } + if (common.statNoFollowLinks(srcFile).isSymbolicLink() && !options.followsymlink) { + try { + common.statNoFollowLinks(destFile); + common.unlinkSync(destFile); // re-link it + } catch (e) { + // it doesn't exist, so no work needs to be done + } -const SemVer = __nccwpck_require__(2478) -const compare = (a, b, loose) => - new SemVer(a, loose).compare(new SemVer(b, loose)) + var symlinkFull = fs.readlinkSync(srcFile); + fs.symlinkSync(symlinkFull, destFile, isWindows ? 'junction' : null); + } else { + var buf = common.buffer(); + var bufLength = buf.length; + var bytesRead = bufLength; + var pos = 0; + var fdr = null; + var fdw = null; + var srcStat = common.statFollowLinks(srcFile); -module.exports = compare + try { + fdr = fs.openSync(srcFile, 'r'); + } catch (e) { + /* istanbul ignore next */ + common.error('copyFileSync: could not read src file (' + srcFile + ')'); + } + try { + fdw = fs.openSync(destFile, 'w', srcStat.mode); + } catch (e) { + /* istanbul ignore next */ + common.error('copyFileSync: could not write to dest file (code=' + e.code + '):' + destFile); + } -/***/ }), + while (bytesRead === bufLength) { + bytesRead = fs.readSync(fdr, buf, 0, bufLength, pos); + fs.writeSync(fdw, buf, 0, bytesRead); + pos += bytesRead; + } -/***/ 3854: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + if (options.preserve) { + fs.fchownSync(fdw, srcStat.uid, srcStat.gid); + // Note: utimesSync does not work (rounds to seconds), but futimesSync has + // millisecond precision. + fs.futimesSync(fdw, srcStat.atime, srcStat.mtime); + } -"use strict"; + fs.closeSync(fdr); + fs.closeSync(fdw); + } +} +// Recursively copies 'sourceDir' into 'destDir' +// Adapted from https://github.com/ryanmcgrath/wrench-js +// +// Copyright (c) 2010 Ryan McGrath +// Copyright (c) 2012 Artur Adib +// +// Licensed under the MIT License +// http://www.opensource.org/licenses/mit-license.php +function cpdirSyncRecursive(sourceDir, destDir, currentDepth, opts) { + if (!opts) opts = {}; -const parse = __nccwpck_require__(162) + // Ensure there is not a run away recursive copy + if (currentDepth >= common.config.maxdepth) return; + currentDepth++; -const diff = (version1, version2) => { - const v1 = parse(version1, null, true) - const v2 = parse(version2, null, true) - const comparison = v1.compare(v2) + var isWindows = process.platform === 'win32'; - if (comparison === 0) { - return null + // Create the directory where all our junk is moving to; read the mode/etc. of + // the source directory (we'll set this on the destDir at the end). + var checkDir = common.statFollowLinks(sourceDir); + try { + fs.mkdirSync(destDir); + } catch (e) { + // if the directory already exists, that's okay + if (e.code !== 'EEXIST') throw e; } - const v1Higher = comparison > 0 - const highVersion = v1Higher ? v1 : v2 - const lowVersion = v1Higher ? v2 : v1 - const highHasPre = !!highVersion.prerelease.length - const lowHasPre = !!lowVersion.prerelease.length + var files = fs.readdirSync(sourceDir); - if (lowHasPre && !highHasPre) { - // Going from prerelease -> no prerelease requires some special casing + for (var i = 0; i < files.length; i++) { + var srcFile = sourceDir + '/' + files[i]; + var destFile = destDir + '/' + files[i]; + var srcFileStat = common.statNoFollowLinks(srcFile); - // If the low version has only a major, then it will always be a major - // Some examples: - // 1.0.0-1 -> 1.0.0 - // 1.0.0-1 -> 1.1.1 - // 1.0.0-1 -> 2.0.0 - if (!lowVersion.patch && !lowVersion.minor) { - return 'major' + var symlinkFull; + if (opts.followsymlink) { + if (cpcheckcycle(sourceDir, srcFile)) { + // Cycle link found. + console.error('Cycle link found.'); + symlinkFull = fs.readlinkSync(srcFile); + fs.symlinkSync(symlinkFull, destFile, isWindows ? 'junction' : null); + continue; + } } - - // If the main part has no difference - if (lowVersion.compareMain(highVersion) === 0) { - if (lowVersion.minor && !lowVersion.patch) { - return 'minor' + if (srcFileStat.isDirectory()) { + /* recursion this thing right on back. */ + cpdirSyncRecursive(srcFile, destFile, currentDepth, opts); + } else if (srcFileStat.isSymbolicLink() && !opts.followsymlink) { + symlinkFull = fs.readlinkSync(srcFile); + try { + common.statNoFollowLinks(destFile); + common.unlinkSync(destFile); // re-link it + } catch (e) { + // it doesn't exist, so no work needs to be done } - return 'patch' + fs.symlinkSync(symlinkFull, destFile, isWindows ? 'junction' : null); + } else if (srcFileStat.isSymbolicLink() && opts.followsymlink) { + srcFileStat = common.statFollowLinks(srcFile); + if (srcFileStat.isDirectory()) { + cpdirSyncRecursive(srcFile, destFile, currentDepth, opts); + } else { + copyFileSync(srcFile, destFile, opts); + } + } else if (fs.existsSync(destFile) && opts.no_force) { + common.log('skipping existing file: ' + files[i]); + } else { + copyFileSync(srcFile, destFile, opts); } - } - - // add the `pre` prefix if we are going to a prerelease version - const prefix = highHasPre ? 'pre' : '' + } // for files - if (v1.major !== v2.major) { - return prefix + 'major' + // finally change the mode for the newly created directory (otherwise, we + // couldn't add files to a read-only directory). + // var checkDir = common.statFollowLinks(sourceDir); + if (opts.preserve) { + fs.utimesSync(destDir, checkDir.atime, checkDir.mtime); } + fs.chmodSync(destDir, checkDir.mode); +} // cpdirSyncRecursive - if (v1.minor !== v2.minor) { - return prefix + 'minor' - } +// Checks if cureent file was created recently +function checkRecentCreated(sources, index) { + var lookedSource = sources[index]; + return sources.slice(0, index).some(function (src) { + return path.basename(src) === path.basename(lookedSource); + }); +} - if (v1.patch !== v2.patch) { - return prefix + 'patch' +function cpcheckcycle(sourceDir, srcFile) { + var srcFileStat = common.statNoFollowLinks(srcFile); + if (srcFileStat.isSymbolicLink()) { + // Do cycle check. For example: + // $ mkdir -p 1/2/3/4 + // $ cd 1/2/3/4 + // $ ln -s ../../3 link + // $ cd ../../../.. + // $ cp -RL 1 copy + var cyclecheck = common.statFollowLinks(srcFile); + if (cyclecheck.isDirectory()) { + var sourcerealpath = fs.realpathSync(sourceDir); + var symlinkrealpath = fs.realpathSync(srcFile); + var re = new RegExp(symlinkrealpath); + if (re.test(sourcerealpath)) { + return true; + } + } } - - // high and low are preleases - return 'prerelease' + return false; } -module.exports = diff +//@ +//@ ### cp([options,] source [, source ...], dest) +//@ ### cp([options,] source_array, dest) +//@ +//@ Available options: +//@ +//@ + `-f`: force (default behavior) +//@ + `-n`: no-clobber +//@ + `-u`: only copy if `source` is newer than `dest` +//@ + `-r`, `-R`: recursive +//@ + `-L`: follow symlinks +//@ + `-P`: don't follow symlinks +//@ + `-p`: preserve file mode, ownership, and timestamps +//@ +//@ Examples: +//@ +//@ ```javascript +//@ cp('file1', 'dir1'); +//@ cp('-R', 'path/to/dir/', '~/newCopy/'); +//@ cp('-Rf', '/tmp/*', '/usr/local/*', '/home/tmp'); +//@ cp('-Rf', ['/tmp/*', '/usr/local/*'], '/home/tmp'); // same as above +//@ ``` +//@ +//@ Copies files. Returns a [ShellString](#shellstringstr) indicating success +//@ or failure. +function _cp(options, sources, dest) { + // If we're missing -R, it actually implies -L (unless -P is explicit) + if (options.followsymlink) { + options.noFollowsymlink = false; + } + if (!options.recursive && !options.noFollowsymlink) { + options.followsymlink = true; + } + // Get sources, dest + if (arguments.length < 3) { + common.error('missing and/or '); + } else { + sources = [].slice.call(arguments, 1, arguments.length - 1); + dest = arguments[arguments.length - 1]; + } -/***/ }), + var destExists = fs.existsSync(dest); + var destStat = destExists && common.statFollowLinks(dest); -/***/ 4255: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // Dest is not existing dir, but multiple sources given + if ((!destExists || !destStat.isDirectory()) && sources.length > 1) { + common.error('dest is not a directory (too many sources)'); + } -"use strict"; + // Dest is an existing file, but -n is given + if (destExists && destStat.isFile() && options.no_force) { + return new common.ShellString('', '', 0); + } + sources.forEach(function (src, srcIndex) { + if (!fs.existsSync(src)) { + if (src === '') src = "''"; // if src was empty string, display empty string + common.error('no such file or directory: ' + src, { continue: true }); + return; // skip file + } + var srcStat = common.statFollowLinks(src); + if (!options.noFollowsymlink && srcStat.isDirectory()) { + if (!options.recursive) { + // Non-Recursive + common.error("omitting directory '" + src + "'", { continue: true }); + } else { + // Recursive + // 'cp /a/source dest' should create 'source' in 'dest' + var newDest = (destStat && destStat.isDirectory()) ? + path.join(dest, path.basename(src)) : + dest; -const compare = __nccwpck_require__(126) -const eq = (a, b, loose) => compare(a, b, loose) === 0 -module.exports = eq + try { + common.statFollowLinks(path.dirname(dest)); + cpdirSyncRecursive(src, newDest, 0, options); + } catch (e) { + /* istanbul ignore next */ + common.error("cannot create directory '" + dest + "': No such file or directory"); + } + } + } else { + // If here, src is a file + // When copying to '/path/dir': + // thisDest = '/path/dir/file1' + var thisDest = dest; + if (destStat && destStat.isDirectory()) { + thisDest = path.normalize(dest + '/' + path.basename(src)); + } -/***/ }), + var thisDestExists = fs.existsSync(thisDest); + if (thisDestExists && checkRecentCreated(sources, srcIndex)) { + // cannot overwrite file created recently in current execution, but we want to continue copying other files + if (!options.no_force) { + common.error("will not overwrite just-created '" + thisDest + "' with '" + src + "'", { continue: true }); + } + return; + } -/***/ 9158: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + if (thisDestExists && options.no_force) { + return; // skip file + } -"use strict"; + if (path.relative(src, thisDest) === '') { + // a file cannot be copied to itself, but we want to continue copying other files + common.error("'" + thisDest + "' and '" + src + "' are the same file", { continue: true }); + return; + } + copyFileSync(src, thisDest, options); + } + }); // forEach(src) -const compare = __nccwpck_require__(126) -const gt = (a, b, loose) => compare(a, b, loose) > 0 -module.exports = gt + return new common.ShellString('', common.state.error, common.state.errorCode); +} +module.exports = _cp; /***/ }), -/***/ 9727: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +/***/ 473: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { -"use strict"; +var path = __nccwpck_require__(6928); +var common = __nccwpck_require__(8400); +var _cd = __nccwpck_require__(3046); +common.register('dirs', _dirs, { + wrapOutput: false, +}); +common.register('pushd', _pushd, { + wrapOutput: false, +}); +common.register('popd', _popd, { + wrapOutput: false, +}); -const compare = __nccwpck_require__(126) -const gte = (a, b, loose) => compare(a, b, loose) >= 0 -module.exports = gte +// Pushd/popd/dirs internals +var _dirStack = []; +function _isStackIndex(index) { + return (/^[-+]\d+$/).test(index); +} -/***/ }), +function _parseStackIndex(index) { + if (_isStackIndex(index)) { + if (Math.abs(index) < _dirStack.length + 1) { // +1 for pwd + return (/^-/).test(index) ? Number(index) - 1 : Number(index); + } + common.error(index + ': directory stack index out of range'); + } else { + common.error(index + ': invalid number'); + } +} -/***/ 6473: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +function _actualDirStack() { + return [process.cwd()].concat(_dirStack); +} -"use strict"; +//@ +//@ ### pushd([options,] [dir | '-N' | '+N']) +//@ +//@ Available options: +//@ +//@ + `-n`: Suppresses the normal change of directory when adding directories to the stack, so that only the stack is manipulated. +//@ + `-q`: Suppresses output to the console. +//@ +//@ Arguments: +//@ +//@ + `dir`: Sets the current working directory to the top of the stack, then executes the equivalent of `cd dir`. +//@ + `+N`: Brings the Nth directory (counting from the left of the list printed by dirs, starting with zero) to the top of the list by rotating the stack. +//@ + `-N`: Brings the Nth directory (counting from the right of the list printed by dirs, starting with zero) to the top of the list by rotating the stack. +//@ +//@ Examples: +//@ +//@ ```javascript +//@ // process.cwd() === '/usr' +//@ pushd('/etc'); // Returns /etc /usr +//@ pushd('+1'); // Returns /usr /etc +//@ ``` +//@ +//@ Save the current directory on the top of the directory stack and then `cd` to `dir`. With no arguments, `pushd` exchanges the top two directories. Returns an array of paths in the stack. +function _pushd(options, dir) { + if (_isStackIndex(options)) { + dir = options; + options = ''; + } + options = common.parseOptions(options, { + 'n': 'no-cd', + 'q': 'quiet', + }); -const SemVer = __nccwpck_require__(2478) + var dirs = _actualDirStack(); -const inc = (version, release, options, identifier, identifierBase) => { - if (typeof (options) === 'string') { - identifierBase = identifier - identifier = options - options = undefined + if (dir === '+0') { + return dirs; // +0 is a noop + } else if (!dir) { + if (dirs.length > 1) { + dirs = dirs.splice(1, 1).concat(dirs); + } else { + return common.error('no other directory'); + } + } else if (_isStackIndex(dir)) { + var n = _parseStackIndex(dir); + dirs = dirs.slice(n).concat(dirs.slice(0, n)); + } else if (options['no-cd']) { + dirs.splice(1, 0, dir); + } else { + dirs.unshift(dir); } - try { - return new SemVer( - version instanceof SemVer ? version.version : version, - options - ).inc(release, identifier, identifierBase).version - } catch (er) { - return null + if (options['no-cd']) { + dirs = dirs.slice(1); + } else { + dir = path.resolve(dirs.shift()); + _cd('', dir); } + + _dirStack = dirs; + return _dirs(options.quiet ? '-q' : ''); } -module.exports = inc +exports.pushd = _pushd; +//@ +//@ +//@ ### popd([options,] ['-N' | '+N']) +//@ +//@ Available options: +//@ +//@ + `-n`: Suppress the normal directory change when removing directories from the stack, so that only the stack is manipulated. +//@ + `-q`: Suppresses output to the console. +//@ +//@ Arguments: +//@ +//@ + `+N`: Removes the Nth directory (counting from the left of the list printed by dirs), starting with zero. +//@ + `-N`: Removes the Nth directory (counting from the right of the list printed by dirs), starting with zero. +//@ +//@ Examples: +//@ +//@ ```javascript +//@ echo(process.cwd()); // '/usr' +//@ pushd('/etc'); // '/etc /usr' +//@ echo(process.cwd()); // '/etc' +//@ popd(); // '/usr' +//@ echo(process.cwd()); // '/usr' +//@ ``` +//@ +//@ When no arguments are given, `popd` removes the top directory from the stack and performs a `cd` to the new top directory. The elements are numbered from 0, starting at the first directory listed with dirs (i.e., `popd` is equivalent to `popd +0`). Returns an array of paths in the stack. +function _popd(options, index) { + if (_isStackIndex(options)) { + index = options; + options = ''; + } -/***/ }), + options = common.parseOptions(options, { + 'n': 'no-cd', + 'q': 'quiet', + }); -/***/ 4009: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + if (!_dirStack.length) { + return common.error('directory stack empty'); + } -"use strict"; + index = _parseStackIndex(index || '+0'); + if (options['no-cd'] || index > 0 || _dirStack.length + index === 0) { + index = index > 0 ? index - 1 : index; + _dirStack.splice(index, 1); + } else { + var dir = path.resolve(_dirStack.shift()); + _cd('', dir); + } -const compare = __nccwpck_require__(126) -const lt = (a, b, loose) => compare(a, b, loose) < 0 -module.exports = lt + return _dirs(options.quiet ? '-q' : ''); +} +exports.popd = _popd; +//@ +//@ +//@ ### dirs([options | '+N' | '-N']) +//@ +//@ Available options: +//@ +//@ + `-c`: Clears the directory stack by deleting all of the elements. +//@ + `-q`: Suppresses output to the console. +//@ +//@ Arguments: +//@ +//@ + `+N`: Displays the Nth directory (counting from the left of the list printed by dirs when invoked without options), starting with zero. +//@ + `-N`: Displays the Nth directory (counting from the right of the list printed by dirs when invoked without options), starting with zero. +//@ +//@ Display the list of currently remembered directories. Returns an array of paths in the stack, or a single path if `+N` or `-N` was specified. +//@ +//@ See also: `pushd`, `popd` +function _dirs(options, index) { + if (_isStackIndex(options)) { + index = options; + options = ''; + } -/***/ }), + options = common.parseOptions(options, { + 'c': 'clear', + 'q': 'quiet', + }); -/***/ 4394: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + if (options.clear) { + _dirStack = []; + return _dirStack; + } + + var stack = _actualDirStack(); -"use strict"; + if (index) { + index = _parseStackIndex(index); + if (index < 0) { + index = stack.length + index; + } -const compare = __nccwpck_require__(126) -const lte = (a, b, loose) => compare(a, b, loose) <= 0 -module.exports = lte + if (!options.quiet) { + common.log(stack[index]); + } + return stack[index]; + } + + if (!options.quiet) { + common.log(stack.join(' ')); + } + + return stack; +} +exports.dirs = _dirs; /***/ }), -/***/ 1536: +/***/ 2016: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; +var format = (__nccwpck_require__(9023).format); +var common = __nccwpck_require__(8400); -const SemVer = __nccwpck_require__(2478) -const major = (a, loose) => new SemVer(a, loose).major -module.exports = major +common.register('echo', _echo, { + allowGlobbing: false, +}); +//@ +//@ ### echo([options,] string [, string ...]) +//@ +//@ Available options: +//@ +//@ + `-e`: interpret backslash escapes (default) +//@ + `-n`: remove trailing newline from output +//@ +//@ Examples: +//@ +//@ ```javascript +//@ echo('hello world'); +//@ var str = echo('hello world'); +//@ echo('-n', 'no newline at end'); +//@ ``` +//@ +//@ Prints `string` to stdout, and returns a [ShellString](#shellstringstr). +function _echo(opts) { + // allow strings starting with '-', see issue #20 + var messages = [].slice.call(arguments, opts ? 0 : 1); + var options = {}; -/***/ }), + // If the first argument starts with '-', parse it as options string. + // If parseOptions throws, it wasn't an options string. + try { + options = common.parseOptions(messages[0], { + 'e': 'escapes', + 'n': 'no_newline', + }, { + silent: true, + }); -/***/ 3900: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // Allow null to be echoed + if (messages[0]) { + messages.shift(); + } + } catch (_) { + // Clear out error if an error occurred + common.state.error = null; + } -"use strict"; + var output = format.apply(null, messages); + // Add newline if -n is not passed. + if (!options.no_newline) { + output += '\n'; + } -const SemVer = __nccwpck_require__(2478) -const minor = (a, loose) => new SemVer(a, loose).minor -module.exports = minor + process.stdout.write(output); + + return output; +} + +module.exports = _echo; /***/ }), -/***/ 9469: +/***/ 123: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; +var common = __nccwpck_require__(8400); - -const compare = __nccwpck_require__(126) -const neq = (a, b, loose) => compare(a, b, loose) !== 0 -module.exports = neq +//@ +//@ ### error() +//@ +//@ Tests if error occurred in the last command. Returns a truthy value if an +//@ error returned, or a falsy value otherwise. +//@ +//@ **Note**: do not rely on the +//@ return value to be an error message. If you need the last error message, use +//@ the `.stderr` attribute from the last command's return value instead. +function error() { + return common.state.error; +} +module.exports = error; /***/ }), -/***/ 162: +/***/ 9650: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; +var common = __nccwpck_require__(8400); +//@ +//@ ### errorCode() +//@ +//@ Returns the error code from the last command. +function errorCode() { + return common.state.errorCode; +} +module.exports = errorCode; -const SemVer = __nccwpck_require__(2478) -const parse = (version, options, throwErrors = false) => { - if (version instanceof SemVer) { - return version + +/***/ }), + +/***/ 2107: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __nccwpck_require__) => { + +var childProcess = __nccwpck_require__(5317); +var fs = __nccwpck_require__(9896); + +function main() { + var paramFilePath = process.argv[2]; + + var serializedParams = fs.readFileSync(paramFilePath, 'utf8'); + var params = JSON.parse(serializedParams); + + var cmd = params.command; + var execOptions = params.execOptions; + var pipe = params.pipe; + var stdoutFile = params.stdoutFile; + var stderrFile = params.stderrFile; + + function isMaxBufferError(err) { + var maxBufferErrorPattern = /^.*\bmaxBuffer\b.*exceeded.*$/; + if (err instanceof Error && err.message && + err.message.match(maxBufferErrorPattern)) { + // < v10 + // Error: stdout maxBuffer exceeded + return true; + } else if (err instanceof RangeError && err.message && + err.message.match(maxBufferErrorPattern)) { + // >= v10 + // RangeError [ERR_CHILD_PROCESS_STDIO_MAXBUFFER]: stdout maxBuffer length + // exceeded + return true; + } + return false; } - try { - return new SemVer(version, options) - } catch (er) { - if (!throwErrors) { - return null + + var stdoutStream = fs.createWriteStream(stdoutFile); + var stderrStream = fs.createWriteStream(stderrFile); + + function appendError(message, code) { + stderrStream.write(message); + process.exitCode = code; + } + + var c = childProcess.exec(cmd, execOptions, function (err) { + if (!err) { + process.exitCode = 0; + } else if (isMaxBufferError(err)) { + appendError('maxBuffer exceeded', 1); + } else if (err.code === undefined && err.message) { + /* istanbul ignore next */ + appendError(err.message, 1); + } else if (err.code === undefined) { + /* istanbul ignore next */ + appendError('Unknown issue', 1); + } else { + process.exitCode = err.code; } - throw er + }); + + c.stdout.pipe(stdoutStream); + c.stderr.pipe(stderrStream); + c.stdout.pipe(process.stdout); + c.stderr.pipe(process.stderr); + + if (pipe) { + c.stdin.end(pipe); } } -module.exports = parse +// This file should only be executed. This module does not export anything. +/* istanbul ignore else */ +if (false) {} /***/ }), -/***/ 9443: +/***/ 1927: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; +var path = __nccwpck_require__(6928); +var fs = __nccwpck_require__(9896); +var child = __nccwpck_require__(5317); +var common = __nccwpck_require__(8400); +var _tempDir = (__nccwpck_require__(1356).tempDir); +var _pwd = __nccwpck_require__(566); +var DEFAULT_MAXBUFFER_SIZE = 20 * 1024 * 1024; +var DEFAULT_ERROR_CODE = 1; -const SemVer = __nccwpck_require__(2478) -const patch = (a, loose) => new SemVer(a, loose).patch -module.exports = patch +common.register('exec', _exec, { + unix: false, + canReceivePipe: true, + wrapOutput: false, + handlesFatalDynamically: true, +}); +// We use this function to run `exec` synchronously while also providing realtime +// output. +function execSync(cmd, opts, pipe) { + if (!common.config.execPath) { + try { + common.error('Unable to find a path to the node binary. Please manually set config.execPath'); + } catch (e) { + if (opts.fatal) { + throw e; + } -/***/ }), + return; + } + } -/***/ 1779: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + var tempDir = _tempDir(); + var paramsFile = path.join(tempDir, common.randomFileName()); + var stderrFile = path.join(tempDir, common.randomFileName()); + var stdoutFile = path.join(tempDir, common.randomFileName()); -"use strict"; + opts = common.extend({ + silent: common.config.silent, + fatal: common.config.fatal, // TODO(nfischer): this and the line above are probably unnecessary + cwd: _pwd().toString(), + env: process.env, + maxBuffer: DEFAULT_MAXBUFFER_SIZE, + encoding: 'utf8', + }, opts); + if (fs.existsSync(paramsFile)) common.unlinkSync(paramsFile); + if (fs.existsSync(stderrFile)) common.unlinkSync(stderrFile); + if (fs.existsSync(stdoutFile)) common.unlinkSync(stdoutFile); -const parse = __nccwpck_require__(162) -const prerelease = (version, options) => { - const parsed = parse(version, options) - return (parsed && parsed.prerelease.length) ? parsed.prerelease : null -} -module.exports = prerelease + opts.cwd = path.resolve(opts.cwd); + var paramsToSerialize = { + command: cmd, + execOptions: opts, + pipe, + stdoutFile, + stderrFile, + }; -/***/ }), + // Create the files and ensure these are locked down (for read and write) to + // the current user. The main concerns here are: + // + // * If we execute a command which prints sensitive output, then + // stdoutFile/stderrFile must not be readable by other users. + // * paramsFile must not be readable by other users, or else they can read it + // to figure out the path for stdoutFile/stderrFile and create these first + // (locked down to their own access), which will crash exec() when it tries + // to write to the files. + function writeFileLockedDown(filePath, data) { + fs.writeFileSync(filePath, data, { + encoding: 'utf8', + mode: parseInt('600', 8), + }); + } + writeFileLockedDown(stdoutFile, ''); + writeFileLockedDown(stderrFile, ''); + writeFileLockedDown(paramsFile, JSON.stringify(paramsToSerialize)); -/***/ 5016: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + var execArgs = [ + __nccwpck_require__.ab + "exec-child.js", + paramsFile, + ]; + + /* istanbul ignore else */ + if (opts.silent) { + opts.stdio = 'ignore'; + } else { + opts.stdio = [0, 1, 2]; + } -"use strict"; + var code = 0; + // Welcome to the future + try { + // Bad things if we pass in a `shell` option to child_process.execFileSync, + // so we need to explicitly remove it here. + delete opts.shell; -const compare = __nccwpck_require__(126) -const rcompare = (a, b, loose) => compare(b, a, loose) -module.exports = rcompare + child.execFileSync(common.config.execPath, execArgs, opts); + } catch (e) { + // Commands with non-zero exit code raise an exception. + code = e.status || DEFAULT_ERROR_CODE; + } + // fs.readFileSync uses buffer encoding by default, so call + // it without the encoding option if the encoding is 'buffer'. + // Also, if the exec timeout is too short for node to start up, + // the files will not be created, so these calls will throw. + var stdout = ''; + var stderr = ''; + if (opts.encoding === 'buffer') { + stdout = fs.readFileSync(stdoutFile); + stderr = fs.readFileSync(stderrFile); + } else { + stdout = fs.readFileSync(stdoutFile, opts.encoding); + stderr = fs.readFileSync(stderrFile, opts.encoding); + } -/***/ }), + // No biggie if we can't erase the files now -- they're in a temp dir anyway + // and we locked down permissions (see the note above). + try { common.unlinkSync(paramsFile); } catch (e) {} + try { common.unlinkSync(stderrFile); } catch (e) {} + try { common.unlinkSync(stdoutFile); } catch (e) {} -/***/ 5119: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + if (code !== 0) { + // Note: `silent` should be unconditionally true to avoid double-printing + // the command's stderr, and to avoid printing any stderr when the user has + // set `shell.config.silent`. + common.error(stderr, code, { continue: true, silent: true, fatal: opts.fatal }); + } + var obj = common.ShellString(stdout, stderr, code); + return obj; +} // execSync() -"use strict"; +// Wrapper around exec() to enable echoing output to console in real time +function execAsync(cmd, opts, pipe, callback) { + opts = common.extend({ + silent: common.config.silent, + fatal: common.config.fatal, // TODO(nfischer): this and the line above are probably unnecessary + cwd: _pwd().toString(), + env: process.env, + maxBuffer: DEFAULT_MAXBUFFER_SIZE, + encoding: 'utf8', + }, opts); + var c = child.exec(cmd, opts, function (err, stdout, stderr) { + if (callback) { + if (!err) { + callback(0, stdout, stderr); + } else if (err.code === undefined) { + // See issue #536 + /* istanbul ignore next */ + callback(1, stdout, stderr); + } else { + callback(err.code, stdout, stderr); + } + } + }); -const compareBuild = __nccwpck_require__(175) -const rsort = (list, loose) => list.sort((a, b) => compareBuild(b, a, loose)) -module.exports = rsort + if (pipe) c.stdin.end(pipe); + if (!opts.silent) { + c.stdout.pipe(process.stdout); + c.stderr.pipe(process.stderr); + } -/***/ }), + return c; +} -/***/ 9832: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +//@ +//@ ### exec(command [, options] [, callback]) +//@ +//@ Available options: +//@ +//@ + `async`: Asynchronous execution. If a callback is provided, it will be set to +//@ `true`, regardless of the passed value (default: `false`). +//@ + `fatal`: Exit upon error (default: `false`). +//@ + `silent`: Do not echo program output to console (default: `false`). +//@ + `encoding`: Character encoding to use. Affects the values returned to stdout and stderr, and +//@ what is written to stdout and stderr when not in silent mode (default: `'utf8'`). +//@ + and any option available to Node.js's +//@ [`child_process.exec()`](https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback) +//@ +//@ Examples: +//@ +//@ ```javascript +//@ var version = exec('node --version', {silent:true}).stdout; +//@ +//@ var child = exec('some_long_running_process', {async:true}); +//@ child.stdout.on('data', function(data) { +//@ /* ... do something with data ... */ +//@ }); +//@ +//@ exec('some_long_running_process', function(code, stdout, stderr) { +//@ console.log('Exit code:', code); +//@ console.log('Program output:', stdout); +//@ console.log('Program stderr:', stderr); +//@ }); +//@ ``` +//@ +//@ Executes the given `command` _synchronously_, unless otherwise specified. +//@ When in synchronous mode, this returns a [ShellString](#shellstringstr). +//@ Otherwise, this returns the child process object, and the `callback` +//@ receives the arguments `(code, stdout, stderr)`. +//@ +//@ Not seeing the behavior you want? `exec()` runs everything through `sh` +//@ by default (or `cmd.exe` on Windows), which differs from `bash`. If you +//@ need bash-specific behavior, try out the `{shell: 'path/to/bash'}` option. +//@ +//@ **Security note:** as `shell.exec()` executes an arbitrary string in the +//@ system shell, it is **critical** to properly sanitize user input to avoid +//@ **command injection**. For more context, consult the [Security +//@ Guidelines](https://github.com/shelljs/shelljs/wiki/Security-guidelines). +function _exec(command, options, callback) { + options = options || {}; -"use strict"; + var pipe = common.readFromPipe(); + // Callback is defined instead of options. + if (typeof options === 'function') { + callback = options; + options = { async: true }; + } -const Range = __nccwpck_require__(8037) -const satisfies = (version, range, options) => { - try { - range = new Range(range, options) - } catch (er) { - return false + // Callback is defined with options. + if (typeof options === 'object' && typeof callback === 'function') { + options.async = true; + } + + options = common.extend({ + silent: common.config.silent, + fatal: common.config.fatal, + async: false, + }, options); + + if (!command) { + try { + common.error('must specify command'); + } catch (e) { + if (options.fatal) { + throw e; + } + + return; + } + } + + if (options.async) { + return execAsync(command, options, pipe, callback); + } else { + return execSync(command, options, pipe); } - return range.test(version) } -module.exports = satisfies +module.exports = _exec; /***/ }), -/***/ 5025: +/***/ 9638: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; +var path = __nccwpck_require__(6928); +var common = __nccwpck_require__(8400); +var _ls = __nccwpck_require__(4800); +common.register('find', _find, { + cmdOptions: { + 'L': 'link', + }, +}); -const compareBuild = __nccwpck_require__(175) -const sort = (list, loose) => list.sort((a, b) => compareBuild(a, b, loose)) -module.exports = sort +//@ +//@ ### find(path [, path ...]) +//@ ### find(path_array) +//@ +//@ Examples: +//@ +//@ ```javascript +//@ find('src', 'lib'); +//@ find(['src', 'lib']); // same as above +//@ find('.').filter(function(file) { return file.match(/\.js$/); }); +//@ ``` +//@ +//@ Returns a [ShellString](#shellstringstr) (with array-like properties) of all +//@ files (however deep) in the given paths. +//@ +//@ The main difference from `ls('-R', path)` is that the resulting file names +//@ include the base directories (e.g., `lib/resources/file1` instead of just `file1`). +function _find(options, paths) { + if (!paths) { + common.error('no path specified'); + } else if (typeof paths === 'string') { + paths = [].slice.call(arguments, 1); + } + var list = []; -/***/ }), + function pushFile(file) { + if (process.platform === 'win32') { + file = file.replace(/\\/g, '/'); + } + list.push(file); + } -/***/ 9383: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // why not simply do `ls('-R', paths)`? because the output wouldn't give the base dirs + // to get the base dir in the output, we need instead `ls('-R', 'dir/*')` for every directory -"use strict"; + paths.forEach(function (file) { + var stat; + try { + stat = common.statFollowLinks(file); + } catch (e) { + common.error('no such file or directory: ' + file); + } + pushFile(file); -const parse = __nccwpck_require__(162) -const valid = (version, options) => { - const v = parse(version, options) - return v ? v.version : null + if (stat.isDirectory()) { + _ls({ recursive: true, all: true, link: options.link }, file).forEach(function (subfile) { + pushFile(path.join(file, subfile)); + }); + } + }); + + return list; } -module.exports = valid +module.exports = _find; /***/ }), -/***/ 388: +/***/ 573: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; - - -// just pre-load all the stuff that index.js lazily exports -const internalRe = __nccwpck_require__(3032) -const constants = __nccwpck_require__(7108) -const SemVer = __nccwpck_require__(2478) -const identifiers = __nccwpck_require__(5341) -const parse = __nccwpck_require__(162) -const valid = __nccwpck_require__(9383) -const clean = __nccwpck_require__(6152) -const inc = __nccwpck_require__(6473) -const diff = __nccwpck_require__(3854) -const major = __nccwpck_require__(1536) -const minor = __nccwpck_require__(3900) -const patch = __nccwpck_require__(9443) -const prerelease = __nccwpck_require__(1779) -const compare = __nccwpck_require__(126) -const rcompare = __nccwpck_require__(5016) -const compareLoose = __nccwpck_require__(9621) -const compareBuild = __nccwpck_require__(175) -const sort = __nccwpck_require__(5025) -const rsort = __nccwpck_require__(5119) -const gt = __nccwpck_require__(9158) -const lt = __nccwpck_require__(4009) -const eq = __nccwpck_require__(4255) -const neq = __nccwpck_require__(9469) -const gte = __nccwpck_require__(9727) -const lte = __nccwpck_require__(4394) -const cmp = __nccwpck_require__(1941) -const coerce = __nccwpck_require__(6536) -const Comparator = __nccwpck_require__(2514) -const Range = __nccwpck_require__(8037) -const satisfies = __nccwpck_require__(9832) -const toComparators = __nccwpck_require__(1461) -const maxSatisfying = __nccwpck_require__(8714) -const minSatisfying = __nccwpck_require__(3792) -const minVersion = __nccwpck_require__(7051) -const validRange = __nccwpck_require__(2668) -const outside = __nccwpck_require__(1129) -const gtr = __nccwpck_require__(8097) -const ltr = __nccwpck_require__(5416) -const intersects = __nccwpck_require__(9026) -const simplifyRange = __nccwpck_require__(1527) -const subset = __nccwpck_require__(998) -module.exports = { - parse, - valid, - clean, - inc, - diff, - major, - minor, - patch, - prerelease, - compare, - rcompare, - compareLoose, - compareBuild, - sort, - rsort, - gt, - lt, - eq, - neq, - gte, - lte, - cmp, - coerce, - Comparator, - Range, - satisfies, - toComparators, - maxSatisfying, - minSatisfying, - minVersion, - validRange, - outside, - gtr, - ltr, - intersects, - simplifyRange, - subset, - SemVer, - re: internalRe.re, - src: internalRe.src, - tokens: internalRe.t, - SEMVER_SPEC_VERSION: constants.SEMVER_SPEC_VERSION, - RELEASE_TYPES: constants.RELEASE_TYPES, - compareIdentifiers: identifiers.compareIdentifiers, - rcompareIdentifiers: identifiers.rcompareIdentifiers, -} +var fs = __nccwpck_require__(9896); +var common = __nccwpck_require__(8400); +common.register('grep', _grep, { + globStart: 2, // don't glob-expand the regex + canReceivePipe: true, + cmdOptions: { + 'v': 'inverse', + 'l': 'nameOnly', + 'i': 'ignoreCase', + 'n': 'lineNumber', + 'B': 'beforeContext', + 'A': 'afterContext', + 'C': 'context', + }, +}); -/***/ }), +//@ +//@ ### grep([options,] regex_filter, file [, file ...]) +//@ ### grep([options,] regex_filter, file_array) +//@ +//@ Available options: +//@ +//@ + `-v`: Invert `regex_filter` (only print non-matching lines). +//@ + `-l`: Print only filenames of matching files. +//@ + `-i`: Ignore case. +//@ + `-n`: Print line numbers. +//@ + `-B `: Show `` lines before each result. +//@ + `-A `: Show `` lines after each result. +//@ + `-C `: Show `` lines before and after each result. -B and -A override this option. +//@ +//@ Examples: +//@ +//@ ```javascript +//@ grep('-v', 'GLOBAL_VARIABLE', '*.js'); +//@ grep('GLOBAL_VARIABLE', '*.js'); +//@ grep('-B', 3, 'GLOBAL_VARIABLE', '*.js'); +//@ grep({ '-B': 3 }, 'GLOBAL_VARIABLE', '*.js'); +//@ grep({ '-B': 3, '-C': 2 }, 'GLOBAL_VARIABLE', '*.js'); +//@ ``` +//@ +//@ Reads input string from given files and returns a +//@ [ShellString](#shellstringstr) containing all lines of the @ file that match +//@ the given `regex_filter`. +function _grep(options, regex, files) { + // Check if this is coming from a pipe + var pipe = common.readFromPipe(); -/***/ 7108: -/***/ ((module) => { + if (!files && !pipe) common.error('no paths given', 2); -"use strict"; + var idx = 2; + var contextError = ': invalid context length argument'; + // If the option has been found but not read, copy value from arguments + if (options.beforeContext === true) { + idx = 3; + options.beforeContext = Number(arguments[1]); + if (options.beforeContext < 0) { + common.error(options.beforeContext + contextError, 2); + } + } + if (options.afterContext === true) { + idx = 3; + options.afterContext = Number(arguments[1]); + if (options.afterContext < 0) { + common.error(options.afterContext + contextError, 2); + } + } + if (options.context === true) { + idx = 3; + options.context = Number(arguments[1]); + if (options.context < 0) { + common.error(options.context + contextError, 2); + } + } + // If before or after not given but context is, update values + if (typeof options.context === 'number') { + if (options.beforeContext === false) { + options.beforeContext = options.context; + } + if (options.afterContext === false) { + options.afterContext = options.context; + } + } + regex = arguments[idx - 1]; + files = [].slice.call(arguments, idx); + if (pipe) { + files.unshift('-'); + } -// Note: this is the semver.org version of the spec that it implements -// Not necessarily the package version of this code. -const SEMVER_SPEC_VERSION = '2.0.0' + var grep = []; + if (options.ignoreCase) { + regex = new RegExp(regex, 'i'); + } + files.forEach(function (file) { + if (!fs.existsSync(file) && file !== '-') { + common.error('no such file or directory: ' + file, 2, { continue: true }); + return; + } -const MAX_LENGTH = 256 -const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || -/* istanbul ignore next */ 9007199254740991 + var contents = file === '-' ? pipe : fs.readFileSync(file, 'utf8'); + if (options.nameOnly) { + if (contents.match(regex)) { + grep.push(file); + } + } else { + var lines = contents.split('\n'); + var matches = []; -// Max safe segment length for coercion. -const MAX_SAFE_COMPONENT_LENGTH = 16 + lines.forEach(function (line, index) { + var matched = line.match(regex); + if ((options.inverse && !matched) || (!options.inverse && matched)) { + var lineNumber = index + 1; + var result = {}; + if (matches.length > 0) { + // If the last result intersects, combine them + var last = matches[matches.length - 1]; + var minimumLineNumber = Math.max( + 1, + lineNumber - options.beforeContext - 1, + ); + if ( + last.hasOwnProperty('' + lineNumber) || + last.hasOwnProperty('' + minimumLineNumber) + ) { + result = last; + } + } + result[lineNumber] = { + line, + match: true, + }; + if (options.beforeContext > 0) { + // Store the lines with their line numbers to check for overlap + lines + .slice(Math.max(index - options.beforeContext, 0), index) + .forEach(function (v, i, a) { + var lineNum = '' + (index - a.length + i + 1); + if (!result.hasOwnProperty(lineNum)) { + result[lineNum] = { line: v, match: false }; + } + }); + } + if (options.afterContext > 0) { + // Store the lines with their line numbers to check for overlap + lines + .slice( + index + 1, + Math.min(index + options.afterContext + 1, lines.length - 1), + ) + .forEach(function (v, i) { + var lineNum = '' + (index + 1 + i + 1); + if (!result.hasOwnProperty(lineNum)) { + result[lineNum] = { line: v, match: false }; + } + }); + } + // Only add the result if it's new + if (!matches.includes(result)) { + matches.push(result); + } + } + }); -// Max safe length for a build identifier. The max length minus 6 characters for -// the shortest version with a build 0.0.0+BUILD. -const MAX_SAFE_BUILD_LENGTH = MAX_LENGTH - 6 + // Loop through the matches and add them to the output + Array.prototype.push.apply( + grep, + matches.map(function (result) { + return Object.entries(result) + .map(function (entry) { + var lineNumber = entry[0]; + var line = entry[1].line; + var match = entry[1].match; + return options.lineNumber + ? lineNumber + (match ? ':' : '-') + line + : line; + }) + .join('\n'); + }), + ); + } + }); -const RELEASE_TYPES = [ - 'major', - 'premajor', - 'minor', - 'preminor', - 'patch', - 'prepatch', - 'prerelease', -] + if (grep.length === 0 && common.state.errorCode !== 2) { + // We didn't hit the error above, but pattern didn't match + common.error('', { silent: true }); + } -module.exports = { - MAX_LENGTH, - MAX_SAFE_COMPONENT_LENGTH, - MAX_SAFE_BUILD_LENGTH, - MAX_SAFE_INTEGER, - RELEASE_TYPES, - SEMVER_SPEC_VERSION, - FLAG_INCLUDE_PRERELEASE: 0b001, - FLAG_LOOSE: 0b010, + var separator = '\n'; + if ( + typeof options.beforeContext === 'number' || + typeof options.afterContext === 'number' + ) { + separator = '\n--\n'; + } + return grep.join(separator) + '\n'; } +module.exports = _grep; /***/ }), -/***/ 6018: -/***/ ((module) => { - -"use strict"; +/***/ 1787: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +var fs = __nccwpck_require__(9896); +var common = __nccwpck_require__(8400); -const debug = ( - typeof process === 'object' && - process.env && - process.env.NODE_DEBUG && - /\bsemver\b/i.test(process.env.NODE_DEBUG) -) ? (...args) => console.error('SEMVER', ...args) - : () => {} +common.register('head', _head, { + canReceivePipe: true, + cmdOptions: { + 'n': 'numLines', + }, +}); -module.exports = debug +// Reads |numLines| lines or the entire file, whichever is less. +function readSomeLines(file, numLines) { + var buf = common.buffer(); + var bufLength = buf.length; + var bytesRead = bufLength; + var pos = 0; + var fdr = fs.openSync(file, 'r'); + var numLinesRead = 0; + var ret = ''; + while (bytesRead === bufLength && numLinesRead < numLines) { + bytesRead = fs.readSync(fdr, buf, 0, bufLength, pos); + var bufStr = buf.toString('utf8', 0, bytesRead); + numLinesRead += bufStr.split('\n').length - 1; + ret += bufStr; + pos += bytesRead; + } -/***/ }), + fs.closeSync(fdr); + return ret; +} -/***/ 5341: -/***/ ((module) => { +//@ +//@ ### head([{'-n': \},] file [, file ...]) +//@ ### head([{'-n': \},] file_array) +//@ +//@ Available options: +//@ +//@ + `-n `: Show the first `` lines of the files +//@ +//@ Examples: +//@ +//@ ```javascript +//@ var str = head({'-n': 1}, 'file*.txt'); +//@ var str = head('file1', 'file2'); +//@ var str = head(['file1', 'file2']); // same as above +//@ ``` +//@ +//@ Read the start of a `file`. Returns a [ShellString](#shellstringstr). +function _head(options, files) { + var head = []; + var pipe = common.readFromPipe(); -"use strict"; + if (!files && !pipe) common.error('no paths given'); + var idx = 1; + if (options.numLines === true) { + idx = 2; + options.numLines = Number(arguments[1]); + } else if (options.numLines === false) { + options.numLines = 10; + } + files = [].slice.call(arguments, idx); -const numeric = /^[0-9]+$/ -const compareIdentifiers = (a, b) => { - if (typeof a === 'number' && typeof b === 'number') { - return a === b ? 0 : a < b ? -1 : 1 + if (pipe) { + files.unshift('-'); } - const anum = numeric.test(a) - const bnum = numeric.test(b) + var shouldAppendNewline = false; + files.forEach(function (file) { + if (file !== '-') { + if (!fs.existsSync(file)) { + common.error('no such file or directory: ' + file, { continue: true }); + return; + } else if (common.statFollowLinks(file).isDirectory()) { + common.error("error reading '" + file + "': Is a directory", { + continue: true, + }); + return; + } + } - if (anum && bnum) { - a = +a - b = +b - } + var contents; + if (file === '-') { + contents = pipe; + } else if (options.numLines < 0) { + contents = fs.readFileSync(file, 'utf8'); + } else { + contents = readSomeLines(file, options.numLines); + } - return a === b ? 0 - : (anum && !bnum) ? -1 - : (bnum && !anum) ? 1 - : a < b ? -1 - : 1 -} + var lines = contents.split('\n'); + var hasTrailingNewline = (lines[lines.length - 1] === ''); + if (hasTrailingNewline) { + lines.pop(); + } + shouldAppendNewline = (hasTrailingNewline || options.numLines < lines.length); -const rcompareIdentifiers = (a, b) => compareIdentifiers(b, a) + head = head.concat(lines.slice(0, options.numLines)); + }); -module.exports = { - compareIdentifiers, - rcompareIdentifiers, + if (shouldAppendNewline) { + head.push(''); // to add a trailing newline once we join + } + return head.join('\n'); } +module.exports = _head; /***/ }), -/***/ 6684: -/***/ ((module) => { +/***/ 507: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; +var fs = __nccwpck_require__(9896); +var path = __nccwpck_require__(6928); +var common = __nccwpck_require__(8400); +common.register('ln', _ln, { + cmdOptions: { + 's': 'symlink', + 'f': 'force', + }, +}); -class LRUCache { - constructor () { - this.max = 1000 - this.map = new Map() +//@ +//@ ### ln([options,] source, dest) +//@ +//@ Available options: +//@ +//@ + `-s`: symlink +//@ + `-f`: force +//@ +//@ Examples: +//@ +//@ ```javascript +//@ ln('file', 'newlink'); +//@ ln('-sf', 'file', 'existing'); +//@ ``` +//@ +//@ Links `source` to `dest`. Use `-f` to force the link, should `dest` already +//@ exist. Returns a [ShellString](#shellstringstr) indicating success or +//@ failure. +function _ln(options, source, dest) { + if (!source || !dest) { + common.error('Missing and/or '); } - get (key) { - const value = this.map.get(key) - if (value === undefined) { - return undefined - } else { - // Remove the key from the map and add it to the end - this.map.delete(key) - this.map.set(key, value) - return value + source = String(source); + var sourcePath = path.normalize(source).replace(RegExp(path.sep + '$'), ''); + var isAbsolute = (path.resolve(source) === sourcePath); + dest = path.resolve(process.cwd(), String(dest)); + + if (fs.existsSync(dest)) { + if (!options.force) { + common.error('Destination file exists', { continue: true }); } - } - delete (key) { - return this.map.delete(key) + fs.unlinkSync(dest); } - set (key, value) { - const deleted = this.delete(key) - - if (!deleted && value !== undefined) { - // If cache is full, delete the least recently used item - if (this.map.size >= this.max) { - const firstKey = this.map.keys().next().value - this.delete(firstKey) - } - - this.map.set(key, value) + if (options.symlink) { + var isWindows = process.platform === 'win32'; + var linkType = isWindows ? 'file' : null; + var resolvedSourcePath = isAbsolute ? sourcePath : path.resolve(process.cwd(), path.dirname(dest), source); + if (!fs.existsSync(resolvedSourcePath)) { + common.error('Source file does not exist', { continue: true }); + } else if (isWindows && common.statFollowLinks(resolvedSourcePath).isDirectory()) { + linkType = 'junction'; } - return this + try { + fs.symlinkSync(linkType === 'junction' ? resolvedSourcePath : source, dest, linkType); + } catch (err) { + common.error(err.message); + } + } else { + if (!fs.existsSync(source)) { + common.error('Source file does not exist', { continue: true }); + } + try { + fs.linkSync(source, dest); + } catch (err) { + common.error(err.message); + } } + return ''; } - -module.exports = LRUCache +module.exports = _ln; /***/ }), -/***/ 9373: -/***/ ((module) => { - -"use strict"; - - -// parse out just the options we care about -const looseOption = Object.freeze({ loose: true }) -const emptyOpts = Object.freeze({ }) -const parseOptions = options => { - if (!options) { - return emptyOpts - } - - if (typeof options !== 'object') { - return looseOption - } - - return options -} -module.exports = parseOptions +/***/ 4800: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +var path = __nccwpck_require__(6928); +var fs = __nccwpck_require__(9896); +var glob = __nccwpck_require__(2206); +var common = __nccwpck_require__(8400); -/***/ }), +// glob patterns use the UNIX path seperator +var globPatternRecursive = '/**'; -/***/ 3032: -/***/ ((module, exports, __nccwpck_require__) => { +common.register('ls', _ls, { + cmdOptions: { + 'R': 'recursive', + 'A': 'all', + 'L': 'link', + 'a': 'all_deprecated', + 'd': 'directory', + 'l': 'long', + }, +}); -"use strict"; - - -const { - MAX_SAFE_COMPONENT_LENGTH, - MAX_SAFE_BUILD_LENGTH, - MAX_LENGTH, -} = __nccwpck_require__(7108) -const debug = __nccwpck_require__(6018) -exports = module.exports = {} - -// The actual regexps go on exports.re -const re = exports.re = [] -const safeRe = exports.safeRe = [] -const src = exports.src = [] -const safeSrc = exports.safeSrc = [] -const t = exports.t = {} -let R = 0 +//@ +//@ ### ls([options,] [path, ...]) +//@ ### ls([options,] path_array) +//@ +//@ Available options: +//@ +//@ + `-R`: recursive +//@ + `-A`: all files (include files beginning with `.`, except for `.` and `..`) +//@ + `-L`: follow symlinks +//@ + `-d`: list directories themselves, not their contents +//@ + `-l`: provides more details for each file. Specifically, each file is +//@ represented by a structured object with separate fields for file +//@ metadata (see +//@ [`fs.Stats`](https://nodejs.org/api/fs.html#fs_class_fs_stats)). The +//@ return value also overrides `.toString()` to resemble `ls -l`'s +//@ output format for human readability, but programmatic usage should +//@ depend on the stable object format rather than the `.toString()` +//@ representation. +//@ +//@ Examples: +//@ +//@ ```javascript +//@ ls('projs/*.js'); +//@ ls('projs/**/*.js'); // Find all js files recursively in projs +//@ ls('-R', '/users/me', '/tmp'); +//@ ls('-R', ['/users/me', '/tmp']); // same as above +//@ ls('-l', 'file.txt'); // { name: 'file.txt', mode: 33188, nlink: 1, ...} +//@ ``` +//@ +//@ Returns a [ShellString](#shellstringstr) (with array-like properties) of all +//@ the files in the given `path`, or files in the current directory if no +//@ `path` is provided. +function _ls(options, paths) { + if (options.all_deprecated) { + // We won't support the -a option as it's hard to image why it's useful + // (it includes '.' and '..' in addition to '.*' files) + // For backwards compatibility we'll dump a deprecated message and proceed as before + common.log('ls: Option -a is deprecated. Use -A instead'); + options.all = true; + } -const LETTERDASHNUMBER = '[a-zA-Z0-9-]' + if (!paths) { + paths = ['.']; + } else { + paths = [].slice.call(arguments, 1); + } -// Replace some greedy regex tokens to prevent regex dos issues. These regex are -// used internally via the safeRe object since all inputs in this library get -// normalized first to trim and collapse all extra whitespace. The original -// regexes are exported for userland consumption and lower level usage. A -// future breaking change could export the safer regex only with a note that -// all input should have extra whitespace removed. -const safeRegexReplacements = [ - ['\\s', 1], - ['\\d', MAX_LENGTH], - [LETTERDASHNUMBER, MAX_SAFE_BUILD_LENGTH], -] + var list = []; -const makeSafeRegex = (value) => { - for (const [token, max] of safeRegexReplacements) { - value = value - .split(`${token}*`).join(`${token}{0,${max}}`) - .split(`${token}+`).join(`${token}{1,${max}}`) + function pushFile(abs, relName, stat) { + if (process.platform === 'win32') { + relName = relName.replace(/\\/g, '/'); + } + if (options.long) { + stat = stat || (options.link ? common.statFollowLinks(abs) : common.statNoFollowLinks(abs)); + list.push(addLsAttributes(relName, stat)); + } else { + // list.push(path.relative(rel || '.', file)); + list.push(relName); + } } - return value -} - -const createToken = (name, value, isGlobal) => { - const safe = makeSafeRegex(value) - const index = R++ - debug(name, index, value) - t[name] = index - src[index] = value - safeSrc[index] = safe - re[index] = new RegExp(value, isGlobal ? 'g' : undefined) - safeRe[index] = new RegExp(safe, isGlobal ? 'g' : undefined) -} -// The following Regular Expressions can be used for tokenizing, -// validating, and parsing SemVer version strings. + paths.forEach(function (p) { + var stat; -// ## Numeric Identifier -// A single `0`, or a non-zero digit followed by zero or more digits. + try { + stat = options.link ? common.statFollowLinks(p) : common.statNoFollowLinks(p); + // follow links to directories by default + if (stat.isSymbolicLink()) { + /* istanbul ignore next */ + // workaround for https://github.com/shelljs/shelljs/issues/795 + // codecov seems to have a bug that miscalculate this block as uncovered. + // but according to nyc report this block does get covered. + try { + var _stat = common.statFollowLinks(p); + if (_stat.isDirectory()) { + stat = _stat; + } + } catch (_) {} // bad symlink, treat it like a file + } + } catch (e) { + common.error('no such file or directory: ' + p, 2, { continue: true }); + return; + } -createToken('NUMERICIDENTIFIER', '0|[1-9]\\d*') -createToken('NUMERICIDENTIFIERLOOSE', '\\d+') + // If the stat succeeded + if (stat.isDirectory() && !options.directory) { + if (options.recursive) { + // use glob, because it's simple + glob.sync(p + globPatternRecursive, { + // These options are just to make fast-glob be compatible with POSIX + // (bash) wildcard behavior. + onlyFiles: false, -// ## Non-numeric Identifier -// Zero or more digits, followed by a letter or hyphen, and then zero or -// more letters, digits, or hyphens. + // These options depend on the cmdOptions provided to ls. + dot: options.all, + followSymbolicLinks: options.link, + }).forEach(function (item) { + // Glob pattern returns the directory itself and needs to be filtered out. + if (path.relative(p, item)) { + pushFile(item, path.relative(p, item)); + } + }); + } else if (options.all) { + // use fs.readdirSync, because it's fast + fs.readdirSync(p).forEach(function (item) { + pushFile(path.join(p, item), item); + }); + } else { + // use fs.readdirSync and then filter out secret files + fs.readdirSync(p).forEach(function (item) { + if (item[0] !== '.') { + pushFile(path.join(p, item), item); + } + }); + } + } else { + pushFile(p, p, stat); + } + }); -createToken('NONNUMERICIDENTIFIER', `\\d*[a-zA-Z-]${LETTERDASHNUMBER}*`) + // Add methods, to make this more compatible with ShellStrings + return list; +} -// ## Main Version -// Three dot-separated numeric identifiers. +function addLsAttributes(pathName, stats) { + // Note: this object will contain more information than .toString() returns + stats.name = pathName; + stats.toString = function () { + // Return a string resembling unix's `ls -l` format + return [this.mode, this.nlink, this.uid, this.gid, this.size, this.mtime, this.name].join(' '); + }; + return stats; +} -createToken('MAINVERSION', `(${src[t.NUMERICIDENTIFIER]})\\.` + - `(${src[t.NUMERICIDENTIFIER]})\\.` + - `(${src[t.NUMERICIDENTIFIER]})`) +module.exports = _ls; -createToken('MAINVERSIONLOOSE', `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.` + - `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.` + - `(${src[t.NUMERICIDENTIFIERLOOSE]})`) -// ## Pre-release Version Identifier -// A numeric identifier, or a non-numeric identifier. -// Non-numberic identifiers include numberic identifiers but can be longer. -// Therefore non-numberic identifiers must go first. +/***/ }), -createToken('PRERELEASEIDENTIFIER', `(?:${src[t.NONNUMERICIDENTIFIER] -}|${src[t.NUMERICIDENTIFIER]})`) +/***/ 850: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -createToken('PRERELEASEIDENTIFIERLOOSE', `(?:${src[t.NONNUMERICIDENTIFIER] -}|${src[t.NUMERICIDENTIFIERLOOSE]})`) +var fs = __nccwpck_require__(9896); +var path = __nccwpck_require__(6928); +var common = __nccwpck_require__(8400); -// ## Pre-release Version -// Hyphen, followed by one or more dot-separated pre-release version -// identifiers. +common.register('mkdir', _mkdir, { + cmdOptions: { + 'p': 'fullpath', + }, +}); -createToken('PRERELEASE', `(?:-(${src[t.PRERELEASEIDENTIFIER] -}(?:\\.${src[t.PRERELEASEIDENTIFIER]})*))`) +// Recursively creates `dir` +function mkdirSyncRecursive(dir) { + var baseDir = path.dirname(dir); -createToken('PRERELEASELOOSE', `(?:-?(${src[t.PRERELEASEIDENTIFIERLOOSE] -}(?:\\.${src[t.PRERELEASEIDENTIFIERLOOSE]})*))`) + // Prevents some potential problems arising from malformed UNCs or + // insufficient permissions. + /* istanbul ignore next */ + if (baseDir === dir) { + common.error('dirname() failed: [' + dir + ']'); + } -// ## Build Metadata Identifier -// Any combination of digits, letters, or hyphens. + // Base dir does not exist, go recursive + if (!fs.existsSync(baseDir)) { + mkdirSyncRecursive(baseDir); + } -createToken('BUILDIDENTIFIER', `${LETTERDASHNUMBER}+`) + try { + // Base dir created, can create dir + fs.mkdirSync(dir, parseInt('0777', 8)); + } catch (e) { + // swallow error if dir already exists + if (e.code !== 'EEXIST' || common.statNoFollowLinks(dir).isFile()) { throw e; } + } +} -// ## Build Metadata -// Plus sign, followed by one or more period-separated build metadata -// identifiers. +//@ +//@ ### mkdir([options,] dir [, dir ...]) +//@ ### mkdir([options,] dir_array) +//@ +//@ Available options: +//@ +//@ + `-p`: full path (and create intermediate directories, if necessary) +//@ +//@ Examples: +//@ +//@ ```javascript +//@ mkdir('-p', '/tmp/a/b/c/d', '/tmp/e/f/g'); +//@ mkdir('-p', ['/tmp/a/b/c/d', '/tmp/e/f/g']); // same as above +//@ ``` +//@ +//@ Creates directories. Returns a [ShellString](#shellstringstr) indicating +//@ success or failure. +function _mkdir(options, dirs) { + if (!dirs) common.error('no paths given'); -createToken('BUILD', `(?:\\+(${src[t.BUILDIDENTIFIER] -}(?:\\.${src[t.BUILDIDENTIFIER]})*))`) + if (typeof dirs === 'string') { + dirs = [].slice.call(arguments, 1); + } + // if it's array leave it as it is -// ## Full Version String -// A main version, followed optionally by a pre-release version and -// build metadata. + dirs.forEach(function (dir) { + try { + var stat = common.statNoFollowLinks(dir); + if (!options.fullpath) { + common.error('path already exists: ' + dir, { continue: true }); + } else if (stat.isFile()) { + common.error('cannot create directory ' + dir + ': File exists', { continue: true }); + } + return; // skip dir + } catch (e) { + // do nothing + } -// Note that the only major, minor, patch, and pre-release sections of -// the version string are capturing groups. The build metadata is not a -// capturing group, because it should not ever be used in version -// comparison. + // Base dir does not exist, and no -p option given + var baseDir = path.dirname(dir); + if (!fs.existsSync(baseDir) && !options.fullpath) { + common.error('no such file or directory: ' + baseDir, { continue: true }); + return; // skip dir + } -createToken('FULLPLAIN', `v?${src[t.MAINVERSION] -}${src[t.PRERELEASE]}?${ - src[t.BUILD]}?`) + try { + if (options.fullpath) { + mkdirSyncRecursive(path.resolve(dir)); + } else { + fs.mkdirSync(dir, parseInt('0777', 8)); + } + } catch (e) { + var reason; + if (e.code === 'EACCES') { + reason = 'Permission denied'; + } else if (e.code === 'ENOTDIR' || e.code === 'ENOENT') { + reason = 'Not a directory'; + } else { + /* istanbul ignore next */ + throw e; + } + common.error('cannot create directory ' + dir + ': ' + reason, { continue: true }); + } + }); + return ''; +} // man arraykdir +module.exports = _mkdir; -createToken('FULL', `^${src[t.FULLPLAIN]}$`) -// like full, but allows v1.2.3 and =1.2.3, which people do sometimes. -// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty -// common in the npm registry. -createToken('LOOSEPLAIN', `[v=\\s]*${src[t.MAINVERSIONLOOSE] -}${src[t.PRERELEASELOOSE]}?${ - src[t.BUILD]}?`) +/***/ }), -createToken('LOOSE', `^${src[t.LOOSEPLAIN]}$`) +/***/ 7314: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -createToken('GTLT', '((?:<|>)?=?)') +var fs = __nccwpck_require__(9896); +var path = __nccwpck_require__(6928); +var common = __nccwpck_require__(8400); +var cp = __nccwpck_require__(1642); +var rm = __nccwpck_require__(6900); -// Something like "2.*" or "1.2.x". -// Note that "x.x" is a valid xRange identifer, meaning "any version" -// Only the first item is strictly required. -createToken('XRANGEIDENTIFIERLOOSE', `${src[t.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`) -createToken('XRANGEIDENTIFIER', `${src[t.NUMERICIDENTIFIER]}|x|X|\\*`) +common.register('mv', _mv, { + cmdOptions: { + 'f': '!no_force', + 'n': 'no_force', + }, +}); -createToken('XRANGEPLAIN', `[v=\\s]*(${src[t.XRANGEIDENTIFIER]})` + - `(?:\\.(${src[t.XRANGEIDENTIFIER]})` + - `(?:\\.(${src[t.XRANGEIDENTIFIER]})` + - `(?:${src[t.PRERELEASE]})?${ - src[t.BUILD]}?` + - `)?)?`) +// Checks if cureent file was created recently +function checkRecentCreated(sources, index) { + var lookedSource = sources[index]; + return sources.slice(0, index).some(function (src) { + return path.basename(src) === path.basename(lookedSource); + }); +} -createToken('XRANGEPLAINLOOSE', `[v=\\s]*(${src[t.XRANGEIDENTIFIERLOOSE]})` + - `(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` + - `(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` + - `(?:${src[t.PRERELEASELOOSE]})?${ - src[t.BUILD]}?` + - `)?)?`) +//@ +//@ ### mv([options ,] source [, source ...], dest') +//@ ### mv([options ,] source_array, dest') +//@ +//@ Available options: +//@ +//@ + `-f`: force (default behavior) +//@ + `-n`: no-clobber +//@ +//@ Examples: +//@ +//@ ```javascript +//@ mv('-n', 'file', 'dir/'); +//@ mv('file1', 'file2', 'dir/'); +//@ mv(['file1', 'file2'], 'dir/'); // same as above +//@ ``` +//@ +//@ Moves `source` file(s) to `dest`. Returns a [ShellString](#shellstringstr) +//@ indicating success or failure. +function _mv(options, sources, dest) { + // Get sources, dest + if (arguments.length < 3) { + common.error('missing and/or '); + } else if (arguments.length > 3) { + sources = [].slice.call(arguments, 1, arguments.length - 1); + dest = arguments[arguments.length - 1]; + } else if (typeof sources === 'string') { + sources = [sources]; + } else { + // TODO(nate): figure out if we actually need this line + common.error('invalid arguments'); + } -createToken('XRANGE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAIN]}$`) -createToken('XRANGELOOSE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAINLOOSE]}$`) + var exists = fs.existsSync(dest); + var stats = exists && common.statFollowLinks(dest); -// Coercion. -// Extract anything that could conceivably be a part of a valid semver -createToken('COERCEPLAIN', `${'(^|[^\\d])' + - '(\\d{1,'}${MAX_SAFE_COMPONENT_LENGTH}})` + - `(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?` + - `(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?`) -createToken('COERCE', `${src[t.COERCEPLAIN]}(?:$|[^\\d])`) -createToken('COERCEFULL', src[t.COERCEPLAIN] + - `(?:${src[t.PRERELEASE]})?` + - `(?:${src[t.BUILD]})?` + - `(?:$|[^\\d])`) -createToken('COERCERTL', src[t.COERCE], true) -createToken('COERCERTLFULL', src[t.COERCEFULL], true) + // Dest is not existing dir, but multiple sources given + if ((!exists || !stats.isDirectory()) && sources.length > 1) { + common.error('dest is not a directory (too many sources)'); + } -// Tilde ranges. -// Meaning is "reasonably at or greater than" -createToken('LONETILDE', '(?:~>?)') + // Dest is an existing file, but no -f given + if (exists && stats.isFile() && options.no_force) { + common.error('dest file already exists: ' + dest); + } -createToken('TILDETRIM', `(\\s*)${src[t.LONETILDE]}\\s+`, true) -exports.tildeTrimReplace = '$1~' + sources.forEach(function (src, srcIndex) { + if (!fs.existsSync(src)) { + common.error('no such file or directory: ' + src, { continue: true }); + return; // skip file + } -createToken('TILDE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAIN]}$`) -createToken('TILDELOOSE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAINLOOSE]}$`) + // If here, src exists -// Caret ranges. -// Meaning is "at least and backwards compatible with" -createToken('LONECARET', '(?:\\^)') + // When copying to '/path/dir': + // thisDest = '/path/dir/file1' + var thisDest = dest; + if (fs.existsSync(dest) && common.statFollowLinks(dest).isDirectory()) { + thisDest = path.normalize(dest + '/' + path.basename(src)); + } -createToken('CARETTRIM', `(\\s*)${src[t.LONECARET]}\\s+`, true) -exports.caretTrimReplace = '$1^' + var thisDestExists = fs.existsSync(thisDest); -createToken('CARET', `^${src[t.LONECARET]}${src[t.XRANGEPLAIN]}$`) -createToken('CARETLOOSE', `^${src[t.LONECARET]}${src[t.XRANGEPLAINLOOSE]}$`) + if (thisDestExists && checkRecentCreated(sources, srcIndex)) { + // cannot overwrite file created recently in current execution, but we want to continue copying other files + if (!options.no_force) { + common.error("will not overwrite just-created '" + thisDest + "' with '" + src + "'", { continue: true }); + } + return; + } -// A simple gt/lt/eq thing, or just "" to indicate "any version" -createToken('COMPARATORLOOSE', `^${src[t.GTLT]}\\s*(${src[t.LOOSEPLAIN]})$|^$`) -createToken('COMPARATOR', `^${src[t.GTLT]}\\s*(${src[t.FULLPLAIN]})$|^$`) + if (fs.existsSync(thisDest) && options.no_force) { + common.error('dest file already exists: ' + thisDest, { continue: true }); + return; // skip file + } -// An expression to strip any whitespace between the gtlt and the thing -// it modifies, so that `> 1.2.3` ==> `>1.2.3` -createToken('COMPARATORTRIM', `(\\s*)${src[t.GTLT] -}\\s*(${src[t.LOOSEPLAIN]}|${src[t.XRANGEPLAIN]})`, true) -exports.comparatorTrimReplace = '$1$2$3' + if (path.resolve(src) === path.dirname(path.resolve(thisDest))) { + common.error('cannot move to self: ' + src, { continue: true }); + return; // skip file + } -// Something like `1.2.3 - 1.2.4` -// Note that these all use the loose form, because they'll be -// checked against either the strict or loose comparator form -// later. -createToken('HYPHENRANGE', `^\\s*(${src[t.XRANGEPLAIN]})` + - `\\s+-\\s+` + - `(${src[t.XRANGEPLAIN]})` + - `\\s*$`) + try { + fs.renameSync(src, thisDest); + } catch (e) { + /* istanbul ignore next */ + if (e.code === 'EXDEV') { + // If we're trying to `mv` to an external partition, we'll actually need + // to perform a copy and then clean up the original file. If either the + // copy or the rm fails with an exception, we should allow this + // exception to pass up to the top level. + cp({ recursive: true }, src, thisDest); + rm({ recursive: true, force: true }, src); + } + } + }); // forEach(src) + return ''; +} // mv +module.exports = _mv; -createToken('HYPHENRANGELOOSE', `^\\s*(${src[t.XRANGEPLAINLOOSE]})` + - `\\s+-\\s+` + - `(${src[t.XRANGEPLAINLOOSE]})` + - `\\s*$`) -// Star ranges basically just allow anything at all. -createToken('STAR', '(<|>)?=?\\s*\\*') -// >=0.0.0 is like a star -createToken('GTE0', '^\\s*>=\\s*0\\.0\\.0\\s*$') -createToken('GTE0PRE', '^\\s*>=\\s*0\\.0\\.0-0\\s*$') +/***/ }), +/***/ 9844: +/***/ (() => { -/***/ }), +// see dirs.js -/***/ 8097: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; +/***/ }), +/***/ 7653: +/***/ (() => { -// Determine if version is greater than all the versions possible in the range. -const outside = __nccwpck_require__(1129) -const gtr = (version, range, options) => outside(version, range, '>', options) -module.exports = gtr +// see dirs.js /***/ }), -/***/ 9026: +/***/ 566: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; +var path = __nccwpck_require__(6928); +var common = __nccwpck_require__(8400); +common.register('pwd', _pwd, { + allowGlobbing: false, +}); -const Range = __nccwpck_require__(8037) -const intersects = (r1, r2, options) => { - r1 = new Range(r1, options) - r2 = new Range(r2, options) - return r1.intersects(r2, options) +//@ +//@ ### pwd() +//@ +//@ Returns the current directory as a [ShellString](#shellstringstr). +function _pwd() { + var pwd = path.resolve(process.cwd()); + return pwd; } -module.exports = intersects +module.exports = _pwd; /***/ }), -/***/ 5416: +/***/ 6900: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; - +var fs = __nccwpck_require__(9896); +var common = __nccwpck_require__(8400); -const outside = __nccwpck_require__(1129) -// Determine if version is less than all the versions possible in the range -const ltr = (version, range, options) => outside(version, range, '<', options) -module.exports = ltr +common.register('rm', _rm, { + cmdOptions: { + 'f': 'force', + 'r': 'recursive', + 'R': 'recursive', + }, +}); +// Recursively removes 'dir' +// Adapted from https://github.com/ryanmcgrath/wrench-js +// +// Copyright (c) 2010 Ryan McGrath +// Copyright (c) 2012 Artur Adib +// +// Licensed under the MIT License +// http://www.opensource.org/licenses/mit-license.php +function rmdirSyncRecursive(dir, force, fromSymlink) { + var files; -/***/ }), + files = fs.readdirSync(dir); -/***/ 8714: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // Loop through and delete everything in the sub-tree after checking it + for (var i = 0; i < files.length; i++) { + var file = dir + '/' + files[i]; + var currFile = common.statNoFollowLinks(file); -"use strict"; + if (currFile.isDirectory()) { // Recursive function back to the beginning + rmdirSyncRecursive(file, force); + } else if (force || isWriteable(file)) { + // Assume it's a file - perhaps a try/catch belongs here? + try { + common.unlinkSync(file); + } catch (e) { + /* istanbul ignore next */ + common.error('could not remove file (code ' + e.code + '): ' + file, { + continue: true, + }); + } + } + } + // if was directory was referenced through a symbolic link, + // the contents should be removed, but not the directory itself + if (fromSymlink) return; -const SemVer = __nccwpck_require__(2478) -const Range = __nccwpck_require__(8037) + // Now that we know everything in the sub-tree has been deleted, we can delete the main directory. + // Huzzah for the shopkeep. -const maxSatisfying = (versions, range, options) => { - let max = null - let maxSV = null - let rangeObj = null + var result; try { - rangeObj = new Range(range, options) - } catch (er) { - return null - } - versions.forEach((v) => { - if (rangeObj.test(v)) { - // satisfies(v, range, options) - if (!max || maxSV.compare(v) === -1) { - // compare(max, v, true) - max = v - maxSV = new SemVer(max, options) + // Retry on windows, sometimes it takes a little time before all the files in the directory are gone + var start = Date.now(); + + // TODO: replace this with a finite loop + for (;;) { + try { + result = fs.rmdirSync(dir); + if (fs.existsSync(dir)) throw { code: 'EAGAIN' }; + break; + } catch (er) { + /* istanbul ignore next */ + // In addition to error codes, also check if the directory still exists and loop again if true + if (process.platform === 'win32' && (er.code === 'ENOTEMPTY' || er.code === 'EBUSY' || er.code === 'EPERM' || er.code === 'EAGAIN')) { + if (Date.now() - start > 1000) throw er; + } else if (er.code === 'ENOENT') { + // Directory did not exist, deletion was successful + break; + } else { + throw er; + } } } - }) - return max -} -module.exports = maxSatisfying + } catch (e) { + common.error('could not remove directory (code ' + e.code + '): ' + dir, { continue: true }); + } + return result; +} // rmdirSyncRecursive -/***/ }), +// Hack to determine if file has write permissions for current user +// Avoids having to check user, group, etc, but it's probably slow +function isWriteable(file) { + var writePermission = true; + try { + var __fd = fs.openSync(file, 'a'); + fs.closeSync(__fd); + } catch (e) { + writePermission = false; + } -/***/ 3792: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + return writePermission; +} -"use strict"; +function handleFile(file, options) { + if (options.force || isWriteable(file)) { + // -f was passed, or file is writable, so it can be removed + common.unlinkSync(file); + } else { + common.error('permission denied: ' + file, { continue: true }); + } +} +function handleDirectory(file, options) { + if (options.recursive) { + // -r was passed, so directory can be removed + rmdirSyncRecursive(file, options.force); + } else { + common.error('path is a directory', { continue: true }); + } +} -const SemVer = __nccwpck_require__(2478) -const Range = __nccwpck_require__(8037) -const minSatisfying = (versions, range, options) => { - let min = null - let minSV = null - let rangeObj = null +function handleSymbolicLink(file, options) { + var stats; try { - rangeObj = new Range(range, options) - } catch (er) { - return null + stats = common.statFollowLinks(file); + } catch (e) { + // symlink is broken, so remove the symlink itself + common.unlinkSync(file); + return; } - versions.forEach((v) => { - if (rangeObj.test(v)) { - // satisfies(v, range, options) - if (!min || minSV.compare(v) === 1) { - // compare(min, v, true) - min = v - minSV = new SemVer(min, options) + + if (stats.isFile()) { + common.unlinkSync(file); + } else if (stats.isDirectory()) { + if (file[file.length - 1] === '/') { + // trailing separator, so remove the contents, not the link + if (options.recursive) { + // -r was passed, so directory can be removed + var fromSymlink = true; + rmdirSyncRecursive(file, options.force, fromSymlink); + } else { + common.error('path is a directory', { continue: true }); } + } else { + // no trailing separator, so remove the link + common.unlinkSync(file); } - }) - return min + } } -module.exports = minSatisfying - -/***/ }), - -/***/ 7051: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -"use strict"; - - -const SemVer = __nccwpck_require__(2478) -const Range = __nccwpck_require__(8037) -const gt = __nccwpck_require__(9158) - -const minVersion = (range, loose) => { - range = new Range(range, loose) - - let minver = new SemVer('0.0.0') - if (range.test(minver)) { - return minver - } +function handleFIFO(file) { + common.unlinkSync(file); +} - minver = new SemVer('0.0.0-0') - if (range.test(minver)) { - return minver - } +//@ +//@ ### rm([options,] file [, file ...]) +//@ ### rm([options,] file_array) +//@ +//@ Available options: +//@ +//@ + `-f`: force +//@ + `-r, -R`: recursive +//@ +//@ Examples: +//@ +//@ ```javascript +//@ rm('-rf', '/tmp/*'); +//@ rm('some_file.txt', 'another_file.txt'); +//@ rm(['some_file.txt', 'another_file.txt']); // same as above +//@ ``` +//@ +//@ Removes files. Returns a [ShellString](#shellstringstr) indicating success +//@ or failure. +function _rm(options, files) { + if (!files) common.error('no paths given'); - minver = null - for (let i = 0; i < range.set.length; ++i) { - const comparators = range.set[i] + // Convert to array + files = [].slice.call(arguments, 1); - let setMin = null - comparators.forEach((comparator) => { - // Clone to avoid manipulating the comparator's semver object. - const compver = new SemVer(comparator.semver.version) - switch (comparator.operator) { - case '>': - if (compver.prerelease.length === 0) { - compver.patch++ - } else { - compver.prerelease.push(0) - } - compver.raw = compver.format() - /* fallthrough */ - case '': - case '>=': - if (!setMin || gt(compver, setMin)) { - setMin = compver - } - break - case '<': - case '<=': - /* Ignore maximum versions */ - break - /* istanbul ignore next */ - default: - throw new Error(`Unexpected operation: ${comparator.operator}`) + files.forEach(function (file) { + var lstats; + try { + var filepath = (file[file.length - 1] === '/') + ? file.slice(0, -1) // remove the '/' so lstatSync can detect symlinks + : file; + lstats = common.statNoFollowLinks(filepath); // test for existence + } catch (e) { + // Path does not exist, no force flag given + if (!options.force) { + common.error('no such file or directory: ' + file, { continue: true }); } - }) - if (setMin && (!minver || gt(minver, setMin))) { - minver = setMin + return; // skip file } - } - - if (minver && range.test(minver)) { - return minver - } - return null -} -module.exports = minVersion + // If here, path exists + if (lstats.isFile()) { + handleFile(file, options); + } else if (lstats.isDirectory()) { + handleDirectory(file, options); + } else if (lstats.isSymbolicLink()) { + handleSymbolicLink(file, options); + } else if (lstats.isFIFO()) { + handleFIFO(file); + } + }); // forEach(file) + return ''; +} // rm +module.exports = _rm; /***/ }), -/***/ 1129: +/***/ 7253: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; +var fs = __nccwpck_require__(9896); +var common = __nccwpck_require__(8400); +common.register('sed', _sed, { + globStart: 3, // don't glob-expand regexes + canReceivePipe: true, + cmdOptions: { + 'i': 'inplace', + }, +}); -const SemVer = __nccwpck_require__(2478) -const Comparator = __nccwpck_require__(2514) -const { ANY } = Comparator -const Range = __nccwpck_require__(8037) -const satisfies = __nccwpck_require__(9832) -const gt = __nccwpck_require__(9158) -const lt = __nccwpck_require__(4009) -const lte = __nccwpck_require__(4394) -const gte = __nccwpck_require__(9727) +//@ +//@ ### sed([options,] search_regex, replacement, file [, file ...]) +//@ ### sed([options,] search_regex, replacement, file_array) +//@ +//@ Available options: +//@ +//@ + `-i`: Replace contents of `file` in-place. _Note that no backups will be created!_ +//@ +//@ Examples: +//@ +//@ ```javascript +//@ sed('-i', 'PROGRAM_VERSION', 'v0.1.3', 'source.js'); +//@ ``` +//@ +//@ Reads an input string from `file`s, line by line, and performs a JavaScript `replace()` on +//@ each of the lines from the input string using the given `search_regex` and `replacement` string or +//@ function. Returns the new [ShellString](#shellstringstr) after replacement. +//@ +//@ Note: +//@ +//@ Like unix `sed`, ShellJS `sed` supports capture groups. Capture groups are specified +//@ using the `$n` syntax: +//@ +//@ ```javascript +//@ sed(/(\w+)\s(\w+)/, '$2, $1', 'file.txt'); +//@ ``` +//@ +//@ Also, like unix `sed`, ShellJS `sed` runs replacements on each line from the input file +//@ (split by '\n') separately, so `search_regex`es that span more than one line (or include '\n') +//@ will not match anything and nothing will be replaced. +function _sed(options, regex, replacement, files) { + // Check if this is coming from a pipe + var pipe = common.readFromPipe(); -const outside = (version, range, hilo, options) => { - version = new SemVer(version, options) - range = new Range(range, options) + if (typeof replacement !== 'string' && typeof replacement !== 'function') { + if (typeof replacement === 'number') { + replacement = replacement.toString(); // fallback + } else { + common.error('invalid replacement string'); + } + } - let gtfn, ltefn, ltfn, comp, ecomp - switch (hilo) { - case '>': - gtfn = gt - ltefn = lte - ltfn = lt - comp = '>' - ecomp = '>=' - break - case '<': - gtfn = lt - ltefn = gte - ltfn = gt - comp = '<' - ecomp = '<=' - break - default: - throw new TypeError('Must provide a hilo val of "<" or ">"') + // Convert all search strings to RegExp + if (typeof regex === 'string') { + regex = RegExp(regex); } - // If it satisfies the range it is not outside - if (satisfies(version, range, options)) { - return false + if (!files && !pipe) { + common.error('no files given'); } - // From now on, variable terms are as if we're in "gtr" mode. - // but note that everything is flipped for the "ltr" function. + files = [].slice.call(arguments, 3); - for (let i = 0; i < range.set.length; ++i) { - const comparators = range.set[i] + if (pipe) { + files.unshift('-'); + } - let high = null - let low = null + var sed = []; + files.forEach(function (file) { + if (!fs.existsSync(file) && file !== '-') { + common.error('no such file or directory: ' + file, 2, { continue: true }); + return; + } - comparators.forEach((comparator) => { - if (comparator.semver === ANY) { - comparator = new Comparator('>=0.0.0') - } - high = high || comparator - low = low || comparator - if (gtfn(comparator.semver, high.semver, options)) { - high = comparator - } else if (ltfn(comparator.semver, low.semver, options)) { - low = comparator - } - }) + var contents = file === '-' ? pipe : fs.readFileSync(file, 'utf8'); + var lines = contents.split('\n'); + var result = lines.map(function (line) { + return line.replace(regex, replacement); + }).join('\n'); - // If the edge version comparator has a operator then our version - // isn't outside it - if (high.operator === comp || high.operator === ecomp) { - return false - } + sed.push(result); - // If the lowest version comparator has an operator and our version - // is less than it then it isn't higher than the range - if ((!low.operator || low.operator === comp) && - ltefn(version, low.semver)) { - return false - } else if (low.operator === ecomp && ltfn(version, low.semver)) { - return false + if (options.inplace) { + fs.writeFileSync(file, result, 'utf8'); } + }); + + if (options.inplace) { + return ''; + } else { + return sed.join('\n'); } - return true } - -module.exports = outside +module.exports = _sed; /***/ }), -/***/ 1527: +/***/ 2501: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; +var common = __nccwpck_require__(8400); +common.register('set', _set, { + allowGlobbing: false, + wrapOutput: false, +}); -// given a set of versions and a range, create a "simplified" range -// that includes the same versions that the original range does -// If the original range is shorter than the simplified one, return that. -const satisfies = __nccwpck_require__(9832) -const compare = __nccwpck_require__(126) -module.exports = (versions, range, options) => { - const set = [] - let first = null - let prev = null - const v = versions.sort((a, b) => compare(a, b, options)) - for (const version of v) { - const included = satisfies(version, range, options) - if (included) { - prev = version - if (!first) { - first = version - } - } else { - if (prev) { - set.push([first, prev]) - } - prev = null - first = null - } +//@ +//@ ### set(options) +//@ +//@ Available options: +//@ +//@ + `+/-e`: exit upon error (`config.fatal`) +//@ + `+/-v`: verbose: show all commands (`config.verbose`) +//@ + `+/-f`: disable filename expansion (globbing) +//@ +//@ Examples: +//@ +//@ ```javascript +//@ set('-e'); // exit upon first error +//@ set('+e'); // this undoes a "set('-e')" +//@ ``` +//@ +//@ Sets global configuration variables. +function _set(options) { + if (!options) { + var args = [].slice.call(arguments, 0); + if (args.length < 2) common.error('must provide an argument'); + options = args[1]; } - if (first) { - set.push([first, null]) + var negate = (options[0] === '+'); + if (negate) { + options = '-' + options.slice(1); // parseOptions needs a '-' prefix + } + options = common.parseOptions(options, { + 'e': 'fatal', + 'v': 'verbose', + 'f': 'noglob', + }); + + if (negate) { + Object.keys(options).forEach(function (key) { + options[key] = !options[key]; + }); } - const ranges = [] - for (const [min, max] of set) { - if (min === max) { - ranges.push(min) - } else if (!max && min === v[0]) { - ranges.push('*') - } else if (!max) { - ranges.push(`>=${min}`) - } else if (min === v[0]) { - ranges.push(`<=${max}`) - } else { - ranges.push(`${min} - ${max}`) + Object.keys(options).forEach(function (key) { + // Only change the global config if `negate` is false and the option is true + // or if `negate` is true and the option is false (aka negate !== option) + if (negate !== options[key]) { + common.config[key] = options[key]; } - } - const simplified = ranges.join(' || ') - const original = typeof range.raw === 'string' ? range.raw : String(range) - return simplified.length < original.length ? simplified : range + }); } +module.exports = _set; /***/ }), -/***/ 998: +/***/ 1581: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; - +var fs = __nccwpck_require__(9896); +var common = __nccwpck_require__(8400); -const Range = __nccwpck_require__(8037) -const Comparator = __nccwpck_require__(2514) -const { ANY } = Comparator -const satisfies = __nccwpck_require__(9832) -const compare = __nccwpck_require__(126) - -// Complex range `r1 || r2 || ...` is a subset of `R1 || R2 || ...` iff: -// - Every simple range `r1, r2, ...` is a null set, OR -// - Every simple range `r1, r2, ...` which is not a null set is a subset of -// some `R1, R2, ...` -// -// Simple range `c1 c2 ...` is a subset of simple range `C1 C2 ...` iff: -// - If c is only the ANY comparator -// - If C is only the ANY comparator, return true -// - Else if in prerelease mode, return false -// - else replace c with `[>=0.0.0]` -// - If C is only the ANY comparator -// - if in prerelease mode, return true -// - else replace C with `[>=0.0.0]` -// - Let EQ be the set of = comparators in c -// - If EQ is more than one, return true (null set) -// - Let GT be the highest > or >= comparator in c -// - Let LT be the lowest < or <= comparator in c -// - If GT and LT, and GT.semver > LT.semver, return true (null set) -// - If any C is a = range, and GT or LT are set, return false -// - If EQ -// - If GT, and EQ does not satisfy GT, return true (null set) -// - If LT, and EQ does not satisfy LT, return true (null set) -// - If EQ satisfies every C, return true -// - Else return false -// - If GT -// - If GT.semver is lower than any > or >= comp in C, return false -// - If GT is >=, and GT.semver does not satisfy every C, return false -// - If GT.semver has a prerelease, and not in prerelease mode -// - If no C has a prerelease and the GT.semver tuple, return false -// - If LT -// - If LT.semver is greater than any < or <= comp in C, return false -// - If LT is <=, and LT.semver does not satisfy every C, return false -// - If GT.semver has a prerelease, and not in prerelease mode -// - If no C has a prerelease and the LT.semver tuple, return false -// - Else return true - -const subset = (sub, dom, options = {}) => { - if (sub === dom) { - return true - } - - sub = new Range(sub, options) - dom = new Range(dom, options) - let sawNonNull = false +common.register('sort', _sort, { + canReceivePipe: true, + cmdOptions: { + 'r': 'reverse', + 'n': 'numerical', + }, +}); - OUTER: for (const simpleSub of sub.set) { - for (const simpleDom of dom.set) { - const isSub = simpleSubset(simpleSub, simpleDom, options) - sawNonNull = sawNonNull || isSub !== null - if (isSub) { - continue OUTER - } - } - // the null set is a subset of everything, but null simple ranges in - // a complex range should be ignored. so if we saw a non-null range, - // then we know this isn't a subset, but if EVERY simple range was null, - // then it is a subset. - if (sawNonNull) { - return false - } - } - return true +// parse out the number prefix of a line +function parseNumber(str) { + var match = str.match(/^\s*(\d*)\s*(.*)$/); + return { num: Number(match[1]), value: match[2] }; } -const minimumVersionWithPreRelease = [new Comparator('>=0.0.0-0')] -const minimumVersion = [new Comparator('>=0.0.0')] - -const simpleSubset = (sub, dom, options) => { - if (sub === dom) { - return true - } - - if (sub.length === 1 && sub[0].semver === ANY) { - if (dom.length === 1 && dom[0].semver === ANY) { - return true - } else if (options.includePrerelease) { - sub = minimumVersionWithPreRelease - } else { - sub = minimumVersion - } - } - - if (dom.length === 1 && dom[0].semver === ANY) { - if (options.includePrerelease) { - return true - } else { - dom = minimumVersion - } - } - - const eqSet = new Set() - let gt, lt - for (const c of sub) { - if (c.operator === '>' || c.operator === '>=') { - gt = higherGT(gt, c, options) - } else if (c.operator === '<' || c.operator === '<=') { - lt = lowerLT(lt, c, options) - } else { - eqSet.add(c.semver) - } - } - - if (eqSet.size > 1) { - return null - } +// compare two strings case-insensitively, but examine case for strings that are +// case-insensitive equivalent +function unixCmp(a, b) { + var aLower = a.toLowerCase(); + var bLower = b.toLowerCase(); + return (aLower === bLower ? + -1 * a.localeCompare(b) : // unix sort treats case opposite how javascript does + aLower.localeCompare(bLower)); +} - let gtltComp - if (gt && lt) { - gtltComp = compare(gt.semver, lt.semver, options) - if (gtltComp > 0) { - return null - } else if (gtltComp === 0 && (gt.operator !== '>=' || lt.operator !== '<=')) { - return null - } +// compare two strings in the fashion that unix sort's -n option works +function numericalCmp(a, b) { + var objA = parseNumber(a); + var objB = parseNumber(b); + if (objA.hasOwnProperty('num') && objB.hasOwnProperty('num')) { + return ((objA.num !== objB.num) ? + (objA.num - objB.num) : + unixCmp(objA.value, objB.value)); + } else { + return unixCmp(objA.value, objB.value); } +} - // will iterate one or zero times - for (const eq of eqSet) { - if (gt && !satisfies(eq, String(gt), options)) { - return null - } - - if (lt && !satisfies(eq, String(lt), options)) { - return null - } +//@ +//@ ### sort([options,] file [, file ...]) +//@ ### sort([options,] file_array) +//@ +//@ Available options: +//@ +//@ + `-r`: Reverse the results +//@ + `-n`: Compare according to numerical value +//@ +//@ Examples: +//@ +//@ ```javascript +//@ sort('foo.txt', 'bar.txt'); +//@ sort('-r', 'foo.txt'); +//@ ``` +//@ +//@ Return the contents of the `file`s, sorted line-by-line as a +//@ [ShellString](#shellstringstr). Sorting multiple files mixes their content +//@ (just as unix `sort` does). +function _sort(options, files) { + // Check if this is coming from a pipe + var pipe = common.readFromPipe(); - for (const c of dom) { - if (!satisfies(eq, String(c), options)) { - return false - } - } + if (!files && !pipe) common.error('no files given'); - return true - } + files = [].slice.call(arguments, 1); - let higher, lower - let hasDomLT, hasDomGT - // if the subset has a prerelease, we need a comparator in the superset - // with the same tuple and a prerelease, or it's not a subset - let needDomLTPre = lt && - !options.includePrerelease && - lt.semver.prerelease.length ? lt.semver : false - let needDomGTPre = gt && - !options.includePrerelease && - gt.semver.prerelease.length ? gt.semver : false - // exception: <1.2.3-0 is the same as <1.2.3 - if (needDomLTPre && needDomLTPre.prerelease.length === 1 && - lt.operator === '<' && needDomLTPre.prerelease[0] === 0) { - needDomLTPre = false + if (pipe) { + files.unshift('-'); } - for (const c of dom) { - hasDomGT = hasDomGT || c.operator === '>' || c.operator === '>=' - hasDomLT = hasDomLT || c.operator === '<' || c.operator === '<=' - if (gt) { - if (needDomGTPre) { - if (c.semver.prerelease && c.semver.prerelease.length && - c.semver.major === needDomGTPre.major && - c.semver.minor === needDomGTPre.minor && - c.semver.patch === needDomGTPre.patch) { - needDomGTPre = false - } - } - if (c.operator === '>' || c.operator === '>=') { - higher = higherGT(gt, c, options) - if (higher === c && higher !== gt) { - return false - } - } else if (gt.operator === '>=' && !satisfies(gt.semver, String(c), options)) { - return false - } - } - if (lt) { - if (needDomLTPre) { - if (c.semver.prerelease && c.semver.prerelease.length && - c.semver.major === needDomLTPre.major && - c.semver.minor === needDomLTPre.minor && - c.semver.patch === needDomLTPre.patch) { - needDomLTPre = false - } - } - if (c.operator === '<' || c.operator === '<=') { - lower = lowerLT(lt, c, options) - if (lower === c && lower !== lt) { - return false - } - } else if (lt.operator === '<=' && !satisfies(lt.semver, String(c), options)) { - return false + var lines = files.reduce(function (accum, file) { + if (file !== '-') { + if (!fs.existsSync(file)) { + common.error('no such file or directory: ' + file, { continue: true }); + return accum; + } else if (common.statFollowLinks(file).isDirectory()) { + common.error('read failed: ' + file + ': Is a directory', { + continue: true, + }); + return accum; } } - if (!c.operator && (lt || gt) && gtltComp !== 0) { - return false - } - } - - // if there was a < or >, and nothing in the dom, then must be false - // UNLESS it was limited by another range in the other direction. - // Eg, >1.0.0 <1.0.1 is still a subset of <2.0.0 - if (gt && hasDomLT && !lt && gtltComp !== 0) { - return false - } - if (lt && hasDomGT && !gt && gtltComp !== 0) { - return false - } - - // we needed a prerelease range in a specific tuple, but didn't get one - // then this isn't a subset. eg >=1.2.3-pre is not a subset of >=1.0.0, - // because it includes prereleases in the 1.2.3 tuple - if (needDomGTPre || needDomLTPre) { - return false - } + var contents = file === '-' ? pipe : fs.readFileSync(file, 'utf8'); + return accum.concat(contents.trimRight().split('\n')); + }, []); - return true -} + var sorted = lines.sort(options.numerical ? numericalCmp : unixCmp); -// >=1.2.3 is lower than >1.2.3 -const higherGT = (a, b, options) => { - if (!a) { - return b + if (options.reverse) { + sorted = sorted.reverse(); } - const comp = compare(a.semver, b.semver, options) - return comp > 0 ? a - : comp < 0 ? b - : b.operator === '>' && a.operator === '>=' ? b - : a -} -// <=1.2.3 is higher than <1.2.3 -const lowerLT = (a, b, options) => { - if (!a) { - return b - } - const comp = compare(a.semver, b.semver, options) - return comp < 0 ? a - : comp > 0 ? b - : b.operator === '<' && a.operator === '<=' ? b - : a + return sorted.join('\n') + '\n'; } -module.exports = subset +module.exports = _sort; /***/ }), -/***/ 1461: +/***/ 8211: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; +var fs = __nccwpck_require__(9896); +var common = __nccwpck_require__(8400); +common.register('tail', _tail, { + canReceivePipe: true, + cmdOptions: { + 'n': 'numLines', + }, +}); -const Range = __nccwpck_require__(8037) +//@ +//@ ### tail([{'-n': \},] file [, file ...]) +//@ ### tail([{'-n': \},] file_array) +//@ +//@ Available options: +//@ +//@ + `-n `: Show the last `` lines of `file`s +//@ +//@ Examples: +//@ +//@ ```javascript +//@ var str = tail({'-n': 1}, 'file*.txt'); +//@ var str = tail('file1', 'file2'); +//@ var str = tail(['file1', 'file2']); // same as above +//@ ``` +//@ +//@ Read the end of a `file`. Returns a [ShellString](#shellstringstr). +function _tail(options, files) { + var tail = []; + var pipe = common.readFromPipe(); -// Mostly just for testing and legacy API reasons -const toComparators = (range, options) => - new Range(range, options).set - .map(comp => comp.map(c => c.value).join(' ').trim().split(' ')) + if (!files && !pipe) common.error('no paths given'); -module.exports = toComparators + var idx = 1; + var plusOption = false; + if (options.numLines === true) { + idx = 2; + if (arguments[1][0] === '+') { + plusOption = true; + } + options.numLines = Number(arguments[1]); + } else if (options.numLines === false) { + options.numLines = 10; + } + // arguments[0] is a json object + if (arguments[0].numLines[0] === '+') { + plusOption = true; + } + options.numLines = -1 * Math.abs(options.numLines); + files = [].slice.call(arguments, idx); + if (pipe) { + files.unshift('-'); + } -/***/ }), + var shouldAppendNewline = false; + files.forEach(function (file) { + if (file !== '-') { + if (!fs.existsSync(file)) { + common.error('no such file or directory: ' + file, { continue: true }); + return; + } else if (common.statFollowLinks(file).isDirectory()) { + common.error("error reading '" + file + "': Is a directory", { + continue: true, + }); + return; + } + } -/***/ 2668: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + var contents = file === '-' ? pipe : fs.readFileSync(file, 'utf8'); -"use strict"; + var lines = contents.split('\n'); + if (lines[lines.length - 1] === '') { + lines.pop(); + shouldAppendNewline = true; + } else { + shouldAppendNewline = false; + } + tail = tail.concat(plusOption ? lines.slice(-options.numLines - 1) : lines.slice(options.numLines)); + }); -const Range = __nccwpck_require__(8037) -const validRange = (range, options) => { - try { - // Return '*' instead of '' so that truthiness works. - // This will throw if it's invalid anyway - return new Range(range, options).range || '*' - } catch (er) { - return null + if (shouldAppendNewline) { + tail.push(''); // to add a trailing newline once we join } + + return tail.join('\n'); } -module.exports = validRange + +module.exports = _tail; /***/ }), -/***/ 3336: +/***/ 1356: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; +var os = __nccwpck_require__(857); +var fs = __nccwpck_require__(9896); +var common = __nccwpck_require__(8400); -const shebangRegex = __nccwpck_require__(8345); +common.register('tempdir', _tempDir, { + allowGlobbing: false, + wrapOutput: false, +}); -module.exports = (string = '') => { - const match = string.match(shebangRegex); +// Returns false if 'dir' is not a writeable directory, 'dir' otherwise +function writeableDir(dir) { + if (!dir || !fs.existsSync(dir)) return false; - if (!match) { - return null; - } + if (!common.statFollowLinks(dir).isDirectory()) return false; - const [path, argument] = match[0].replace(/#! ?/, '').split(' '); - const binary = path.split('/').pop(); + var testFile = dir + '/' + common.randomFileName(); + try { + fs.writeFileSync(testFile, ' '); + common.unlinkSync(testFile); + return dir; + } catch (e) { + /* istanbul ignore next */ + return false; + } +} - if (binary === 'env') { - return argument; - } +// Variable to cache the tempdir value for successive lookups. +var cachedTempDir; - return argument ? `${binary} ${argument}` : binary; -}; +//@ +//@ ### tempdir() +//@ +//@ Examples: +//@ +//@ ```javascript +//@ var tmp = tempdir(); // "/tmp" for most *nix platforms +//@ ``` +//@ +//@ Searches and returns string containing a writeable, platform-dependent temporary directory. +//@ Follows Python's [tempfile algorithm](http://docs.python.org/library/tempfile.html#tempfile.tempdir). +function _tempDir() { + if (cachedTempDir) return cachedTempDir; + cachedTempDir = writeableDir(os.tmpdir()) || + writeableDir(process.env.TMPDIR) || + writeableDir(process.env.TEMP) || + writeableDir(process.env.TMP) || + writeableDir(process.env.Wimp$ScrapDir) || // RiscOS + writeableDir('C:\\TEMP') || // Windows + writeableDir('C:\\TMP') || // Windows + writeableDir('\\TEMP') || // Windows + writeableDir('\\TMP') || // Windows + writeableDir('/tmp') || + writeableDir('/var/tmp') || + writeableDir('/usr/tmp') || + writeableDir('.'); // last resort -/***/ }), + return cachedTempDir; +} -/***/ 8345: -/***/ ((module) => { +// Indicates if the tempdir value is currently cached. This is exposed for tests +// only. The return value should only be tested for truthiness. +function isCached() { + return cachedTempDir; +} -"use strict"; +// Clears the cached tempDir value, if one is cached. This is exposed for tests +// only. +function clearCache() { + cachedTempDir = undefined; +} -module.exports = /^#!(.*)/; +module.exports.tempDir = _tempDir; +module.exports.isCached = isCached; +module.exports.clearCache = clearCache; /***/ }), -/***/ 8007: +/***/ 4565: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -// -// ShellJS -// Unix shell commands on top of Node's API -// -// Copyright (c) 2012 Artur Adib -// http://github.com/shelljs/shelljs -// +var fs = __nccwpck_require__(9896); +var common = __nccwpck_require__(8400); -var common = __nccwpck_require__(3311); +common.register('test', _test, { + cmdOptions: { + 'b': 'block', + 'c': 'character', + 'd': 'directory', + 'e': 'exists', + 'f': 'file', + 'L': 'link', + 'p': 'pipe', + 'S': 'socket', + }, + wrapOutput: false, + allowGlobbing: false, +}); -module.exports = common.shell; //@ -//@ All commands run synchronously, unless otherwise stated. -//@ All commands accept standard bash globbing characters (`*`, `?`, etc.), -//@ compatible with [`fast-glob`](https://www.npmjs.com/package/fast-glob). +//@ ### test(expression) //@ -//@ For less-commonly used commands and features, please check out our [wiki -//@ page](https://github.com/shelljs/shelljs/wiki). +//@ Available expression primaries: //@ - -// Include the docs for all the default commands -//@commands - -// Load all default commands. We import these for their side effect of loading -// using the plugin architecture via `common.register()`. -__nccwpck_require__(904); -__nccwpck_require__(6649); -__nccwpck_require__(3385); -__nccwpck_require__(6836); -__nccwpck_require__(2981); -__nccwpck_require__(4346); -__nccwpck_require__(8191); -__nccwpck_require__(263); -__nccwpck_require__(4884); // A hint to the bundler to keep exec-child.js -__nccwpck_require__(4145); -__nccwpck_require__(686); -__nccwpck_require__(9068); -__nccwpck_require__(9011); -__nccwpck_require__(1275); -__nccwpck_require__(2523); -__nccwpck_require__(4913); -__nccwpck_require__(391); -__nccwpck_require__(500); -__nccwpck_require__(4879); -__nccwpck_require__(5595); -__nccwpck_require__(3548); -__nccwpck_require__(2652); -__nccwpck_require__(289); -__nccwpck_require__(6588); -__nccwpck_require__(1125); -__nccwpck_require__(6682); -__nccwpck_require__(4511); -__nccwpck_require__(230); -__nccwpck_require__(8155); -__nccwpck_require__(2155); -__nccwpck_require__(1721); - +//@ + `'-b', 'path'`: true if path is a block device +//@ + `'-c', 'path'`: true if path is a character device +//@ + `'-d', 'path'`: true if path is a directory +//@ + `'-e', 'path'`: true if path exists +//@ + `'-f', 'path'`: true if path is a regular file +//@ + `'-L', 'path'`: true if path is a symbolic link +//@ + `'-p', 'path'`: true if path is a pipe (FIFO) +//@ + `'-S', 'path'`: true if path is a socket //@ -//@ ### exit(code) +//@ Examples: //@ -//@ Exits the current process with the given exit `code`. -module.exports.exit = function exit(code) { - common.state.error = null; - common.state.errorCode = 0; - if (code) { - common.error('exit', { - continue: true, - code, - prefix: '', - silent: true, - fatal: false, - }); - process.exit(code); - } else { - process.exit(); +//@ ```javascript +//@ if (test('-d', path)) { /* do something with dir */ }; +//@ if (!test('-f', path)) continue; // skip if it's not a regular file +//@ ``` +//@ +//@ Evaluates `expression` using the available primaries and returns +//@ corresponding boolean value. +function _test(options, path) { + if (!path) common.error('no path given'); + + var canInterpret = false; + Object.keys(options).forEach(function (key) { + if (options[key] === true) { + canInterpret = true; + } + }); + + if (!canInterpret) common.error('could not interpret expression'); + + if (options.link) { + try { + return common.statNoFollowLinks(path).isSymbolicLink(); + } catch (e) { + return false; + } } -}; -//@include ./src/error.js -module.exports.error = __nccwpck_require__(6190); + if (!fs.existsSync(path)) return false; -//@include ./src/errorCode.js -module.exports.errorCode = __nccwpck_require__(5163); + if (options.exists) return true; -//@include ./src/common.js -module.exports.ShellString = common.ShellString; + var stats = common.statFollowLinks(path); -//@ -//@ ### env['VAR_NAME'] -//@ -//@ Object containing environment variables (both getter and setter). Shortcut -//@ to `process.env`. -module.exports.env = process.env; + if (options.block) return stats.isBlockDevice(); + + if (options.character) return stats.isCharacterDevice(); + + if (options.directory) return stats.isDirectory(); + + if (options.file) return stats.isFile(); + + /* istanbul ignore next */ + if (options.pipe) return stats.isFIFO(); + + /* istanbul ignore next */ + if (options.socket) return stats.isSocket(); + + /* istanbul ignore next */ + return false; // fallback +} // test +module.exports = _test; + + +/***/ }), + +/***/ 7196: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var fs = __nccwpck_require__(9896); +var path = __nccwpck_require__(6928); +var common = __nccwpck_require__(8400); + +common.register('to', _to, { + pipeOnly: true, + wrapOutput: false, +}); //@ -//@ ### Pipes +//@ ### ShellString.prototype.to(file) //@ //@ Examples: //@ //@ ```javascript -//@ grep('foo', 'file1.txt', 'file2.txt').sed(/o/g, 'a').to('output.txt'); -//@ echo("files with o's in the name:\n" + ls().grep('o')); -//@ cat('test.js').exec('node'); // pipe to exec() call +//@ cat('input.txt').to('output.txt'); //@ ``` //@ -//@ Commands can send their output to another command in a pipe-like fashion. -//@ `sed`, `grep`, `cat`, `exec`, `to`, and `toEnd` can appear on the right-hand -//@ side of a pipe. Pipes can be chained. +//@ Analogous to the redirection operator `>` in Unix, but works with +//@ `ShellStrings` (such as those returned by `cat`, `grep`, etc.). _Like Unix +//@ redirections, `to()` will overwrite any existing file!_ Returns the same +//@ [ShellString](#shellstringstr) this operated on, to support chaining. +function _to(options, file) { + if (!file) common.error('wrong arguments'); -//@ -//@ ## Configuration -//@ + if (!fs.existsSync(path.dirname(file))) { + common.error('no such file or directory: ' + path.dirname(file)); + } -module.exports.config = common.config; + try { + fs.writeFileSync(file, this.stdout || this.toString(), 'utf8'); + return this; + } catch (e) { + /* istanbul ignore next */ + common.error('could not write to file (code ' + e.code + '): ' + file, { continue: true }); + } +} +module.exports = _to; -//@ -//@ ### config.silent -//@ -//@ Example: -//@ -//@ ```javascript -//@ var sh = require('shelljs'); -//@ var silentState = sh.config.silent; // save old silent state -//@ sh.config.silent = true; -//@ /* ... */ -//@ sh.config.silent = silentState; // restore old silent state -//@ ``` -//@ -//@ Suppresses all command output if `true`, except for `echo()` calls. -//@ Default is `false`. -//@ -//@ ### config.fatal -//@ -//@ Example: -//@ -//@ ```javascript -//@ require('shelljs/global'); -//@ config.fatal = true; // or set('-e'); -//@ cp('this_file_does_not_exist', '/dev/null'); // throws Error here -//@ /* more commands... */ -//@ ``` -//@ -//@ If `true`, the script will throw a Javascript error when any shell.js -//@ command encounters an error. Default is `false`. This is analogous to -//@ Bash's `set -e`. +/***/ }), -//@ -//@ ### config.verbose -//@ -//@ Example: -//@ -//@ ```javascript -//@ config.verbose = true; // or set('-v'); -//@ cd('dir/'); -//@ rm('-rf', 'foo.txt', 'bar.txt'); -//@ exec('echo hello'); -//@ ``` -//@ -//@ Will print each command as follows: -//@ -//@ ``` -//@ cd dir/ -//@ rm -rf foo.txt bar.txt -//@ exec echo hello -//@ ``` +/***/ 6867: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -//@ -//@ ### config.globOptions (deprecated) -//@ -//@ **Deprecated**: we recommend that you do not edit `config.globOptions`. -//@ Support for this configuration option may be changed or removed in a future -//@ ShellJS release. -//@ -//@ **Breaking change**: ShellJS v0.8.x uses `node-glob`. Starting with ShellJS -//@ v0.9.x, `config.globOptions` is compatible with `fast-glob`. -//@ -//@ Example: -//@ -//@ ```javascript -//@ config.globOptions = {nodir: true}; -//@ ``` -//@ -//@ `config.globOptions` changes how ShellJS expands glob (wildcard) -//@ expressions. See -//@ [fast-glob](https://github.com/mrmlnc/fast-glob?tab=readme-ov-file#options-3) -//@ for available options. Be aware that modifying `config.globOptions` **may -//@ break ShellJS functionality.** +var fs = __nccwpck_require__(9896); +var path = __nccwpck_require__(6928); +var common = __nccwpck_require__(8400); + +common.register('toEnd', _toEnd, { + pipeOnly: true, + wrapOutput: false, +}); //@ -//@ ### config.reset() +//@ ### ShellString.prototype.toEnd(file) //@ -//@ Example: +//@ Examples: //@ //@ ```javascript -//@ var shell = require('shelljs'); -//@ // Make changes to shell.config, and do stuff... -//@ /* ... */ -//@ shell.config.reset(); // reset to original state -//@ // Do more stuff, but with original settings -//@ /* ... */ +//@ cat('input.txt').toEnd('output.txt'); //@ ``` //@ -//@ Reset `shell.config` to the defaults: -//@ -//@ ```javascript -//@ { -//@ fatal: false, -//@ globOptions: {}, -//@ maxdepth: 255, -//@ noglob: false, -//@ silent: false, -//@ verbose: false, -//@ } -//@ ``` +//@ Analogous to the redirect-and-append operator `>>` in Unix, but works with +//@ `ShellStrings` (such as those returned by `cat`, `grep`, etc.). Returns the +//@ same [ShellString](#shellstringstr) this operated on, to support chaining. +function _toEnd(options, file) { + if (!file) common.error('wrong arguments'); + + if (!fs.existsSync(path.dirname(file))) { + common.error('no such file or directory: ' + path.dirname(file)); + } + + try { + fs.appendFileSync(file, this.stdout || this.toString(), 'utf8'); + return this; + } catch (e) { + /* istanbul ignore next */ + common.error('could not append to file (code ' + e.code + '): ' + file, { continue: true }); + } +} +module.exports = _toEnd; /***/ }), -/***/ 904: +/***/ 9646: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { var fs = __nccwpck_require__(9896); -var common = __nccwpck_require__(3311); +var common = __nccwpck_require__(8400); -common.register('cat', _cat, { - canReceivePipe: true, +common.register('touch', _touch, { cmdOptions: { - 'n': 'number', + 'a': 'atime_only', + 'c': 'no_create', + 'd': 'date', + 'm': 'mtime_only', + 'r': 'reference', }, }); //@ -//@ ### cat([options,] file [, file ...]) -//@ ### cat([options,] file_array) +//@ ### touch([options,] file [, file ...]) +//@ ### touch([options,] file_array) //@ //@ Available options: //@ -//@ + `-n`: number all output lines +//@ + `-a`: Change only the access time +//@ + `-c`: Do not create any files +//@ + `-m`: Change only the modification time +//@ + `{'-d': someDate}`, `{date: someDate}`: Use a `Date` instance (ex. `someDate`) +//@ instead of current time +//@ + `{'-r': file}`, `{reference: file}`: Use `file`'s times instead of current +//@ time //@ //@ Examples: //@ //@ ```javascript -//@ var str = cat('file*.txt'); -//@ var str = cat('file1', 'file2'); -//@ var str = cat(['file1', 'file2']); // same as above +//@ touch('source.js'); +//@ touch('-c', 'path/to/file.js'); +//@ touch({ '-r': 'referenceFile.txt' }, 'path/to/file.js'); +//@ touch({ '-d': new Date('December 17, 1995 03:24:00'), '-m': true }, 'path/to/file.js'); +//@ touch({ date: new Date('December 17, 1995 03:24:00') }, 'path/to/file.js'); //@ ``` //@ -//@ Returns a [ShellString](#shellstringstr) containing the given file, or a -//@ concatenated string containing the files if more than one file is given (a -//@ new line character is introduced between each file). -function _cat(options, files) { - var cat = common.readFromPipe(); - - if (!files && !cat) common.error('no paths given'); - - files = [].slice.call(arguments, 1); - - files.forEach(function (file) { - if (!fs.existsSync(file)) { - common.error('no such file or directory: ' + file); - } else if (common.statFollowLinks(file).isDirectory()) { - common.error(file + ': Is a directory'); - } - - cat += fs.readFileSync(file, 'utf8'); - }); - - if (options.number) { - cat = addNumbers(cat); +//@ Update the access and modification times of each file to the current time. +//@ A file argument that does not exist is created empty, unless `-c` is supplied. +//@ This is a partial implementation of +//@ [`touch(1)`](http://linux.die.net/man/1/touch). Returns a +//@ [ShellString](#shellstringstr) indicating success or failure. +function _touch(opts, files) { + if (!files) { + common.error('no files given'); + } else if (typeof files === 'string') { + files = [].slice.call(arguments, 1); + } else { + common.error('file arg should be a string file path or an Array of string file paths'); } - return cat; + files.forEach(function (f) { + touchFile(opts, f); + }); + return ''; } -module.exports = _cat; - -function addNumbers(cat) { - var lines = cat.split('\n'); - var lastLine = lines.pop(); - lines = lines.map(function (line, i) { - return numberedLine(i + 1, line); - }); +function touchFile(opts, file) { + var stat = tryStatFile(file); - if (lastLine.length) { - lastLine = numberedLine(lines.length + 1, lastLine); + if (stat && stat.isDirectory()) { + // don't error just exit + return; } - lines.push(lastLine); - - return lines.join('\n'); -} -function numberedLine(n, line) { - // GNU cat use six pad start number + tab. See http://lingrok.org/xref/coreutils/src/cat.c#57 - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart - var number = (' ' + n).slice(-6) + '\t'; - return number + line; -} + // if the file doesn't already exist and the user has specified --no-create then + // this script is finished + if (!stat && opts.no_create) { + return; + } + // open the file and then close it. this will create it if it doesn't exist but will + // not truncate the file + fs.closeSync(fs.openSync(file, 'a')); -/***/ }), + // + // Set timestamps + // -/***/ 6649: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // setup some defaults + var now = new Date(); + var mtime = opts.date || now; + var atime = opts.date || now; -var os = __nccwpck_require__(857); -var common = __nccwpck_require__(3311); + // use reference file + if (opts.reference) { + var refStat = tryStatFile(opts.reference); + if (!refStat) { + common.error('failed to get attributess of ' + opts.reference); + } + mtime = refStat.mtime; + atime = refStat.atime; + } else if (opts.date) { + mtime = opts.date; + atime = opts.date; + } -common.register('cd', _cd, {}); + if (opts.atime_only && opts.mtime_only) { + // keep the new values of mtime and atime like GNU + } else if (opts.atime_only) { + mtime = stat.mtime; + } else if (opts.mtime_only) { + atime = stat.atime; + } -//@ -//@ ### cd([dir]) -//@ -//@ Changes to directory `dir` for the duration of the script. Changes to home -//@ directory if no argument is supplied. Returns a -//@ [ShellString](#shellstringstr) to indicate success or failure. -function _cd(options, dir) { - if (!dir) dir = os.homedir(); + fs.utimesSync(file, atime, mtime); +} - if (dir === '-') { - if (!process.env.OLDPWD) { - common.error('could not find previous directory'); - } else { - dir = process.env.OLDPWD; - } - } +module.exports = _touch; +function tryStatFile(filePath) { try { - var curDir = process.cwd(); - process.chdir(dir); - process.env.OLDPWD = curDir; + return common.statFollowLinks(filePath); } catch (e) { - // something went wrong, let's figure out the error - var err; - try { - common.statFollowLinks(dir); // if this succeeds, it must be some sort of file - err = 'not a directory: ' + dir; - } catch (e2) { - err = 'no such file or directory: ' + dir; - } - if (err) common.error(err); + return null; } - return ''; } -module.exports = _cd; /***/ }), -/***/ 3385: +/***/ 8568: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { var fs = __nccwpck_require__(9896); -var path = __nccwpck_require__(6928); -var common = __nccwpck_require__(3311); - -var PERMS = (function (base) { - return { - OTHER_EXEC: base.EXEC, - OTHER_WRITE: base.WRITE, - OTHER_READ: base.READ, - - GROUP_EXEC: base.EXEC << 3, - GROUP_WRITE: base.WRITE << 3, - GROUP_READ: base.READ << 3, +var common = __nccwpck_require__(8400); - OWNER_EXEC: base.EXEC << 6, - OWNER_WRITE: base.WRITE << 6, - OWNER_READ: base.READ << 6, - - // Literal octal numbers are apparently not allowed in "strict" javascript. - STICKY: parseInt('01000', 8), - SETGID: parseInt('02000', 8), - SETUID: parseInt('04000', 8), - - TYPE_MASK: parseInt('0770000', 8), - }; -}({ - EXEC: 1, - WRITE: 2, - READ: 4, -})); +// add c spaces to the left of str +function lpad(c, str) { + var res = '' + str; + if (res.length < c) { + res = Array((c - res.length) + 1).join(' ') + res; + } + return res; +} -common.register('chmod', _chmod, { +common.register('uniq', _uniq, { + canReceivePipe: true, + cmdOptions: { + 'i': 'ignoreCase', + 'c': 'count', + 'd': 'duplicates', + }, }); //@ -//@ ### chmod([options,] octal_mode || octal_string, file) -//@ ### chmod([options,] symbolic_mode, file) +//@ ### uniq([options,] [input, [output]]) //@ //@ Available options: //@ -//@ + `-v`: output a diagnostic for every file processed//@ -//@ + `-c`: like verbose, but report only when a change is made//@ -//@ + `-R`: change files and directories recursively//@ +//@ + `-i`: Ignore case while comparing +//@ + `-c`: Prefix lines by the number of occurrences +//@ + `-d`: Only print duplicate lines, one for each group of identical lines //@ //@ Examples: //@ //@ ```javascript -//@ chmod(755, '/Users/brandon'); -//@ chmod('755', '/Users/brandon'); // same as above -//@ chmod('u+x', '/Users/brandon'); -//@ chmod('-R', 'a-w', '/Users/brandon'); +//@ uniq('foo.txt'); +//@ uniq('-i', 'foo.txt'); +//@ uniq('-cd', 'foo.txt', 'bar.txt'); //@ ``` //@ -//@ Alters the permissions of a file or directory by either specifying the -//@ absolute permissions in octal form or expressing the changes in symbols. -//@ This command tries to mimic the POSIX behavior as much as possible. -//@ Notable exceptions: -//@ -//@ + In symbolic modes, `a-r` and `-r` are identical. No consideration is -//@ given to the `umask`. -//@ + There is no "quiet" option, since default behavior is to run silent. -//@ + Windows OS uses a very different permission model than POSIX. `chmod()` -//@ does its best on Windows, but there are limits to how file permissions can -//@ be set. Note that WSL (Windows subsystem for Linux) **does** follow POSIX, -//@ so cross-platform compatibility should not be a concern there. -//@ -//@ Returns a [ShellString](#shellstringstr) indicating success or failure. -function _chmod(options, mode, filePattern) { - if (!filePattern) { - if (options.length > 0 && options.charAt(0) === '-') { - // Special case where the specified file permissions started with - to subtract perms, which - // get picked up by the option parser as command flags. - // If we are down by one argument and options starts with -, shift everything over. - [].unshift.call(arguments, ''); - } else { - common.error('You must specify a file.'); +//@ Filter adjacent matching lines from `input`. Returns a +//@ [ShellString](#shellstringstr). +function _uniq(options, input, output) { + // Check if this is coming from a pipe + var pipe = common.readFromPipe(); + + if (!pipe) { + if (!input) common.error('no input given'); + + if (!fs.existsSync(input)) { + common.error(input + ': No such file or directory'); + } else if (common.statFollowLinks(input).isDirectory()) { + common.error("error reading '" + input + "'"); } } + if (output && fs.existsSync(output) && common.statFollowLinks(output).isDirectory()) { + common.error(output + ': Is a directory'); + } - options = common.parseOptions(options, { - 'R': 'recursive', - 'c': 'changes', - 'v': 'verbose', - }); + var lines = (input ? fs.readFileSync(input, 'utf8') : pipe) + .trimRight() + .split('\n'); - filePattern = [].slice.call(arguments, 2); - - var files; - - // TODO: replace this with a call to common.expand() - if (options.recursive) { - files = []; - filePattern.forEach(function addFile(expandedFile) { - var stat = common.statNoFollowLinks(expandedFile); - - if (!stat.isSymbolicLink()) { - files.push(expandedFile); + var compare = function (a, b) { + return options.ignoreCase ? + a.toLocaleLowerCase().localeCompare(b.toLocaleLowerCase()) : + a.localeCompare(b); + }; + var uniqed = lines.reduceRight(function (res, e) { + // Perform uniq -c on the input + if (res.length === 0) { + return [{ count: 1, ln: e }]; + } else if (compare(res[0].ln, e) === 0) { + return [{ count: res[0].count + 1, ln: e }].concat(res.slice(1)); + } else { + return [{ count: 1, ln: e }].concat(res); + } + }, []).filter(function (obj) { + // Do we want only duplicated objects? + return options.duplicates ? obj.count > 1 : true; + }).map(function (obj) { + // Are we tracking the counts of each line? + return (options.count ? (lpad(7, obj.count) + ' ') : '') + obj.ln; + }).join('\n') + '\n'; - if (stat.isDirectory()) { // intentionally does not follow symlinks. - fs.readdirSync(expandedFile).forEach(function (child) { - addFile(expandedFile + '/' + child); - }); - } - } - }); + if (output) { + (new common.ShellString(uniqed)).to(output); + // if uniq writes to output, nothing is passed to the next command in the pipeline (if any) + return ''; } else { - files = filePattern; + return uniqed; } +} - files.forEach(function innerChmod(file) { - file = path.resolve(file); - if (!fs.existsSync(file)) { - common.error('File not found: ' + file); - } - - // When recursing, don't follow symlinks. - if (options.recursive && common.statNoFollowLinks(file).isSymbolicLink()) { - return; - } - - var stat = common.statFollowLinks(file); - var isDir = stat.isDirectory(); - var perms = stat.mode; - var type = perms & PERMS.TYPE_MASK; - - var newPerms = perms; - - if (Number.isNaN(parseInt(mode, 8))) { - // parse options - mode.split(',').forEach(function (symbolicMode) { - var pattern = /([ugoa]*)([=+-])([rwxXst]*)/i; - var matches = pattern.exec(symbolicMode); - - if (matches) { - var applyTo = matches[1]; - var operator = matches[2]; - var change = matches[3]; - - var changeOwner = applyTo.includes('u') || applyTo === 'a' || applyTo === ''; - var changeGroup = applyTo.includes('g') || applyTo === 'a' || applyTo === ''; - var changeOther = applyTo.includes('o') || applyTo === 'a' || applyTo === ''; - - var changeRead = change.includes('r'); - var changeWrite = change.includes('w'); - var changeExec = change.includes('x'); - var changeExecDir = change.includes('X'); - var changeSticky = change.includes('t'); - var changeSetuid = change.includes('s'); - - if (changeExecDir && isDir) { - changeExec = true; - } - - var mask = 0; - if (changeOwner) { - mask |= (changeRead ? PERMS.OWNER_READ : 0) + (changeWrite ? PERMS.OWNER_WRITE : 0) + (changeExec ? PERMS.OWNER_EXEC : 0) + (changeSetuid ? PERMS.SETUID : 0); - } - if (changeGroup) { - mask |= (changeRead ? PERMS.GROUP_READ : 0) + (changeWrite ? PERMS.GROUP_WRITE : 0) + (changeExec ? PERMS.GROUP_EXEC : 0) + (changeSetuid ? PERMS.SETGID : 0); - } - if (changeOther) { - mask |= (changeRead ? PERMS.OTHER_READ : 0) + (changeWrite ? PERMS.OTHER_WRITE : 0) + (changeExec ? PERMS.OTHER_EXEC : 0); - } - - // Sticky bit is special - it's not tied to user, group or other. - if (changeSticky) { - mask |= PERMS.STICKY; - } +module.exports = _uniq; - switch (operator) { - case '+': - newPerms |= mask; - break; - case '-': - newPerms &= ~mask; - break; +/***/ }), - case '=': - newPerms = type + mask; +/***/ 9500: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - // According to POSIX, when using = to explicitly set the - // permissions, setuid and setgid can never be cleared. - if (common.statFollowLinks(file).isDirectory()) { - newPerms |= (PERMS.SETUID + PERMS.SETGID) & perms; - } - break; - default: - common.error('Could not recognize operator: `' + operator + '`'); - } +var fs = __nccwpck_require__(9896); +var path = __nccwpck_require__(6928); +var common = __nccwpck_require__(8400); - if (options.verbose) { - console.log(file + ' -> ' + newPerms.toString(8)); - } +common.register('which', _which, { + allowGlobbing: false, + cmdOptions: { + 'a': 'all', + }, +}); - if (perms !== newPerms) { - if (!options.verbose && options.changes) { - console.log(file + ' -> ' + newPerms.toString(8)); - } - fs.chmodSync(file, newPerms); - perms = newPerms; // for the next round of changes! - } - } else { - common.error('Invalid symbolic mode change: ' + symbolicMode); - } - }); - } else { - // they gave us a full number - newPerms = type + parseInt(mode, 8); +// XP's system default value for `PATHEXT` system variable, just in case it's not +// set on Windows. +var XP_DEFAULT_PATHEXT = '.com;.exe;.bat;.cmd;.vbs;.vbe;.js;.jse;.wsf;.wsh'; - // POSIX rules are that setuid and setgid can only be added using numeric - // form, but not cleared. - if (common.statFollowLinks(file).isDirectory()) { - newPerms |= (PERMS.SETUID + PERMS.SETGID) & perms; - } +// For earlier versions of NodeJS that doesn't have a list of constants (< v6) +var FILE_EXECUTABLE_MODE = 1; - fs.chmodSync(file, newPerms); - } - }); - return ''; +function isWindowsPlatform() { + return process.platform === 'win32'; } -module.exports = _chmod; - - -/***/ }), - -/***/ 6836: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -var execa = __nccwpck_require__(1677); -var common = __nccwpck_require__(3311); - -var DEFAULT_MAXBUFFER_SIZE = 20 * 1024 * 1024; -var COMMAND_NOT_FOUND_ERROR_CODE = 127; -common.register('cmd', _cmd, { - cmdOptions: null, - globStart: 1, - canReceivePipe: true, - wrapOutput: true, -}); +// Cross-platform method for splitting environment `PATH` variables +function splitPath(p) { + return p ? p.split(path.delimiter) : []; +} -function isCommandNotFound(execaResult) { - if (process.platform === 'win32') { - var str = 'is not recognized as an internal or external command'; - return execaResult.exitCode && execaResult.stderr.includes(str); +// Tests are running all cases for this func but it stays uncovered by codecov due to unknown reason +/* istanbul ignore next */ +function isExecutable(pathName) { + try { + // TODO(node-support): replace with fs.constants.X_OK once remove support for node < v6 + fs.accessSync(pathName, FILE_EXECUTABLE_MODE); + } catch (err) { + return false; } - return execaResult.failed && execaResult.code === 'ENOENT'; + return true; } -function isExecaInternalError(result) { - if (typeof result.stdout !== 'string') return true; - if (typeof result.stderr !== 'string') return true; - if (typeof result.exitCode !== 'number') return true; - if (result.exitCode === 0 && result.failed) return true; - // Otherwise assume this executed correctly. The command may still have exited - // with non-zero status, but that's not due to anything execa did. - return false; +function checkPath(pathName) { + return fs.existsSync(pathName) && !common.statFollowLinks(pathName).isDirectory() + && (isWindowsPlatform() || isExecutable(pathName)); } //@ -//@ ### cmd(arg1[, arg2, ...] [, options]) -//@ -//@ Available options: -//@ -//@ + `cwd: directoryPath`: change the current working directory only for this -//@ cmd() invocation. -//@ + `maxBuffer: num`: Raise or decrease the default buffer size for -//@ stdout/stderr. -//@ + `timeout`: Change the default timeout. +//@ ### which(command) //@ //@ Examples: //@ //@ ```javascript -//@ var version = cmd('node', '--version').stdout; -//@ cmd('git', 'commit', '-am', `Add suport for node ${version}`); -//@ console.log(cmd('echo', '1st arg', '2nd arg', '3rd arg').stdout) -//@ console.log(cmd('echo', 'this handles ;, |, &, etc. as literal characters').stdout) +//@ var nodeExec = which('node'); //@ ``` //@ -//@ Executes the given command synchronously. This is intended as an easier -//@ alternative for [exec()](#execcommand--options--callback), with better -//@ security around globbing, comamnd injection, and variable expansion. This is -//@ guaranteed to only run one external command, and won't give special -//@ treatment for any shell characters (ex. this treats `|` as a literal -//@ character, not as a shell pipeline). -//@ This returns a [ShellString](#shellstringstr). -//@ -//@ By default, this performs globbing on all platforms, but you can disable -//@ this with `set('-f')`. -//@ -//@ This **does not** support asynchronous mode. If you need asynchronous -//@ command execution, check out [execa](https://www.npmjs.com/package/execa) or -//@ the node builtin `child_process.execFile()` instead. -function _cmd(options, command, commandArgs, userOptions) { - if (!command) { - common.error('Must specify a non-empty string as a command'); - } +//@ Searches for `command` in the system's `PATH`. On Windows, this uses the +//@ `PATHEXT` variable to append the extension if it's not already executable. +//@ Returns a [ShellString](#shellstringstr) containing the absolute path to +//@ `command`. +function _which(options, cmd) { + if (!cmd) common.error('must specify command'); - // `options` will usually not have a value: it's added by our commandline flag - // parsing engine. - commandArgs = [].slice.call(arguments, 2); + var isWindows = isWindowsPlatform(); + var pathArray = splitPath(process.env.PATH); - // `userOptions` may or may not be provided. We need to check the last - // argument. If it's an object, assume it's meant to be passed as - // userOptions (since ShellStrings are already flattened to strings). - if (commandArgs.length === 0) { - userOptions = {}; - } else { - var lastArg = commandArgs.pop(); - if (common.isObject(lastArg)) { - userOptions = lastArg; - } else { - userOptions = {}; - commandArgs.push(lastArg); - } - } + var queryMatches = []; - var pipe = common.readFromPipe(); + // No relative/absolute paths provided? + if (!cmd.includes('/')) { + // Assume that there are no extensions to append to queries (this is the + // case for unix) + var pathExtArray = ['']; + if (isWindows) { + // In case the PATHEXT variable is somehow not set (e.g. + // child_process.spawn with an empty environment), use the XP default. + var pathExtEnv = process.env.PATHEXT || XP_DEFAULT_PATHEXT; + pathExtArray = splitPath(pathExtEnv.toUpperCase()); + } - // Some of our defaults differ from execa's defaults. These can be overridden - // by the user. - var defaultOptions = { - maxBuffer: DEFAULT_MAXBUFFER_SIZE, - stripFinalNewline: false, // Preserve trailing newlines for consistency with unix. - reject: false, // Use ShellJS's error handling system. - }; + // Search for command in PATH + for (var k = 0; k < pathArray.length; k++) { + // already found it + if (queryMatches.length > 0 && !options.all) break; - // For other options, we forbid the user from overriding them (either for - // correctness or security). - var requiredOptions = { - input: pipe, - shell: false, - }; + var attempt = path.resolve(pathArray[k], cmd); - var execaOptions = - Object.assign(defaultOptions, userOptions, requiredOptions); + if (isWindows) { + attempt = attempt.toUpperCase(); + } - var result = execa.sync(command, commandArgs, execaOptions); - var stdout; - var stderr; - var code; - if (isCommandNotFound(result)) { - // This can happen if `command` is not an executable binary, or possibly - // under other conditions. - stdout = ''; - stderr = "'" + command + "': command not found"; - code = COMMAND_NOT_FOUND_ERROR_CODE; - } else if (isExecaInternalError(result)) { - // Catch-all: execa tried to run `command` but it encountered some error - // (ex. maxBuffer, timeout). - stdout = result.stdout || ''; - stderr = result.stderr || - `'${command}' encountered an error during execution`; - code = result.exitCode !== undefined && result.exitCode > 0 ? result.exitCode : 1; - } else { - // Normal exit: execa was able to execute `command` and get a return value. - stdout = result.stdout.toString(); - stderr = result.stderr.toString(); - code = result.exitCode; + var match = attempt.match(/\.[^<>:"/|?*.]+$/); + if (match && pathExtArray.includes(match[0])) { // this is Windows-only + // The user typed a query with the file extension, like + // `which('node.exe')` + if (checkPath(attempt)) { + queryMatches.push(attempt); + break; + } + } else { // All-platforms + // Cycle through the PATHEXT array, and check each extension + // Note: the array is always [''] on Unix + for (var i = 0; i < pathExtArray.length; i++) { + var ext = pathExtArray[i]; + var newAttempt = attempt + ext; + if (checkPath(newAttempt)) { + queryMatches.push(newAttempt); + break; + } + } + } + } + } else if (checkPath(cmd)) { // a valid absolute or relative path + queryMatches.push(path.resolve(cmd)); } - // Pass `continue: true` so we can specify a value for stdout. - if (code) common.error(stderr, code, { silent: true, continue: true }); - return new common.ShellString(stdout, stderr, code); + if (queryMatches.length > 0) { + return options.all ? queryMatches : queryMatches[0]; + } + return options.all ? [] : null; } -module.exports = _cmd; +module.exports = _which; /***/ }), -/***/ 3311: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; -// Ignore warning about 'new String()' and use of the Buffer constructor -/* eslint no-new-wrappers: "off", - no-buffer-constructor: "off" */ +/***/ 2638: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +// Note: since nyc uses this module to output coverage, any lines +// that are in the direct sync flow of nyc's outputCoverage are +// ignored, since we can never get coverage for them. +// grab a reference to node's real process object right away +var process = global.process +const processOk = function (process) { + return process && + typeof process === 'object' && + typeof process.removeListener === 'function' && + typeof process.emit === 'function' && + typeof process.reallyExit === 'function' && + typeof process.listeners === 'function' && + typeof process.kill === 'function' && + typeof process.pid === 'number' && + typeof process.on === 'function' +} -var os = __nccwpck_require__(857); -var fs = __nccwpck_require__(9896); -var glob = __nccwpck_require__(7469); +// some kind of non-node environment, just no-op +/* istanbul ignore if */ +if (!processOk(process)) { + module.exports = function () { + return function () {} + } +} else { + var assert = __nccwpck_require__(2613) + var signals = __nccwpck_require__(1819) + var isWin = /^win/i.test(process.platform) -var shell = {}; -exports.shell = shell; + var EE = __nccwpck_require__(4434) + /* istanbul ignore if */ + if (typeof EE !== 'function') { + EE = EE.EventEmitter + } -var shellMethods = Object.create(shell); + var emitter + if (process.__signal_exit_emitter__) { + emitter = process.__signal_exit_emitter__ + } else { + emitter = process.__signal_exit_emitter__ = new EE() + emitter.count = 0 + emitter.emitted = {} + } -exports.extend = Object.assign; + // Because this emitter is a global, we have to check to see if a + // previous version of this library failed to enable infinite listeners. + // I know what you're about to say. But literally everything about + // signal-exit is a compromise with evil. Get used to it. + if (!emitter.infinite) { + emitter.setMaxListeners(Infinity) + emitter.infinite = true + } -// Check if we're running under electron -var isElectron = Boolean(process.versions.electron); + module.exports = function (cb, opts) { + /* istanbul ignore if */ + if (!processOk(global.process)) { + return function () {} + } + assert.equal(typeof cb, 'function', 'a callback must be provided for exit handler') -// Module globals (assume no execPath by default) -var DEFAULT_CONFIG = { - fatal: false, - globOptions: {}, - maxdepth: 255, - noglob: false, - silent: false, - verbose: false, - execPath: null, - bufLength: 64 * 1024, // 64KB -}; + if (loaded === false) { + load() + } -var config = { - reset() { - Object.assign(this, DEFAULT_CONFIG); - if (!isElectron) { - this.execPath = process.execPath; + var ev = 'exit' + if (opts && opts.alwaysLast) { + ev = 'afterexit' } - }, - resetForTesting() { - this.reset(); - this.silent = true; - }, -}; -config.reset(); -exports.config = config; + var remove = function () { + emitter.removeListener(ev, cb) + if (emitter.listeners('exit').length === 0 && + emitter.listeners('afterexit').length === 0) { + unload() + } + } + emitter.on(ev, cb) -// Note: commands should generally consider these as read-only values. -var state = { - error: null, - errorCode: 0, - currentCmd: 'shell.js', -}; -exports.state = state; + return remove + } -delete process.env.OLDPWD; // initially, there's no previous directory + var unload = function unload () { + if (!loaded || !processOk(global.process)) { + return + } + loaded = false -// Reliably test if something is any sort of javascript object -function isObject(a) { - return typeof a === 'object' && a !== null; -} -exports.isObject = isObject; + signals.forEach(function (sig) { + try { + process.removeListener(sig, sigListeners[sig]) + } catch (er) {} + }) + process.emit = originalProcessEmit + process.reallyExit = originalProcessReallyExit + emitter.count -= 1 + } + module.exports.unload = unload -function log() { - /* istanbul ignore next */ - if (!config.silent) { - console.error.apply(console, arguments); + var emit = function emit (event, code, signal) { + /* istanbul ignore if */ + if (emitter.emitted[event]) { + return + } + emitter.emitted[event] = true + emitter.emit(event, code, signal) } -} -exports.log = log; -// Converts strings to be equivalent across all platforms. Primarily responsible -// for making sure we use '/' instead of '\' as path separators, but this may be -// expanded in the future if necessary -function convertErrorOutput(msg) { - if (typeof msg !== 'string') { - throw new TypeError('input must be a string'); - } - return msg.replace(/\\/g, '/'); -} -exports.convertErrorOutput = convertErrorOutput; + // { : , ... } + var sigListeners = {} + signals.forEach(function (sig) { + sigListeners[sig] = function listener () { + /* istanbul ignore if */ + if (!processOk(global.process)) { + return + } + // If there are no other listeners, an exit is coming! + // Simplest way: remove us and then re-send the signal. + // We know that this will kill the process, so we can + // safely emit now. + var listeners = process.listeners(sig) + if (listeners.length === emitter.count) { + unload() + emit('exit', null, sig) + /* istanbul ignore next */ + emit('afterexit', null, sig) + /* istanbul ignore next */ + if (isWin && sig === 'SIGHUP') { + // "SIGHUP" throws an `ENOSYS` error on Windows, + // so use a supported signal instead + sig = 'SIGINT' + } + /* istanbul ignore next */ + process.kill(process.pid, sig) + } + } + }) -// An exception class to help propagate command errors (e.g., non-zero exit -// status) up to the top-level. {@param value} should be a ShellString. -class CommandError extends Error { - constructor(value) { - super(value.toString()); - this.returnValue = value; + module.exports.signals = function () { + return signals } -} -exports.CommandError = CommandError; // visible for testing -// Shows error message. Throws if fatal is true (defaults to config.fatal, overridable with options.fatal) -function error(msg, _code, options) { - // Validate input - if (typeof msg !== 'string') throw new Error('msg must be a string'); + var loaded = false - var DEFAULT_OPTIONS = { - continue: false, - code: 1, - prefix: state.currentCmd + ': ', - silent: false, - fatal: config.fatal, - }; + var load = function load () { + if (loaded || !processOk(global.process)) { + return + } + loaded = true - if (typeof _code === 'number' && isObject(options)) { - options.code = _code; - } else if (isObject(_code)) { // no 'code' - options = _code; - } else if (typeof _code === 'number') { // no 'options' - options = { code: _code }; - } else if (typeof _code !== 'number') { // only 'msg' - options = {}; - } - options = Object.assign({}, DEFAULT_OPTIONS, options); + // This is the number of onSignalExit's that are in play. + // It's important so that we can count the correct number of + // listeners on signals, and don't wait for the other one to + // handle it instead of us. + emitter.count += 1 - if (!state.errorCode) state.errorCode = options.code; + signals = signals.filter(function (sig) { + try { + process.on(sig, sigListeners[sig]) + return true + } catch (er) { + return false + } + }) - var logEntry = convertErrorOutput(options.prefix + msg); - state.error = state.error ? state.error + '\n' : ''; - state.error += logEntry; + process.emit = processEmit + process.reallyExit = processReallyExit + } + module.exports.load = load - // Throw an error, or log the entry - if (options.fatal) { - var err = new Error(logEntry); - err.code = options.code; - throw err; + var originalProcessReallyExit = process.reallyExit + var processReallyExit = function processReallyExit (code) { + /* istanbul ignore if */ + if (!processOk(global.process)) { + return + } + process.exitCode = code || /* istanbul ignore next */ 0 + emit('exit', process.exitCode, null) + /* istanbul ignore next */ + emit('afterexit', process.exitCode, null) + /* istanbul ignore next */ + originalProcessReallyExit.call(process, process.exitCode) } - if (msg.length > 0 && !options.silent) log(logEntry); - if (!options.continue) { - throw new CommandError(new ShellString('', state.error, state.errorCode)); + var originalProcessEmit = process.emit + var processEmit = function processEmit (ev, arg) { + if (ev === 'exit' && processOk(global.process)) { + /* istanbul ignore else */ + if (arg !== undefined) { + process.exitCode = arg + } + var ret = originalProcessEmit.apply(this, arguments) + /* istanbul ignore next */ + emit('exit', process.exitCode, null) + /* istanbul ignore next */ + emit('afterexit', process.exitCode, null) + /* istanbul ignore next */ + return ret + } else { + return originalProcessEmit.apply(this, arguments) + } } } -exports.error = error; -//@ -//@ ### ShellString(str) -//@ -//@ Examples: -//@ -//@ ```javascript -//@ var foo = new ShellString('hello world'); -//@ ``` -//@ -//@ This is a dedicated type returned by most ShellJS methods, which wraps a -//@ string (or array) value. This has all the string (or array) methods, but -//@ also exposes extra methods: [`.to()`](#shellstringprototypetofile), -//@ [`.toEnd()`](#shellstringprototypetoendfile), and all the pipe-able methods -//@ (ex. `.cat()`, `.grep()`, etc.). This can be easily converted into a string -//@ by calling `.toString()`. -//@ -//@ This type also exposes the corresponding command's stdout, stderr, and -//@ return status code via the `.stdout` (string), `.stderr` (string), and -//@ `.code` (number) properties respectively. -function ShellString(stdout, stderr, code) { - var that; - if (stdout instanceof Array) { - that = stdout; - that.stdout = stdout.join('\n'); - if (stdout.length > 0) that.stdout += '\n'; - } else { - that = new String(stdout); - that.stdout = stdout; - } - that.stderr = stderr; - that.code = code; - // A list of all commands that can appear on the right-hand side of a pipe - // (populated by calls to common.wrap()) - pipeMethods.forEach(function (cmd) { - that[cmd] = shellMethods[cmd].bind(that); - }); - return that; + +/***/ }), + +/***/ 1819: +/***/ ((module) => { + +// This is not the set of all possible signals. +// +// It IS, however, the set of all signals that trigger +// an exit on either Linux or BSD systems. Linux is a +// superset of the signal names supported on BSD, and +// the unknown signals just fail to register, so we can +// catch that easily enough. +// +// Don't bother with SIGKILL. It's uncatchable, which +// means that we can't fire any callbacks anyway. +// +// If a user does happen to register a handler on a non- +// fatal signal like SIGWINCH or something, and then +// exit, it'll end up firing `process.emit('exit')`, so +// the handler will be fired anyway. +// +// SIGBUS, SIGFPE, SIGSEGV and SIGILL, when not raised +// artificially, inherently leave the process in a +// state from which it is not safe to try and enter JS +// listeners. +module.exports = [ + 'SIGABRT', + 'SIGALRM', + 'SIGHUP', + 'SIGINT', + 'SIGTERM' +] + +if (process.platform !== 'win32') { + module.exports.push( + 'SIGVTALRM', + 'SIGXCPU', + 'SIGXFSZ', + 'SIGUSR2', + 'SIGTRAP', + 'SIGSYS', + 'SIGQUIT', + 'SIGIOT' + // should detect profiler and enable/disable accordingly. + // see #21 + // 'SIGPROF' + ) } -exports.ShellString = ShellString; +if (process.platform === 'linux') { + module.exports.push( + 'SIGIO', + 'SIGPOLL', + 'SIGPWR', + 'SIGSTKFLT', + 'SIGUNUSED' + ) +} -// Returns {'alice': true, 'bob': false} when passed a string and dictionary as follows: -// parseOptions('-a', {'a':'alice', 'b':'bob'}); -// Returns {'reference': 'string-value', 'bob': false} when passed two dictionaries of the form: -// parseOptions({'-r': 'string-value'}, {'r':'reference', 'b':'bob'}); -// Throws an error when passed a string that does not start with '-': -// parseOptions('a', {'a':'alice'}); // throws -function parseOptions(opt, map, errorOptions) { - errorOptions = errorOptions || {}; - // Validate input - if (typeof opt !== 'string' && !isObject(opt)) { - throw new TypeError('options must be strings or key-value pairs'); - } else if (!isObject(map)) { - throw new TypeError('parseOptions() internal error: map must be an object'); - } else if (!isObject(errorOptions)) { - throw new TypeError( - 'parseOptions() internal error: errorOptions must be object', - ); - } - if (opt === '--') { - // This means there are no options. - return {}; - } +/***/ }), - // All options are false by default - var options = {}; - Object.keys(map).forEach(function (letter) { - var optName = map[letter]; - if (optName[0] !== '!') { - options[optName] = false; - } - }); +/***/ 9005: +/***/ ((module) => { - if (opt === '') return options; // defaults - if (typeof opt === 'string') { - if (opt[0] !== '-') { - throw new Error("Options string must start with a '-'"); - } - // e.g. chars = ['R', 'f'] - var chars = opt.slice(1).split(''); +module.exports = input => { + const LF = typeof input === 'string' ? '\n' : '\n'.charCodeAt(); + const CR = typeof input === 'string' ? '\r' : '\r'.charCodeAt(); - chars.forEach(function (c) { - if (c in map) { - var optionName = map[c]; - if (optionName[0] === '!') { - options[optionName.slice(1)] = false; - } else { - options[optionName] = true; - } - } else { - error('option not recognized: ' + c, errorOptions); - } - }); - } else { // opt is an Object - Object.keys(opt).forEach(function (key) { - if (key[0] === '-') { - // key is a string of the form '-r', '-d', etc. - var c = key[1]; - if (c in map) { - var optionName = map[c]; - options[optionName] = opt[key]; // assign the given value - } else { - error('option not recognized: ' + c, errorOptions); - } - } else if (key in options) { - // key is a "long option", so it should be the same - options[key] = opt[key]; - } else { - error('option not recognized: {' + key + ':...}', errorOptions); - } - }); - } - return options; -} -exports.parseOptions = parseOptions; + if (input[input.length - 1] === LF) { + input = input.slice(0, input.length - 1); + } -function globOptions() { - // These options are just to make fast-glob be compatible with POSIX (bash) - // wildcard behavior. - var defaultGlobOptions = { - onlyFiles: false, - followSymbolicLinks: false, - }; + if (input[input.length - 1] === CR) { + input = input.slice(0, input.length - 1); + } - var newGlobOptions = Object.assign({}, config.globOptions); - var optionRenames = { - // node-glob's 'nodir' is not quote the same as fast-glob's 'onlyFiles'. - // Compatibility for this is implemented at the call site. - mark: 'markDirectories', - matchBase: 'baseNameMatch', - }; - Object.keys(optionRenames).forEach(function (oldKey) { - var newKey = optionRenames[oldKey]; - if (oldKey in config.globOptions) { - newGlobOptions[newKey] = config.globOptions[oldKey]; - } - }); - var invertedOptionRenames = { - nobrace: 'braceExpansion', - noglobstar: 'globstar', - noext: 'extglob', - nocase: 'caseSensitiveMatch', - }; - Object.keys(invertedOptionRenames).forEach(function (oldKey) { - var newKey = invertedOptionRenames[oldKey]; - if (oldKey in config.globOptions) { - newGlobOptions[newKey] = !config.globOptions[oldKey]; - } - }); - return Object.assign({}, defaultGlobOptions, newGlobOptions); -} + return input; +}; -// Expands wildcards with matching (ie. existing) file names. -// For example: -// expand(['file*.js']) = ['file1.js', 'file2.js', ...] -// (if the files 'file1.js', 'file2.js', etc, exist in the current dir) -function expand(list) { - if (!Array.isArray(list)) { - throw new TypeError('must be an array'); + +/***/ }), + +/***/ 3763: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +/*! + * to-regex-range + * + * Copyright (c) 2015-present, Jon Schlinkert. + * Released under the MIT License. + */ + + + +const isNumber = __nccwpck_require__(6176); + +const toRegexRange = (min, max, options) => { + if (isNumber(min) === false) { + throw new TypeError('toRegexRange: expected the first argument to be a number'); } - var expanded = []; - list.forEach(function (listEl) { - // Don't expand non-strings - if (typeof listEl !== 'string') { - expanded.push(listEl); - } else { - var ret; - var globOpts = globOptions(); - try { - ret = glob.sync(listEl, globOpts); - } catch (e) { - // if glob fails, interpret the string literally - ret = [listEl]; - } - // if nothing matched, interpret the string literally - ret = ret.length > 0 ? ret.sort() : [listEl]; - if (globOpts.nodir) { - ret = ret.filter(function (file) { - return !statNoFollowLinks(file).isDirectory(); - }); - } - expanded = expanded.concat(ret); - } - }); - return expanded; -} -exports.expand = expand; -// Normalizes Buffer creation, using Buffer.alloc if possible. -// Also provides a good default buffer length for most use cases. -var buffer = typeof Buffer.alloc === 'function' ? - function (len) { - return Buffer.alloc(len || config.bufLength); - } : - function (len) { - return new Buffer(len || config.bufLength); - }; -exports.buffer = buffer; + if (max === void 0 || min === max) { + return String(min); + } -// Normalizes _unlinkSync() across platforms to match Unix behavior, i.e. -// file can be unlinked even if it's read-only, see https://github.com/joyent/node/issues/3006 -function unlinkSync(file) { - try { - fs.unlinkSync(file); - } catch (e) { - // Try to override file permission - /* istanbul ignore next */ - if (e.code === 'EPERM') { - fs.chmodSync(file, '0666'); - fs.unlinkSync(file); - } else { - throw e; - } + if (isNumber(max) === false) { + throw new TypeError('toRegexRange: expected the second argument to be a number.'); } -} -exports.unlinkSync = unlinkSync; -// wrappers around common.statFollowLinks and common.statNoFollowLinks that clarify intent -// and improve readability -function statFollowLinks() { - return fs.statSync.apply(fs, arguments); -} -exports.statFollowLinks = statFollowLinks; + let opts = { relaxZeros: true, ...options }; + if (typeof opts.strictZeros === 'boolean') { + opts.relaxZeros = opts.strictZeros === false; + } -function statNoFollowLinks() { - return fs.lstatSync.apply(fs, arguments); -} -exports.statNoFollowLinks = statNoFollowLinks; + let relax = String(opts.relaxZeros); + let shorthand = String(opts.shorthand); + let capture = String(opts.capture); + let wrap = String(opts.wrap); + let cacheKey = min + ':' + max + '=' + relax + shorthand + capture + wrap; -// e.g. 'shelljs_a5f185d0443ca...' -function randomFileName() { - function randomHash(count) { - if (count === 1) { - return parseInt(16 * Math.random(), 10).toString(16); + if (toRegexRange.cache.hasOwnProperty(cacheKey)) { + return toRegexRange.cache[cacheKey].result; + } + + let a = Math.min(min, max); + let b = Math.max(min, max); + + if (Math.abs(a - b) === 1) { + let result = min + '|' + max; + if (opts.capture) { + return `(${result})`; } - var hash = ''; - for (var i = 0; i < count; i++) { - hash += randomHash(1); + if (opts.wrap === false) { + return result; } - return hash; + return `(?:${result})`; } - return 'shelljs_' + randomHash(20); -} -exports.randomFileName = randomFileName; + let isPadded = hasPadding(min) || hasPadding(max); + let state = { min, max, a, b }; + let positives = []; + let negatives = []; -// Common wrapper for all Unix-like commands that performs glob expansion, -// command-logging, and other nice things -function wrap(cmd, fn, options) { - options = options || {}; - return function () { - var retValue = null; + if (isPadded) { + state.isPadded = isPadded; + state.maxLen = String(state.max).length; + } - state.currentCmd = cmd; - state.error = null; - state.errorCode = 0; + if (a < 0) { + let newMin = b < 0 ? Math.abs(b) : 1; + negatives = splitToPatterns(newMin, Math.abs(a), state, opts); + a = state.a = 0; + } - try { - var args = [].slice.call(arguments, 0); + if (b >= 0) { + positives = splitToPatterns(a, b, state, opts); + } - // Log the command to stderr, if appropriate - if (config.verbose) { - console.error.apply(console, [cmd].concat(args)); - } + state.negatives = negatives; + state.positives = positives; + state.result = collatePatterns(negatives, positives, opts); - // If this is coming from a pipe, let's set the pipedValue (otherwise, set - // it to the empty string) - state.pipedValue = (this && typeof this.stdout === 'string') ? this.stdout : ''; + if (opts.capture === true) { + state.result = `(${state.result})`; + } else if (opts.wrap !== false && (positives.length + negatives.length) > 1) { + state.result = `(?:${state.result})`; + } - if (options.unix === false) { // this branch is for exec() - retValue = fn.apply(this, args); - } else { // and this branch is for everything else - if (isObject(args[0]) && args[0].constructor.name === 'Object') { - // a no-op, allowing the syntax `touch({'-r': file}, ...)` - } else if (args.length === 0 || typeof args[0] !== 'string' || args[0].length <= 1 || args[0][0] !== '-') { - args.unshift(''); // only add dummy option if '-option' not already present - } - - // flatten out arrays that are arguments, to make the syntax: - // `cp([file1, file2, file3], dest);` - // equivalent to: - // `cp(file1, file2, file3, dest);` - args = args.reduce(function (accum, cur) { - if (Array.isArray(cur)) { - return accum.concat(cur); - } - accum.push(cur); - return accum; - }, []); - - // Convert ShellStrings (basically just String objects) to regular strings - args = args.map(function (arg) { - if (isObject(arg) && arg.constructor.name === 'String') { - return arg.toString(); - } - return arg; - }); + toRegexRange.cache[cacheKey] = state; + return state.result; +}; - // Expand the '~' if appropriate - var homeDir = os.homedir(); - args = args.map(function (arg) { - if (typeof arg === 'string' && arg.slice(0, 2) === '~/' || arg === '~') { - return arg.replace(/^~/, homeDir); - } - return arg; - }); +function collatePatterns(neg, pos, options) { + let onlyNegative = filterPatterns(neg, pos, '-', false, options) || []; + let onlyPositive = filterPatterns(pos, neg, '', false, options) || []; + let intersected = filterPatterns(neg, pos, '-?', true, options) || []; + let subpatterns = onlyNegative.concat(intersected).concat(onlyPositive); + return subpatterns.join('|'); +} - // Perform glob-expansion on all arguments after globStart, but preserve - // the arguments before it (like regexes for sed and grep) - if (!config.noglob && options.allowGlobbing === true) { - args = args.slice(0, options.globStart).concat(expand(args.slice(options.globStart))); - } +function splitToRanges(min, max) { + let nines = 1; + let zeros = 1; - try { - // parse options if options are provided - if (isObject(options.cmdOptions)) { - args[0] = parseOptions(args[0], options.cmdOptions); - } + let stop = countNines(min, nines); + let stops = new Set([max]); - retValue = fn.apply(this, args); - } catch (e) { - /* istanbul ignore else */ - if (e instanceof CommandError) { - retValue = e.returnValue; - } else { - throw e; // this is probably a bug that should be thrown up the call stack - } - } - } - } catch (e) { - /* istanbul ignore next */ - if (!state.error) { - // If state.error hasn't been set it's an error thrown by Node, not us - probably a bug... - e.name = 'ShellJSInternalError'; - throw e; - } - if (config.fatal || options.handlesFatalDynamically) throw e; - } + while (min <= stop && stop <= max) { + stops.add(stop); + nines += 1; + stop = countNines(min, nines); + } - if (options.wrapOutput && - (typeof retValue === 'string' || Array.isArray(retValue))) { - retValue = new ShellString(retValue, state.error, state.errorCode); - } + stop = countZeros(max + 1, zeros) - 1; - state.currentCmd = 'shell.js'; - return retValue; - }; -} // wrap -exports.wrap = wrap; + while (min < stop && stop <= max) { + stops.add(stop); + zeros += 1; + stop = countZeros(max + 1, zeros) - 1; + } -// This returns all the input that is piped into the current command (or the -// empty string, if this isn't on the right-hand side of a pipe -function _readFromPipe() { - return state.pipedValue; + stops = [...stops]; + stops.sort(compare); + return stops; } -exports.readFromPipe = _readFromPipe; -var DEFAULT_WRAP_OPTIONS = { - allowGlobbing: true, - canReceivePipe: false, - cmdOptions: null, - globStart: 1, - handlesFatalDynamically: false, - pipeOnly: false, - wrapOutput: true, - unix: true, -}; +/** + * Convert a range to a regex pattern + * @param {Number} `start` + * @param {Number} `stop` + * @return {String} + */ -// This is populated during plugin registration -var pipeMethods = []; +function rangeToPattern(start, stop, options) { + if (start === stop) { + return { pattern: start, count: [], digits: 0 }; + } -// Register a new ShellJS command -function _register(name, implementation, wrapOptions) { - wrapOptions = wrapOptions || {}; + let zipped = zip(start, stop); + let digits = zipped.length; + let pattern = ''; + let count = 0; - // Validate options - Object.keys(wrapOptions).forEach(function (option) { - if (!DEFAULT_WRAP_OPTIONS.hasOwnProperty(option)) { - throw new Error("Unknown option '" + option + "'"); - } - if (typeof wrapOptions[option] !== typeof DEFAULT_WRAP_OPTIONS[option]) { - throw new TypeError("Unsupported type '" + typeof wrapOptions[option] + - "' for option '" + option + "'"); - } - }); + for (let i = 0; i < digits; i++) { + let [startDigit, stopDigit] = zipped[i]; - // If an option isn't specified, use the default - wrapOptions = Object.assign({}, DEFAULT_WRAP_OPTIONS, wrapOptions); + if (startDigit === stopDigit) { + pattern += startDigit; - if (shell.hasOwnProperty(name)) { - throw new Error('Command `' + name + '` already exists'); - } + } else if (startDigit !== '0' || stopDigit !== '9') { + pattern += toCharacterClass(startDigit, stopDigit, options); - if (wrapOptions.pipeOnly) { - wrapOptions.canReceivePipe = true; - shellMethods[name] = wrap(name, implementation, wrapOptions); - } else { - shell[name] = wrap(name, implementation, wrapOptions); + } else { + count++; + } } - if (wrapOptions.canReceivePipe) { - pipeMethods.push(name); + if (count) { + pattern += options.shorthand === true ? '\\d' : '[0-9]'; } + + return { pattern, count: [count], digits }; } -exports.register = _register; +function splitToPatterns(min, max, tok, options) { + let ranges = splitToRanges(min, max); + let tokens = []; + let start = min; + let prev; -/***/ }), + for (let i = 0; i < ranges.length; i++) { + let max = ranges[i]; + let obj = rangeToPattern(String(start), String(max), options); + let zeros = ''; -/***/ 2981: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + if (!tok.isPadded && prev && prev.pattern === obj.pattern) { + if (prev.count.length > 1) { + prev.count.pop(); + } -var fs = __nccwpck_require__(9896); -var path = __nccwpck_require__(6928); -var common = __nccwpck_require__(3311); + prev.count.push(obj.count[0]); + prev.string = prev.pattern + toQuantifier(prev.count); + start = max + 1; + continue; + } -common.register('cp', _cp, { - cmdOptions: { - 'f': '!no_force', - 'n': 'no_force', - 'u': 'update', - 'R': 'recursive', - 'r': 'recursive', - 'L': 'followsymlink', - 'P': 'noFollowsymlink', - 'p': 'preserve', - }, - wrapOutput: false, -}); + if (tok.isPadded) { + zeros = padZeros(max, tok, options); + } -// Buffered file copy, synchronous -// (Using readFileSync() + writeFileSync() could easily cause a memory overflow -// with large files) -function copyFileSync(srcFile, destFile, options) { - if (!fs.existsSync(srcFile)) { - common.error('copyFileSync: no such file or directory: ' + srcFile); + obj.string = zeros + obj.pattern + toQuantifier(obj.count); + tokens.push(obj); + start = max + 1; + prev = obj; } - var isWindows = process.platform === 'win32'; - - // Check the mtimes of the files if the '-u' flag is provided - try { - if (options.update && common.statFollowLinks(srcFile).mtime < fs.statSync(destFile).mtime) { - return; - } - } catch (e) { - // If we're here, destFile probably doesn't exist, so just do a normal copy - } + return tokens; +} - if (common.statNoFollowLinks(srcFile).isSymbolicLink() && !options.followsymlink) { - try { - common.statNoFollowLinks(destFile); - common.unlinkSync(destFile); // re-link it - } catch (e) { - // it doesn't exist, so no work needs to be done - } +function filterPatterns(arr, comparison, prefix, intersection, options) { + let result = []; - var symlinkFull = fs.readlinkSync(srcFile); - fs.symlinkSync(symlinkFull, destFile, isWindows ? 'junction' : null); - } else { - var buf = common.buffer(); - var bufLength = buf.length; - var bytesRead = bufLength; - var pos = 0; - var fdr = null; - var fdw = null; - var srcStat = common.statFollowLinks(srcFile); + for (let ele of arr) { + let { string } = ele; - try { - fdr = fs.openSync(srcFile, 'r'); - } catch (e) { - /* istanbul ignore next */ - common.error('copyFileSync: could not read src file (' + srcFile + ')'); + // only push if _both_ are negative... + if (!intersection && !contains(comparison, 'string', string)) { + result.push(prefix + string); } - try { - fdw = fs.openSync(destFile, 'w', srcStat.mode); - } catch (e) { - /* istanbul ignore next */ - common.error('copyFileSync: could not write to dest file (code=' + e.code + '):' + destFile); + // or _both_ are positive + if (intersection && contains(comparison, 'string', string)) { + result.push(prefix + string); } + } + return result; +} - while (bytesRead === bufLength) { - bytesRead = fs.readSync(fdr, buf, 0, bufLength, pos); - fs.writeSync(fdw, buf, 0, bytesRead); - pos += bytesRead; - } +/** + * Zip strings + */ - if (options.preserve) { - fs.fchownSync(fdw, srcStat.uid, srcStat.gid); - // Note: utimesSync does not work (rounds to seconds), but futimesSync has - // millisecond precision. - fs.futimesSync(fdw, srcStat.atime, srcStat.mtime); - } +function zip(a, b) { + let arr = []; + for (let i = 0; i < a.length; i++) arr.push([a[i], b[i]]); + return arr; +} - fs.closeSync(fdr); - fs.closeSync(fdw); - } +function compare(a, b) { + return a > b ? 1 : b > a ? -1 : 0; } -// Recursively copies 'sourceDir' into 'destDir' -// Adapted from https://github.com/ryanmcgrath/wrench-js -// -// Copyright (c) 2010 Ryan McGrath -// Copyright (c) 2012 Artur Adib -// -// Licensed under the MIT License -// http://www.opensource.org/licenses/mit-license.php -function cpdirSyncRecursive(sourceDir, destDir, currentDepth, opts) { - if (!opts) opts = {}; +function contains(arr, key, val) { + return arr.some(ele => ele[key] === val); +} - // Ensure there is not a run away recursive copy - if (currentDepth >= common.config.maxdepth) return; - currentDepth++; +function countNines(min, len) { + return Number(String(min).slice(0, -len) + '9'.repeat(len)); +} - var isWindows = process.platform === 'win32'; +function countZeros(integer, zeros) { + return integer - (integer % Math.pow(10, zeros)); +} - // Create the directory where all our junk is moving to; read the mode/etc. of - // the source directory (we'll set this on the destDir at the end). - var checkDir = common.statFollowLinks(sourceDir); - try { - fs.mkdirSync(destDir); - } catch (e) { - // if the directory already exists, that's okay - if (e.code !== 'EEXIST') throw e; +function toQuantifier(digits) { + let [start = 0, stop = ''] = digits; + if (stop || start > 1) { + return `{${start + (stop ? ',' + stop : '')}}`; } + return ''; +} - var files = fs.readdirSync(sourceDir); - - for (var i = 0; i < files.length; i++) { - var srcFile = sourceDir + '/' + files[i]; - var destFile = destDir + '/' + files[i]; - var srcFileStat = common.statNoFollowLinks(srcFile); +function toCharacterClass(a, b, options) { + return `[${a}${(b - a === 1) ? '' : '-'}${b}]`; +} - var symlinkFull; - if (opts.followsymlink) { - if (cpcheckcycle(sourceDir, srcFile)) { - // Cycle link found. - console.error('Cycle link found.'); - symlinkFull = fs.readlinkSync(srcFile); - fs.symlinkSync(symlinkFull, destFile, isWindows ? 'junction' : null); - continue; - } - } - if (srcFileStat.isDirectory()) { - /* recursion this thing right on back. */ - cpdirSyncRecursive(srcFile, destFile, currentDepth, opts); - } else if (srcFileStat.isSymbolicLink() && !opts.followsymlink) { - symlinkFull = fs.readlinkSync(srcFile); - try { - common.statNoFollowLinks(destFile); - common.unlinkSync(destFile); // re-link it - } catch (e) { - // it doesn't exist, so no work needs to be done - } - fs.symlinkSync(symlinkFull, destFile, isWindows ? 'junction' : null); - } else if (srcFileStat.isSymbolicLink() && opts.followsymlink) { - srcFileStat = common.statFollowLinks(srcFile); - if (srcFileStat.isDirectory()) { - cpdirSyncRecursive(srcFile, destFile, currentDepth, opts); - } else { - copyFileSync(srcFile, destFile, opts); - } - } else if (fs.existsSync(destFile) && opts.no_force) { - common.log('skipping existing file: ' + files[i]); - } else { - copyFileSync(srcFile, destFile, opts); - } - } // for files +function hasPadding(str) { + return /^-?(0+)\d/.test(str); +} - // finally change the mode for the newly created directory (otherwise, we - // couldn't add files to a read-only directory). - // var checkDir = common.statFollowLinks(sourceDir); - if (opts.preserve) { - fs.utimesSync(destDir, checkDir.atime, checkDir.mtime); +function padZeros(value, tok, options) { + if (!tok.isPadded) { + return value; } - fs.chmodSync(destDir, checkDir.mode); -} // cpdirSyncRecursive -// Checks if cureent file was created recently -function checkRecentCreated(sources, index) { - var lookedSource = sources[index]; - return sources.slice(0, index).some(function (src) { - return path.basename(src) === path.basename(lookedSource); - }); -} + let diff = Math.abs(tok.maxLen - String(value).length); + let relax = options.relaxZeros !== false; -function cpcheckcycle(sourceDir, srcFile) { - var srcFileStat = common.statNoFollowLinks(srcFile); - if (srcFileStat.isSymbolicLink()) { - // Do cycle check. For example: - // $ mkdir -p 1/2/3/4 - // $ cd 1/2/3/4 - // $ ln -s ../../3 link - // $ cd ../../../.. - // $ cp -RL 1 copy - var cyclecheck = common.statFollowLinks(srcFile); - if (cyclecheck.isDirectory()) { - var sourcerealpath = fs.realpathSync(sourceDir); - var symlinkrealpath = fs.realpathSync(srcFile); - var re = new RegExp(symlinkrealpath); - if (re.test(sourcerealpath)) { - return true; - } + switch (diff) { + case 0: + return ''; + case 1: + return relax ? '0?' : '0'; + case 2: + return relax ? '0{0,2}' : '00'; + default: { + return relax ? `0{0,${diff}}` : `0{${diff}}`; } } - return false; } -//@ -//@ ### cp([options,] source [, source ...], dest) -//@ ### cp([options,] source_array, dest) -//@ -//@ Available options: -//@ -//@ + `-f`: force (default behavior) -//@ + `-n`: no-clobber -//@ + `-u`: only copy if `source` is newer than `dest` -//@ + `-r`, `-R`: recursive -//@ + `-L`: follow symlinks -//@ + `-P`: don't follow symlinks -//@ + `-p`: preserve file mode, ownership, and timestamps -//@ -//@ Examples: -//@ -//@ ```javascript -//@ cp('file1', 'dir1'); -//@ cp('-R', 'path/to/dir/', '~/newCopy/'); -//@ cp('-Rf', '/tmp/*', '/usr/local/*', '/home/tmp'); -//@ cp('-Rf', ['/tmp/*', '/usr/local/*'], '/home/tmp'); // same as above -//@ ``` -//@ -//@ Copies files. Returns a [ShellString](#shellstringstr) indicating success -//@ or failure. -function _cp(options, sources, dest) { - // If we're missing -R, it actually implies -L (unless -P is explicit) - if (options.followsymlink) { - options.noFollowsymlink = false; - } - if (!options.recursive && !options.noFollowsymlink) { - options.followsymlink = true; - } +/** + * Cache + */ - // Get sources, dest - if (arguments.length < 3) { - common.error('missing and/or '); - } else { - sources = [].slice.call(arguments, 1, arguments.length - 1); - dest = arguments[arguments.length - 1]; - } +toRegexRange.cache = {}; +toRegexRange.clearCache = () => (toRegexRange.cache = {}); - var destExists = fs.existsSync(dest); - var destStat = destExists && common.statFollowLinks(dest); +/** + * Expose `toRegexRange` + */ - // Dest is not existing dir, but multiple sources given - if ((!destExists || !destStat.isDirectory()) && sources.length > 1) { - common.error('dest is not a directory (too many sources)'); - } +module.exports = toRegexRange; - // Dest is an existing file, but -n is given - if (destExists && destStat.isFile() && options.no_force) { - return new common.ShellString('', '', 0); - } - sources.forEach(function (src, srcIndex) { - if (!fs.existsSync(src)) { - if (src === '') src = "''"; // if src was empty string, display empty string - common.error('no such file or directory: ' + src, { continue: true }); - return; // skip file - } - var srcStat = common.statFollowLinks(src); - if (!options.noFollowsymlink && srcStat.isDirectory()) { - if (!options.recursive) { - // Non-Recursive - common.error("omitting directory '" + src + "'", { continue: true }); - } else { - // Recursive - // 'cp /a/source dest' should create 'source' in 'dest' - var newDest = (destStat && destStat.isDirectory()) ? - path.join(dest, path.basename(src)) : - dest; +/***/ }), - try { - common.statFollowLinks(path.dirname(dest)); - cpdirSyncRecursive(src, newDest, 0, options); - } catch (e) { - /* istanbul ignore next */ - common.error("cannot create directory '" + dest + "': No such file or directory"); - } - } - } else { - // If here, src is a file +/***/ 406: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - // When copying to '/path/dir': - // thisDest = '/path/dir/file1' - var thisDest = dest; - if (destStat && destStat.isDirectory()) { - thisDest = path.normalize(dest + '/' + path.basename(src)); - } +module.exports = __nccwpck_require__(1822); - var thisDestExists = fs.existsSync(thisDest); - if (thisDestExists && checkRecentCreated(sources, srcIndex)) { - // cannot overwrite file created recently in current execution, but we want to continue copying other files - if (!options.no_force) { - common.error("will not overwrite just-created '" + thisDest + "' with '" + src + "'", { continue: true }); - } - return; - } - if (thisDestExists && options.no_force) { - return; // skip file - } +/***/ }), - if (path.relative(src, thisDest) === '') { - // a file cannot be copied to itself, but we want to continue copying other files - common.error("'" + thisDest + "' and '" + src + "' are the same file", { continue: true }); - return; - } +/***/ 1822: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - copyFileSync(src, thisDest, options); - } - }); // forEach(src) +var __webpack_unused_export__; - return new common.ShellString('', common.state.error, common.state.errorCode); -} -module.exports = _cp; +var net = __nccwpck_require__(9278); +var tls = __nccwpck_require__(4756); +var http = __nccwpck_require__(8611); +var https = __nccwpck_require__(5692); +var events = __nccwpck_require__(4434); +var assert = __nccwpck_require__(2613); +var util = __nccwpck_require__(9023); -/***/ }), -/***/ 4346: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { +exports.httpOverHttp = httpOverHttp; +exports.httpsOverHttp = httpsOverHttp; +exports.httpOverHttps = httpOverHttps; +exports.httpsOverHttps = httpsOverHttps; -var path = __nccwpck_require__(6928); -var common = __nccwpck_require__(3311); -var _cd = __nccwpck_require__(6649); -common.register('dirs', _dirs, { - wrapOutput: false, -}); -common.register('pushd', _pushd, { - wrapOutput: false, -}); -common.register('popd', _popd, { - wrapOutput: false, -}); +function httpOverHttp(options) { + var agent = new TunnelingAgent(options); + agent.request = http.request; + return agent; +} -// Pushd/popd/dirs internals -var _dirStack = []; +function httpsOverHttp(options) { + var agent = new TunnelingAgent(options); + agent.request = http.request; + agent.createSocket = createSecureSocket; + agent.defaultPort = 443; + return agent; +} -function _isStackIndex(index) { - return (/^[-+]\d+$/).test(index); +function httpOverHttps(options) { + var agent = new TunnelingAgent(options); + agent.request = https.request; + return agent; } -function _parseStackIndex(index) { - if (_isStackIndex(index)) { - if (Math.abs(index) < _dirStack.length + 1) { // +1 for pwd - return (/^-/).test(index) ? Number(index) - 1 : Number(index); - } - common.error(index + ': directory stack index out of range'); - } else { - common.error(index + ': invalid number'); - } +function httpsOverHttps(options) { + var agent = new TunnelingAgent(options); + agent.request = https.request; + agent.createSocket = createSecureSocket; + agent.defaultPort = 443; + return agent; } -function _actualDirStack() { - return [process.cwd()].concat(_dirStack); + +function TunnelingAgent(options) { + var self = this; + self.options = options || {}; + self.proxyOptions = self.options.proxy || {}; + self.maxSockets = self.options.maxSockets || http.Agent.defaultMaxSockets; + self.requests = []; + self.sockets = []; + + self.on('free', function onFree(socket, host, port, localAddress) { + var options = toOptions(host, port, localAddress); + for (var i = 0, len = self.requests.length; i < len; ++i) { + var pending = self.requests[i]; + if (pending.host === options.host && pending.port === options.port) { + // Detect the request to connect same origin server, + // reuse the connection. + self.requests.splice(i, 1); + pending.request.onSocket(socket); + return; + } + } + socket.destroy(); + self.removeSocket(socket); + }); } +util.inherits(TunnelingAgent, events.EventEmitter); -//@ -//@ ### pushd([options,] [dir | '-N' | '+N']) -//@ -//@ Available options: -//@ -//@ + `-n`: Suppresses the normal change of directory when adding directories to the stack, so that only the stack is manipulated. -//@ + `-q`: Suppresses output to the console. -//@ -//@ Arguments: -//@ -//@ + `dir`: Sets the current working directory to the top of the stack, then executes the equivalent of `cd dir`. -//@ + `+N`: Brings the Nth directory (counting from the left of the list printed by dirs, starting with zero) to the top of the list by rotating the stack. -//@ + `-N`: Brings the Nth directory (counting from the right of the list printed by dirs, starting with zero) to the top of the list by rotating the stack. -//@ -//@ Examples: -//@ -//@ ```javascript -//@ // process.cwd() === '/usr' -//@ pushd('/etc'); // Returns /etc /usr -//@ pushd('+1'); // Returns /usr /etc -//@ ``` -//@ -//@ Save the current directory on the top of the directory stack and then `cd` to `dir`. With no arguments, `pushd` exchanges the top two directories. Returns an array of paths in the stack. -function _pushd(options, dir) { - if (_isStackIndex(options)) { - dir = options; - options = ''; +TunnelingAgent.prototype.addRequest = function addRequest(req, host, port, localAddress) { + var self = this; + var options = mergeOptions({request: req}, self.options, toOptions(host, port, localAddress)); + + if (self.sockets.length >= this.maxSockets) { + // We are over limit so we'll add it to the queue. + self.requests.push(options); + return; } - options = common.parseOptions(options, { - 'n': 'no-cd', - 'q': 'quiet', + // If we are under maxSockets create a new one. + self.createSocket(options, function(socket) { + socket.on('free', onFree); + socket.on('close', onCloseOrRemove); + socket.on('agentRemove', onCloseOrRemove); + req.onSocket(socket); + + function onFree() { + self.emit('free', socket, options); + } + + function onCloseOrRemove(err) { + self.removeSocket(socket); + socket.removeListener('free', onFree); + socket.removeListener('close', onCloseOrRemove); + socket.removeListener('agentRemove', onCloseOrRemove); + } }); +}; - var dirs = _actualDirStack(); +TunnelingAgent.prototype.createSocket = function createSocket(options, cb) { + var self = this; + var placeholder = {}; + self.sockets.push(placeholder); - if (dir === '+0') { - return dirs; // +0 is a noop - } else if (!dir) { - if (dirs.length > 1) { - dirs = dirs.splice(1, 1).concat(dirs); - } else { - return common.error('no other directory'); + var connectOptions = mergeOptions({}, self.proxyOptions, { + method: 'CONNECT', + path: options.host + ':' + options.port, + agent: false, + headers: { + host: options.host + ':' + options.port } - } else if (_isStackIndex(dir)) { - var n = _parseStackIndex(dir); - dirs = dirs.slice(n).concat(dirs.slice(0, n)); - } else if (options['no-cd']) { - dirs.splice(1, 0, dir); - } else { - dirs.unshift(dir); + }); + if (options.localAddress) { + connectOptions.localAddress = options.localAddress; } - - if (options['no-cd']) { - dirs = dirs.slice(1); - } else { - dir = path.resolve(dirs.shift()); - _cd('', dir); + if (connectOptions.proxyAuth) { + connectOptions.headers = connectOptions.headers || {}; + connectOptions.headers['Proxy-Authorization'] = 'Basic ' + + new Buffer(connectOptions.proxyAuth).toString('base64'); } - _dirStack = dirs; - return _dirs(options.quiet ? '-q' : ''); -} -exports.pushd = _pushd; + debug('making CONNECT request'); + var connectReq = self.request(connectOptions); + connectReq.useChunkedEncodingByDefault = false; // for v0.6 + connectReq.once('response', onResponse); // for v0.6 + connectReq.once('upgrade', onUpgrade); // for v0.6 + connectReq.once('connect', onConnect); // for v0.7 or later + connectReq.once('error', onError); + connectReq.end(); -//@ -//@ -//@ ### popd([options,] ['-N' | '+N']) -//@ -//@ Available options: -//@ -//@ + `-n`: Suppress the normal directory change when removing directories from the stack, so that only the stack is manipulated. -//@ + `-q`: Suppresses output to the console. -//@ -//@ Arguments: -//@ -//@ + `+N`: Removes the Nth directory (counting from the left of the list printed by dirs), starting with zero. -//@ + `-N`: Removes the Nth directory (counting from the right of the list printed by dirs), starting with zero. -//@ -//@ Examples: -//@ -//@ ```javascript -//@ echo(process.cwd()); // '/usr' -//@ pushd('/etc'); // '/etc /usr' -//@ echo(process.cwd()); // '/etc' -//@ popd(); // '/usr' -//@ echo(process.cwd()); // '/usr' -//@ ``` -//@ -//@ When no arguments are given, `popd` removes the top directory from the stack and performs a `cd` to the new top directory. The elements are numbered from 0, starting at the first directory listed with dirs (i.e., `popd` is equivalent to `popd +0`). Returns an array of paths in the stack. -function _popd(options, index) { - if (_isStackIndex(options)) { - index = options; - options = ''; + function onResponse(res) { + // Very hacky. This is necessary to avoid http-parser leaks. + res.upgrade = true; } - options = common.parseOptions(options, { - 'n': 'no-cd', - 'q': 'quiet', - }); - - if (!_dirStack.length) { - return common.error('directory stack empty'); + function onUpgrade(res, socket, head) { + // Hacky. + process.nextTick(function() { + onConnect(res, socket, head); + }); } - index = _parseStackIndex(index || '+0'); + function onConnect(res, socket, head) { + connectReq.removeAllListeners(); + socket.removeAllListeners(); - if (options['no-cd'] || index > 0 || _dirStack.length + index === 0) { - index = index > 0 ? index - 1 : index; - _dirStack.splice(index, 1); - } else { - var dir = path.resolve(_dirStack.shift()); - _cd('', dir); + if (res.statusCode !== 200) { + debug('tunneling socket could not be established, statusCode=%d', + res.statusCode); + socket.destroy(); + var error = new Error('tunneling socket could not be established, ' + + 'statusCode=' + res.statusCode); + error.code = 'ECONNRESET'; + options.request.emit('error', error); + self.removeSocket(placeholder); + return; + } + if (head.length > 0) { + debug('got illegal response body from proxy'); + socket.destroy(); + var error = new Error('got illegal response body from proxy'); + error.code = 'ECONNRESET'; + options.request.emit('error', error); + self.removeSocket(placeholder); + return; + } + debug('tunneling connection has established'); + self.sockets[self.sockets.indexOf(placeholder)] = socket; + return cb(socket); } - return _dirs(options.quiet ? '-q' : ''); -} -exports.popd = _popd; + function onError(cause) { + connectReq.removeAllListeners(); -//@ -//@ -//@ ### dirs([options | '+N' | '-N']) -//@ -//@ Available options: -//@ -//@ + `-c`: Clears the directory stack by deleting all of the elements. -//@ + `-q`: Suppresses output to the console. -//@ -//@ Arguments: -//@ -//@ + `+N`: Displays the Nth directory (counting from the left of the list printed by dirs when invoked without options), starting with zero. -//@ + `-N`: Displays the Nth directory (counting from the right of the list printed by dirs when invoked without options), starting with zero. -//@ -//@ Display the list of currently remembered directories. Returns an array of paths in the stack, or a single path if `+N` or `-N` was specified. -//@ -//@ See also: `pushd`, `popd` -function _dirs(options, index) { - if (_isStackIndex(options)) { - index = options; - options = ''; + debug('tunneling socket could not be established, cause=%s\n', + cause.message, cause.stack); + var error = new Error('tunneling socket could not be established, ' + + 'cause=' + cause.message); + error.code = 'ECONNRESET'; + options.request.emit('error', error); + self.removeSocket(placeholder); } +}; - options = common.parseOptions(options, { - 'c': 'clear', - 'q': 'quiet', - }); +TunnelingAgent.prototype.removeSocket = function removeSocket(socket) { + var pos = this.sockets.indexOf(socket) + if (pos === -1) { + return; + } + this.sockets.splice(pos, 1); - if (options.clear) { - _dirStack = []; - return _dirStack; + var pending = this.requests.shift(); + if (pending) { + // If we have pending requests and a socket gets closed a new one + // needs to be created to take over in the pool for the one that closed. + this.createSocket(pending, function(socket) { + pending.request.onSocket(socket); + }); } +}; - var stack = _actualDirStack(); +function createSecureSocket(options, cb) { + var self = this; + TunnelingAgent.prototype.createSocket.call(self, options, function(socket) { + var hostHeader = options.request.getHeader('host'); + var tlsOptions = mergeOptions({}, self.options, { + socket: socket, + servername: hostHeader ? hostHeader.replace(/:.*$/, '') : options.host + }); - if (index) { - index = _parseStackIndex(index); + // 0 is dummy port for v0.6 + var secureSocket = tls.connect(0, tlsOptions); + self.sockets[self.sockets.indexOf(socket)] = secureSocket; + cb(secureSocket); + }); +} - if (index < 0) { - index = stack.length + index; - } - if (!options.quiet) { - common.log(stack[index]); - } - return stack[index]; +function toOptions(host, port, localAddress) { + if (typeof host === 'string') { // since v0.10 + return { + host: host, + port: port, + localAddress: localAddress + }; } + return host; // for v0.11 or later +} - if (!options.quiet) { - common.log(stack.join(' ')); +function mergeOptions(target) { + for (var i = 1, len = arguments.length; i < len; ++i) { + var overrides = arguments[i]; + if (typeof overrides === 'object') { + var keys = Object.keys(overrides); + for (var j = 0, keyLen = keys.length; j < keyLen; ++j) { + var k = keys[j]; + if (overrides[k] !== undefined) { + target[k] = overrides[k]; + } + } + } } + return target; +} - return stack; + +var debug; +if (process.env.NODE_DEBUG && /\btunnel\b/.test(process.env.NODE_DEBUG)) { + debug = function() { + var args = Array.prototype.slice.call(arguments); + if (typeof args[0] === 'string') { + args[0] = 'TUNNEL: ' + args[0]; + } else { + args.unshift('TUNNEL:'); + } + console.error.apply(console, args); + } +} else { + debug = function() {}; } -exports.dirs = _dirs; +__webpack_unused_export__ = debug; // for test /***/ }), -/***/ 8191: +/***/ 6486: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -var format = (__nccwpck_require__(9023).format); +var __webpack_unused_export__; -var common = __nccwpck_require__(3311); -common.register('echo', _echo, { - allowGlobbing: false, -}); +const Client = __nccwpck_require__(9143) +const Dispatcher = __nccwpck_require__(5137) +const Pool = __nccwpck_require__(4105) +const BalancedPool = __nccwpck_require__(6895) +const Agent = __nccwpck_require__(4779) +const ProxyAgent = __nccwpck_require__(6614) +const EnvHttpProxyAgent = __nccwpck_require__(8019) +const RetryAgent = __nccwpck_require__(8800) +const errors = __nccwpck_require__(329) +const util = __nccwpck_require__(7234) +const { InvalidArgumentError } = errors +const api = __nccwpck_require__(3609) +const buildConnector = __nccwpck_require__(3242) +const MockClient = __nccwpck_require__(4111) +const MockAgent = __nccwpck_require__(5955) +const MockPool = __nccwpck_require__(2958) +const mockErrors = __nccwpck_require__(6843) +const RetryHandler = __nccwpck_require__(1838) +const { getGlobalDispatcher, setGlobalDispatcher } = __nccwpck_require__(1903) +const DecoratorHandler = __nccwpck_require__(6541) +const RedirectHandler = __nccwpck_require__(7608) +const createRedirectInterceptor = __nccwpck_require__(2642) -//@ -//@ ### echo([options,] string [, string ...]) -//@ -//@ Available options: -//@ -//@ + `-e`: interpret backslash escapes (default) -//@ + `-n`: remove trailing newline from output -//@ -//@ Examples: -//@ -//@ ```javascript -//@ echo('hello world'); -//@ var str = echo('hello world'); -//@ echo('-n', 'no newline at end'); -//@ ``` -//@ -//@ Prints `string` to stdout, and returns a [ShellString](#shellstringstr). -function _echo(opts) { - // allow strings starting with '-', see issue #20 - var messages = [].slice.call(arguments, opts ? 0 : 1); - var options = {}; +Object.assign(Dispatcher.prototype, api) - // If the first argument starts with '-', parse it as options string. - // If parseOptions throws, it wasn't an options string. - try { - options = common.parseOptions(messages[0], { - 'e': 'escapes', - 'n': 'no_newline', - }, { - silent: true, - }); +__webpack_unused_export__ = Dispatcher +__webpack_unused_export__ = Client +__webpack_unused_export__ = Pool +__webpack_unused_export__ = BalancedPool +__webpack_unused_export__ = Agent +module.exports.kT = ProxyAgent +__webpack_unused_export__ = EnvHttpProxyAgent +__webpack_unused_export__ = RetryAgent +__webpack_unused_export__ = RetryHandler + +__webpack_unused_export__ = DecoratorHandler +__webpack_unused_export__ = RedirectHandler +__webpack_unused_export__ = createRedirectInterceptor +__webpack_unused_export__ = { + redirect: __nccwpck_require__(3540), + retry: __nccwpck_require__(3916), + dump: __nccwpck_require__(2546), + dns: __nccwpck_require__(1386) +} + +__webpack_unused_export__ = buildConnector +__webpack_unused_export__ = errors +__webpack_unused_export__ = { + parseHeaders: util.parseHeaders, + headerNameToString: util.headerNameToString +} - // Allow null to be echoed - if (messages[0]) { - messages.shift(); +function makeDispatcher (fn) { + return (url, opts, handler) => { + if (typeof opts === 'function') { + handler = opts + opts = null } - } catch (_) { - // Clear out error if an error occurred - common.state.error = null; - } - - var output = format.apply(null, messages); - // Add newline if -n is not passed. - if (!options.no_newline) { - output += '\n'; - } + if (!url || (typeof url !== 'string' && typeof url !== 'object' && !(url instanceof URL))) { + throw new InvalidArgumentError('invalid url') + } - process.stdout.write(output); + if (opts != null && typeof opts !== 'object') { + throw new InvalidArgumentError('invalid opts') + } - return output; -} + if (opts && opts.path != null) { + if (typeof opts.path !== 'string') { + throw new InvalidArgumentError('invalid opts.path') + } -module.exports = _echo; + let path = opts.path + if (!opts.path.startsWith('/')) { + path = `/${path}` + } + url = new URL(util.parseOrigin(url).origin + path) + } else { + if (!opts) { + opts = typeof url === 'object' ? url : {} + } -/***/ }), + url = util.parseURL(url) + } -/***/ 6190: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + const { agent, dispatcher = getGlobalDispatcher() } = opts -var common = __nccwpck_require__(3311); + if (agent) { + throw new InvalidArgumentError('unsupported opts.agent. Did you mean opts.client?') + } -//@ -//@ ### error() -//@ -//@ Tests if error occurred in the last command. Returns a truthy value if an -//@ error returned, or a falsy value otherwise. -//@ -//@ **Note**: do not rely on the -//@ return value to be an error message. If you need the last error message, use -//@ the `.stderr` attribute from the last command's return value instead. -function error() { - return common.state.error; + return fn.call(dispatcher, { + ...opts, + origin: url.origin, + path: url.search ? `${url.pathname}${url.search}` : url.pathname, + method: opts.method || (opts.body ? 'PUT' : 'GET') + }, handler) + } } -module.exports = error; +__webpack_unused_export__ = setGlobalDispatcher +__webpack_unused_export__ = getGlobalDispatcher -/***/ }), +const fetchImpl = (__nccwpck_require__(5780).fetch) +__webpack_unused_export__ = async function fetch (init, options = undefined) { + try { + return await fetchImpl(init, options) + } catch (err) { + if (err && typeof err === 'object') { + Error.captureStackTrace(err) + } -/***/ 5163: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + throw err + } +} +/* unused reexport */ __nccwpck_require__(217).Headers +/* unused reexport */ __nccwpck_require__(4317).Response +/* unused reexport */ __nccwpck_require__(5417).Request +/* unused reexport */ __nccwpck_require__(9411).FormData +__webpack_unused_export__ = globalThis.File ?? (__nccwpck_require__(4573).File) +/* unused reexport */ __nccwpck_require__(1705).FileReader -var common = __nccwpck_require__(3311); +const { setGlobalOrigin, getGlobalOrigin } = __nccwpck_require__(7786) -//@ -//@ ### errorCode() -//@ -//@ Returns the error code from the last command. -function errorCode() { - return common.state.errorCode; -} -module.exports = errorCode; +__webpack_unused_export__ = setGlobalOrigin +__webpack_unused_export__ = getGlobalOrigin + +const { CacheStorage } = __nccwpck_require__(9603) +const { kConstruct } = __nccwpck_require__(7415) + +// Cache & CacheStorage are tightly coupled with fetch. Even if it may run +// in an older version of Node, it doesn't have any use without fetch. +__webpack_unused_export__ = new CacheStorage(kConstruct) + +const { deleteCookie, getCookies, getSetCookies, setCookie } = __nccwpck_require__(3191) + +__webpack_unused_export__ = deleteCookie +__webpack_unused_export__ = getCookies +__webpack_unused_export__ = getSetCookies +__webpack_unused_export__ = setCookie + +const { parseMIMEType, serializeAMimeType } = __nccwpck_require__(6406) + +__webpack_unused_export__ = parseMIMEType +__webpack_unused_export__ = serializeAMimeType + +const { CloseEvent, ErrorEvent, MessageEvent } = __nccwpck_require__(8086) +/* unused reexport */ __nccwpck_require__(5136).WebSocket +__webpack_unused_export__ = CloseEvent +__webpack_unused_export__ = ErrorEvent +__webpack_unused_export__ = MessageEvent + +__webpack_unused_export__ = makeDispatcher(api.request) +__webpack_unused_export__ = makeDispatcher(api.stream) +__webpack_unused_export__ = makeDispatcher(api.pipeline) +__webpack_unused_export__ = makeDispatcher(api.connect) +__webpack_unused_export__ = makeDispatcher(api.upgrade) + +__webpack_unused_export__ = MockClient +__webpack_unused_export__ = MockPool +__webpack_unused_export__ = MockAgent +__webpack_unused_export__ = mockErrors + +const { EventSource } = __nccwpck_require__(7888) + +__webpack_unused_export__ = EventSource /***/ }), -/***/ 4884: -/***/ ((__unused_webpack_module, __unused_webpack_exports, __nccwpck_require__) => { +/***/ 2088: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -var childProcess = __nccwpck_require__(5317); -var fs = __nccwpck_require__(9896); +const { addAbortListener } = __nccwpck_require__(7234) +const { RequestAbortedError } = __nccwpck_require__(329) -function main() { - var paramFilePath = process.argv[2]; +const kListener = Symbol('kListener') +const kSignal = Symbol('kSignal') - var serializedParams = fs.readFileSync(paramFilePath, 'utf8'); - var params = JSON.parse(serializedParams); +function abort (self) { + if (self.abort) { + self.abort(self[kSignal]?.reason) + } else { + self.reason = self[kSignal]?.reason ?? new RequestAbortedError() + } + removeSignal(self) +} - var cmd = params.command; - var execOptions = params.execOptions; - var pipe = params.pipe; - var stdoutFile = params.stdoutFile; - var stderrFile = params.stderrFile; +function addSignal (self, signal) { + self.reason = null - function isMaxBufferError(err) { - var maxBufferErrorPattern = /^.*\bmaxBuffer\b.*exceeded.*$/; - if (err instanceof Error && err.message && - err.message.match(maxBufferErrorPattern)) { - // < v10 - // Error: stdout maxBuffer exceeded - return true; - } else if (err instanceof RangeError && err.message && - err.message.match(maxBufferErrorPattern)) { - // >= v10 - // RangeError [ERR_CHILD_PROCESS_STDIO_MAXBUFFER]: stdout maxBuffer length - // exceeded - return true; - } - return false; + self[kSignal] = null + self[kListener] = null + + if (!signal) { + return } - var stdoutStream = fs.createWriteStream(stdoutFile); - var stderrStream = fs.createWriteStream(stderrFile); + if (signal.aborted) { + abort(self) + return + } - function appendError(message, code) { - stderrStream.write(message); - process.exitCode = code; + self[kSignal] = signal + self[kListener] = () => { + abort(self) } - var c = childProcess.exec(cmd, execOptions, function (err) { - if (!err) { - process.exitCode = 0; - } else if (isMaxBufferError(err)) { - appendError('maxBuffer exceeded', 1); - } else if (err.code === undefined && err.message) { - /* istanbul ignore next */ - appendError(err.message, 1); - } else if (err.code === undefined) { - /* istanbul ignore next */ - appendError('Unknown issue', 1); - } else { - process.exitCode = err.code; - } - }); + addAbortListener(self[kSignal], self[kListener]) +} - c.stdout.pipe(stdoutStream); - c.stderr.pipe(stderrStream); - c.stdout.pipe(process.stdout); - c.stderr.pipe(process.stderr); +function removeSignal (self) { + if (!self[kSignal]) { + return + } - if (pipe) { - c.stdin.end(pipe); + if ('removeEventListener' in self[kSignal]) { + self[kSignal].removeEventListener('abort', self[kListener]) + } else { + self[kSignal].removeListener('abort', self[kListener]) } + + self[kSignal] = null + self[kListener] = null } -// This file should only be executed. This module does not export anything. -/* istanbul ignore else */ -if (false) {} +module.exports = { + addSignal, + removeSignal +} /***/ }), -/***/ 263: +/***/ 3846: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -var path = __nccwpck_require__(6928); -var fs = __nccwpck_require__(9896); -var child = __nccwpck_require__(5317); -var common = __nccwpck_require__(3311); -var _tempDir = (__nccwpck_require__(1125).tempDir); -var _pwd = __nccwpck_require__(4879); - -var DEFAULT_MAXBUFFER_SIZE = 20 * 1024 * 1024; -var DEFAULT_ERROR_CODE = 1; -common.register('exec', _exec, { - unix: false, - canReceivePipe: true, - wrapOutput: false, - handlesFatalDynamically: true, -}); -// We use this function to run `exec` synchronously while also providing realtime -// output. -function execSync(cmd, opts, pipe) { - if (!common.config.execPath) { - try { - common.error('Unable to find a path to the node binary. Please manually set config.execPath'); - } catch (e) { - if (opts.fatal) { - throw e; - } +const assert = __nccwpck_require__(4589) +const { AsyncResource } = __nccwpck_require__(6698) +const { InvalidArgumentError, SocketError } = __nccwpck_require__(329) +const util = __nccwpck_require__(7234) +const { addSignal, removeSignal } = __nccwpck_require__(2088) - return; +class ConnectHandler extends AsyncResource { + constructor (opts, callback) { + if (!opts || typeof opts !== 'object') { + throw new InvalidArgumentError('invalid opts') } - } - - var tempDir = _tempDir(); - var paramsFile = path.join(tempDir, common.randomFileName()); - var stderrFile = path.join(tempDir, common.randomFileName()); - var stdoutFile = path.join(tempDir, common.randomFileName()); - - opts = common.extend({ - silent: common.config.silent, - fatal: common.config.fatal, // TODO(nfischer): this and the line above are probably unnecessary - cwd: _pwd().toString(), - env: process.env, - maxBuffer: DEFAULT_MAXBUFFER_SIZE, - encoding: 'utf8', - }, opts); - if (fs.existsSync(paramsFile)) common.unlinkSync(paramsFile); - if (fs.existsSync(stderrFile)) common.unlinkSync(stderrFile); - if (fs.existsSync(stdoutFile)) common.unlinkSync(stdoutFile); + if (typeof callback !== 'function') { + throw new InvalidArgumentError('invalid callback') + } - opts.cwd = path.resolve(opts.cwd); + const { signal, opaque, responseHeaders } = opts - var paramsToSerialize = { - command: cmd, - execOptions: opts, - pipe, - stdoutFile, - stderrFile, - }; + if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { + throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') + } - // Create the files and ensure these are locked down (for read and write) to - // the current user. The main concerns here are: - // - // * If we execute a command which prints sensitive output, then - // stdoutFile/stderrFile must not be readable by other users. - // * paramsFile must not be readable by other users, or else they can read it - // to figure out the path for stdoutFile/stderrFile and create these first - // (locked down to their own access), which will crash exec() when it tries - // to write to the files. - function writeFileLockedDown(filePath, data) { - fs.writeFileSync(filePath, data, { - encoding: 'utf8', - mode: parseInt('600', 8), - }); - } - writeFileLockedDown(stdoutFile, ''); - writeFileLockedDown(stderrFile, ''); - writeFileLockedDown(paramsFile, JSON.stringify(paramsToSerialize)); + super('UNDICI_CONNECT') - var execArgs = [ - __nccwpck_require__.ab + "exec-child.js", - paramsFile, - ]; + this.opaque = opaque || null + this.responseHeaders = responseHeaders || null + this.callback = callback + this.abort = null - /* istanbul ignore else */ - if (opts.silent) { - opts.stdio = 'ignore'; - } else { - opts.stdio = [0, 1, 2]; + addSignal(this, signal) } - var code = 0; + onConnect (abort, context) { + if (this.reason) { + abort(this.reason) + return + } - // Welcome to the future - try { - // Bad things if we pass in a `shell` option to child_process.execFileSync, - // so we need to explicitly remove it here. - delete opts.shell; + assert(this.callback) - child.execFileSync(common.config.execPath, execArgs, opts); - } catch (e) { - // Commands with non-zero exit code raise an exception. - code = e.status || DEFAULT_ERROR_CODE; + this.abort = abort + this.context = context } - // fs.readFileSync uses buffer encoding by default, so call - // it without the encoding option if the encoding is 'buffer'. - // Also, if the exec timeout is too short for node to start up, - // the files will not be created, so these calls will throw. - var stdout = ''; - var stderr = ''; - if (opts.encoding === 'buffer') { - stdout = fs.readFileSync(stdoutFile); - stderr = fs.readFileSync(stderrFile); - } else { - stdout = fs.readFileSync(stdoutFile, opts.encoding); - stderr = fs.readFileSync(stderrFile, opts.encoding); + onHeaders () { + throw new SocketError('bad connect', null) } - // No biggie if we can't erase the files now -- they're in a temp dir anyway - // and we locked down permissions (see the note above). - try { common.unlinkSync(paramsFile); } catch (e) {} - try { common.unlinkSync(stderrFile); } catch (e) {} - try { common.unlinkSync(stdoutFile); } catch (e) {} + onUpgrade (statusCode, rawHeaders, socket) { + const { callback, opaque, context } = this - if (code !== 0) { - // Note: `silent` should be unconditionally true to avoid double-printing - // the command's stderr, and to avoid printing any stderr when the user has - // set `shell.config.silent`. - common.error(stderr, code, { continue: true, silent: true, fatal: opts.fatal }); - } - var obj = common.ShellString(stdout, stderr, code); - return obj; -} // execSync() + removeSignal(this) -// Wrapper around exec() to enable echoing output to console in real time -function execAsync(cmd, opts, pipe, callback) { - opts = common.extend({ - silent: common.config.silent, - fatal: common.config.fatal, // TODO(nfischer): this and the line above are probably unnecessary - cwd: _pwd().toString(), - env: process.env, - maxBuffer: DEFAULT_MAXBUFFER_SIZE, - encoding: 'utf8', - }, opts); + this.callback = null - var c = child.exec(cmd, opts, function (err, stdout, stderr) { - if (callback) { - if (!err) { - callback(0, stdout, stderr); - } else if (err.code === undefined) { - // See issue #536 - /* istanbul ignore next */ - callback(1, stdout, stderr); - } else { - callback(err.code, stdout, stderr); - } + let headers = rawHeaders + // Indicates is an HTTP2Session + if (headers != null) { + headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) } - }); - if (pipe) c.stdin.end(pipe); - - if (!opts.silent) { - c.stdout.pipe(process.stdout); - c.stderr.pipe(process.stderr); + this.runInAsyncScope(callback, null, null, { + statusCode, + headers, + socket, + opaque, + context + }) } - return c; -} - -//@ -//@ ### exec(command [, options] [, callback]) -//@ -//@ Available options: -//@ -//@ + `async`: Asynchronous execution. If a callback is provided, it will be set to -//@ `true`, regardless of the passed value (default: `false`). -//@ + `fatal`: Exit upon error (default: `false`). -//@ + `silent`: Do not echo program output to console (default: `false`). -//@ + `encoding`: Character encoding to use. Affects the values returned to stdout and stderr, and -//@ what is written to stdout and stderr when not in silent mode (default: `'utf8'`). -//@ + and any option available to Node.js's -//@ [`child_process.exec()`](https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback) -//@ -//@ Examples: -//@ -//@ ```javascript -//@ var version = exec('node --version', {silent:true}).stdout; -//@ -//@ var child = exec('some_long_running_process', {async:true}); -//@ child.stdout.on('data', function(data) { -//@ /* ... do something with data ... */ -//@ }); -//@ -//@ exec('some_long_running_process', function(code, stdout, stderr) { -//@ console.log('Exit code:', code); -//@ console.log('Program output:', stdout); -//@ console.log('Program stderr:', stderr); -//@ }); -//@ ``` -//@ -//@ Executes the given `command` _synchronously_, unless otherwise specified. -//@ When in synchronous mode, this returns a [ShellString](#shellstringstr). -//@ Otherwise, this returns the child process object, and the `callback` -//@ receives the arguments `(code, stdout, stderr)`. -//@ -//@ Not seeing the behavior you want? `exec()` runs everything through `sh` -//@ by default (or `cmd.exe` on Windows), which differs from `bash`. If you -//@ need bash-specific behavior, try out the `{shell: 'path/to/bash'}` option. -//@ -//@ **Security note:** as `shell.exec()` executes an arbitrary string in the -//@ system shell, it is **critical** to properly sanitize user input to avoid -//@ **command injection**. For more context, consult the [Security -//@ Guidelines](https://github.com/shelljs/shelljs/wiki/Security-guidelines). -function _exec(command, options, callback) { - options = options || {}; + onError (err) { + const { callback, opaque } = this - var pipe = common.readFromPipe(); + removeSignal(this) - // Callback is defined instead of options. - if (typeof options === 'function') { - callback = options; - options = { async: true }; + if (callback) { + this.callback = null + queueMicrotask(() => { + this.runInAsyncScope(callback, null, err, { opaque }) + }) + } } +} - // Callback is defined with options. - if (typeof options === 'object' && typeof callback === 'function') { - options.async = true; +function connect (opts, callback) { + if (callback === undefined) { + return new Promise((resolve, reject) => { + connect.call(this, opts, (err, data) => { + return err ? reject(err) : resolve(data) + }) + }) } - options = common.extend({ - silent: common.config.silent, - fatal: common.config.fatal, - async: false, - }, options); - - if (!command) { - try { - common.error('must specify command'); - } catch (e) { - if (options.fatal) { - throw e; - } - - return; + try { + const connectHandler = new ConnectHandler(opts, callback) + this.dispatch({ ...opts, method: 'CONNECT' }, connectHandler) + } catch (err) { + if (typeof callback !== 'function') { + throw err } - } - - if (options.async) { - return execAsync(command, options, pipe, callback); - } else { - return execSync(command, options, pipe); + const opaque = opts?.opaque + queueMicrotask(() => callback(err, { opaque })) } } -module.exports = _exec; + +module.exports = connect /***/ }), -/***/ 4145: +/***/ 8076: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -var path = __nccwpck_require__(6928); -var common = __nccwpck_require__(3311); -var _ls = __nccwpck_require__(1275); -common.register('find', _find, { - cmdOptions: { - 'L': 'link', - }, -}); -//@ -//@ ### find(path [, path ...]) -//@ ### find(path_array) -//@ -//@ Examples: -//@ -//@ ```javascript -//@ find('src', 'lib'); -//@ find(['src', 'lib']); // same as above -//@ find('.').filter(function(file) { return file.match(/\.js$/); }); -//@ ``` -//@ -//@ Returns a [ShellString](#shellstringstr) (with array-like properties) of all -//@ files (however deep) in the given paths. -//@ -//@ The main difference from `ls('-R', path)` is that the resulting file names -//@ include the base directories (e.g., `lib/resources/file1` instead of just `file1`). -function _find(options, paths) { - if (!paths) { - common.error('no path specified'); - } else if (typeof paths === 'string') { - paths = [].slice.call(arguments, 1); - } +const { + Readable, + Duplex, + PassThrough +} = __nccwpck_require__(7075) +const { + InvalidArgumentError, + InvalidReturnValueError, + RequestAbortedError +} = __nccwpck_require__(329) +const util = __nccwpck_require__(7234) +const { AsyncResource } = __nccwpck_require__(6698) +const { addSignal, removeSignal } = __nccwpck_require__(2088) +const assert = __nccwpck_require__(4589) - var list = []; +const kResume = Symbol('resume') - function pushFile(file) { - if (process.platform === 'win32') { - file = file.replace(/\\/g, '/'); - } - list.push(file); +class PipelineRequest extends Readable { + constructor () { + super({ autoDestroy: true }) + + this[kResume] = null } - // why not simply do `ls('-R', paths)`? because the output wouldn't give the base dirs - // to get the base dir in the output, we need instead `ls('-R', 'dir/*')` for every directory + _read () { + const { [kResume]: resume } = this - paths.forEach(function (file) { - var stat; - try { - stat = common.statFollowLinks(file); - } catch (e) { - common.error('no such file or directory: ' + file); + if (resume) { + this[kResume] = null + resume() } + } - pushFile(file); + _destroy (err, callback) { + this._read() - if (stat.isDirectory()) { - _ls({ recursive: true, all: true, link: options.link }, file).forEach(function (subfile) { - pushFile(path.join(file, subfile)); - }); - } - }); - - return list; -} -module.exports = _find; + callback(err) + } +} +class PipelineResponse extends Readable { + constructor (resume) { + super({ autoDestroy: true }) + this[kResume] = resume + } -/***/ }), + _read () { + this[kResume]() + } -/***/ 686: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + _destroy (err, callback) { + if (!err && !this._readableState.endEmitted) { + err = new RequestAbortedError() + } -var fs = __nccwpck_require__(9896); -var common = __nccwpck_require__(3311); + callback(err) + } +} -common.register('grep', _grep, { - globStart: 2, // don't glob-expand the regex - canReceivePipe: true, - cmdOptions: { - 'v': 'inverse', - 'l': 'nameOnly', - 'i': 'ignoreCase', - 'n': 'lineNumber', - 'B': 'beforeContext', - 'A': 'afterContext', - 'C': 'context', - }, -}); +class PipelineHandler extends AsyncResource { + constructor (opts, handler) { + if (!opts || typeof opts !== 'object') { + throw new InvalidArgumentError('invalid opts') + } -//@ -//@ ### grep([options,] regex_filter, file [, file ...]) -//@ ### grep([options,] regex_filter, file_array) -//@ -//@ Available options: -//@ -//@ + `-v`: Invert `regex_filter` (only print non-matching lines). -//@ + `-l`: Print only filenames of matching files. -//@ + `-i`: Ignore case. -//@ + `-n`: Print line numbers. -//@ + `-B `: Show `` lines before each result. -//@ + `-A `: Show `` lines after each result. -//@ + `-C `: Show `` lines before and after each result. -B and -A override this option. -//@ -//@ Examples: -//@ -//@ ```javascript -//@ grep('-v', 'GLOBAL_VARIABLE', '*.js'); -//@ grep('GLOBAL_VARIABLE', '*.js'); -//@ grep('-B', 3, 'GLOBAL_VARIABLE', '*.js'); -//@ grep({ '-B': 3 }, 'GLOBAL_VARIABLE', '*.js'); -//@ grep({ '-B': 3, '-C': 2 }, 'GLOBAL_VARIABLE', '*.js'); -//@ ``` -//@ -//@ Reads input string from given files and returns a -//@ [ShellString](#shellstringstr) containing all lines of the @ file that match -//@ the given `regex_filter`. -function _grep(options, regex, files) { - // Check if this is coming from a pipe - var pipe = common.readFromPipe(); + if (typeof handler !== 'function') { + throw new InvalidArgumentError('invalid handler') + } - if (!files && !pipe) common.error('no paths given', 2); + const { signal, method, opaque, onInfo, responseHeaders } = opts - var idx = 2; - var contextError = ': invalid context length argument'; - // If the option has been found but not read, copy value from arguments - if (options.beforeContext === true) { - idx = 3; - options.beforeContext = Number(arguments[1]); - if (options.beforeContext < 0) { - common.error(options.beforeContext + contextError, 2); - } - } - if (options.afterContext === true) { - idx = 3; - options.afterContext = Number(arguments[1]); - if (options.afterContext < 0) { - common.error(options.afterContext + contextError, 2); - } - } - if (options.context === true) { - idx = 3; - options.context = Number(arguments[1]); - if (options.context < 0) { - common.error(options.context + contextError, 2); + if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { + throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') } - } - // If before or after not given but context is, update values - if (typeof options.context === 'number') { - if (options.beforeContext === false) { - options.beforeContext = options.context; + + if (method === 'CONNECT') { + throw new InvalidArgumentError('invalid method') } - if (options.afterContext === false) { - options.afterContext = options.context; + + if (onInfo && typeof onInfo !== 'function') { + throw new InvalidArgumentError('invalid onInfo callback') } - } - regex = arguments[idx - 1]; - files = [].slice.call(arguments, idx); - if (pipe) { - files.unshift('-'); - } + super('UNDICI_PIPELINE') - var grep = []; - if (options.ignoreCase) { - regex = new RegExp(regex, 'i'); - } - files.forEach(function (file) { - if (!fs.existsSync(file) && file !== '-') { - common.error('no such file or directory: ' + file, 2, { continue: true }); - return; - } + this.opaque = opaque || null + this.responseHeaders = responseHeaders || null + this.handler = handler + this.abort = null + this.context = null + this.onInfo = onInfo || null - var contents = file === '-' ? pipe : fs.readFileSync(file, 'utf8'); - if (options.nameOnly) { - if (contents.match(regex)) { - grep.push(file); - } - } else { - var lines = contents.split('\n'); - var matches = []; + this.req = new PipelineRequest().on('error', util.nop) - lines.forEach(function (line, index) { - var matched = line.match(regex); - if ((options.inverse && !matched) || (!options.inverse && matched)) { - var lineNumber = index + 1; - var result = {}; - if (matches.length > 0) { - // If the last result intersects, combine them - var last = matches[matches.length - 1]; - var minimumLineNumber = Math.max( - 1, - lineNumber - options.beforeContext - 1, - ); - if ( - last.hasOwnProperty('' + lineNumber) || - last.hasOwnProperty('' + minimumLineNumber) - ) { - result = last; - } - } - result[lineNumber] = { - line, - match: true, - }; - if (options.beforeContext > 0) { - // Store the lines with their line numbers to check for overlap - lines - .slice(Math.max(index - options.beforeContext, 0), index) - .forEach(function (v, i, a) { - var lineNum = '' + (index - a.length + i + 1); - if (!result.hasOwnProperty(lineNum)) { - result[lineNum] = { line: v, match: false }; - } - }); - } - if (options.afterContext > 0) { - // Store the lines with their line numbers to check for overlap - lines - .slice( - index + 1, - Math.min(index + options.afterContext + 1, lines.length - 1), - ) - .forEach(function (v, i) { - var lineNum = '' + (index + 1 + i + 1); - if (!result.hasOwnProperty(lineNum)) { - result[lineNum] = { line: v, match: false }; - } - }); - } - // Only add the result if it's new - if (!matches.includes(result)) { - matches.push(result); - } - } - }); + this.ret = new Duplex({ + readableObjectMode: opts.objectMode, + autoDestroy: true, + read: () => { + const { body } = this - // Loop through the matches and add them to the output - Array.prototype.push.apply( - grep, - matches.map(function (result) { - return Object.entries(result) - .map(function (entry) { - var lineNumber = entry[0]; - var line = entry[1].line; - var match = entry[1].match; - return options.lineNumber - ? lineNumber + (match ? ':' : '-') + line - : line; - }) - .join('\n'); - }), - ); - } - }); + if (body?.resume) { + body.resume() + } + }, + write: (chunk, encoding, callback) => { + const { req } = this - if (grep.length === 0 && common.state.errorCode !== 2) { - // We didn't hit the error above, but pattern didn't match - common.error('', { silent: true }); - } + if (req.push(chunk, encoding) || req._readableState.destroyed) { + callback() + } else { + req[kResume] = callback + } + }, + destroy: (err, callback) => { + const { body, req, res, ret, abort } = this - var separator = '\n'; - if ( - typeof options.beforeContext === 'number' || - typeof options.afterContext === 'number' - ) { - separator = '\n--\n'; - } - return grep.join(separator) + '\n'; -} -module.exports = _grep; + if (!err && !ret._readableState.endEmitted) { + err = new RequestAbortedError() + } + if (abort && err) { + abort() + } -/***/ }), + util.destroy(body, err) + util.destroy(req, err) + util.destroy(res, err) -/***/ 9068: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + removeSignal(this) -var fs = __nccwpck_require__(9896); -var common = __nccwpck_require__(3311); + callback(err) + } + }).on('prefinish', () => { + const { req } = this -common.register('head', _head, { - canReceivePipe: true, - cmdOptions: { - 'n': 'numLines', - }, -}); + // Node < 15 does not call _final in same tick. + req.push(null) + }) -// Reads |numLines| lines or the entire file, whichever is less. -function readSomeLines(file, numLines) { - var buf = common.buffer(); - var bufLength = buf.length; - var bytesRead = bufLength; - var pos = 0; + this.res = null - var fdr = fs.openSync(file, 'r'); - var numLinesRead = 0; - var ret = ''; - while (bytesRead === bufLength && numLinesRead < numLines) { - bytesRead = fs.readSync(fdr, buf, 0, bufLength, pos); - var bufStr = buf.toString('utf8', 0, bytesRead); - numLinesRead += bufStr.split('\n').length - 1; - ret += bufStr; - pos += bytesRead; + addSignal(this, signal) } - fs.closeSync(fdr); - return ret; -} + onConnect (abort, context) { + const { ret, res } = this -//@ -//@ ### head([{'-n': \},] file [, file ...]) -//@ ### head([{'-n': \},] file_array) -//@ -//@ Available options: -//@ -//@ + `-n `: Show the first `` lines of the files -//@ -//@ Examples: -//@ -//@ ```javascript -//@ var str = head({'-n': 1}, 'file*.txt'); -//@ var str = head('file1', 'file2'); -//@ var str = head(['file1', 'file2']); // same as above -//@ ``` -//@ -//@ Read the start of a `file`. Returns a [ShellString](#shellstringstr). -function _head(options, files) { - var head = []; - var pipe = common.readFromPipe(); + if (this.reason) { + abort(this.reason) + return + } - if (!files && !pipe) common.error('no paths given'); + assert(!res, 'pipeline cannot be retried') + assert(!ret.destroyed) - var idx = 1; - if (options.numLines === true) { - idx = 2; - options.numLines = Number(arguments[1]); - } else if (options.numLines === false) { - options.numLines = 10; + this.abort = abort + this.context = context } - files = [].slice.call(arguments, idx); - if (pipe) { - files.unshift('-'); - } + onHeaders (statusCode, rawHeaders, resume) { + const { opaque, handler, context } = this - var shouldAppendNewline = false; - files.forEach(function (file) { - if (file !== '-') { - if (!fs.existsSync(file)) { - common.error('no such file or directory: ' + file, { continue: true }); - return; - } else if (common.statFollowLinks(file).isDirectory()) { - common.error("error reading '" + file + "': Is a directory", { - continue: true, - }); - return; + if (statusCode < 200) { + if (this.onInfo) { + const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) + this.onInfo({ statusCode, headers }) } + return } - var contents; - if (file === '-') { - contents = pipe; - } else if (options.numLines < 0) { - contents = fs.readFileSync(file, 'utf8'); - } else { - contents = readSomeLines(file, options.numLines); - } + this.res = new PipelineResponse(resume) - var lines = contents.split('\n'); - var hasTrailingNewline = (lines[lines.length - 1] === ''); - if (hasTrailingNewline) { - lines.pop(); + let body + try { + this.handler = null + const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) + body = this.runInAsyncScope(handler, null, { + statusCode, + headers, + opaque, + body: this.res, + context + }) + } catch (err) { + this.res.on('error', util.nop) + throw err } - shouldAppendNewline = (hasTrailingNewline || options.numLines < lines.length); - head = head.concat(lines.slice(0, options.numLines)); - }); - - if (shouldAppendNewline) { - head.push(''); // to add a trailing newline once we join - } - return head.join('\n'); -} -module.exports = _head; + if (!body || typeof body.on !== 'function') { + throw new InvalidReturnValueError('expected Readable') + } + body + .on('data', (chunk) => { + const { ret, body } = this -/***/ }), + if (!ret.push(chunk) && body.pause) { + body.pause() + } + }) + .on('error', (err) => { + const { ret } = this -/***/ 9011: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + util.destroy(ret, err) + }) + .on('end', () => { + const { ret } = this -var fs = __nccwpck_require__(9896); -var path = __nccwpck_require__(6928); -var common = __nccwpck_require__(3311); + ret.push(null) + }) + .on('close', () => { + const { ret } = this -common.register('ln', _ln, { - cmdOptions: { - 's': 'symlink', - 'f': 'force', - }, -}); + if (!ret._readableState.ended) { + util.destroy(ret, new RequestAbortedError()) + } + }) -//@ -//@ ### ln([options,] source, dest) -//@ -//@ Available options: -//@ -//@ + `-s`: symlink -//@ + `-f`: force -//@ -//@ Examples: -//@ -//@ ```javascript -//@ ln('file', 'newlink'); -//@ ln('-sf', 'file', 'existing'); -//@ ``` -//@ -//@ Links `source` to `dest`. Use `-f` to force the link, should `dest` already -//@ exist. Returns a [ShellString](#shellstringstr) indicating success or -//@ failure. -function _ln(options, source, dest) { - if (!source || !dest) { - common.error('Missing and/or '); + this.body = body } - source = String(source); - var sourcePath = path.normalize(source).replace(RegExp(path.sep + '$'), ''); - var isAbsolute = (path.resolve(source) === sourcePath); - dest = path.resolve(process.cwd(), String(dest)); - - if (fs.existsSync(dest)) { - if (!options.force) { - common.error('Destination file exists', { continue: true }); - } + onData (chunk) { + const { res } = this + return res.push(chunk) + } - fs.unlinkSync(dest); + onComplete (trailers) { + const { res } = this + res.push(null) } - if (options.symlink) { - var isWindows = process.platform === 'win32'; - var linkType = isWindows ? 'file' : null; - var resolvedSourcePath = isAbsolute ? sourcePath : path.resolve(process.cwd(), path.dirname(dest), source); - if (!fs.existsSync(resolvedSourcePath)) { - common.error('Source file does not exist', { continue: true }); - } else if (isWindows && common.statFollowLinks(resolvedSourcePath).isDirectory()) { - linkType = 'junction'; - } + onError (err) { + const { ret } = this + this.handler = null + util.destroy(ret, err) + } +} - try { - fs.symlinkSync(linkType === 'junction' ? resolvedSourcePath : source, dest, linkType); - } catch (err) { - common.error(err.message); - } - } else { - if (!fs.existsSync(source)) { - common.error('Source file does not exist', { continue: true }); - } - try { - fs.linkSync(source, dest); - } catch (err) { - common.error(err.message); - } +function pipeline (opts, handler) { + try { + const pipelineHandler = new PipelineHandler(opts, handler) + this.dispatch({ ...opts, body: pipelineHandler.req }, pipelineHandler) + return pipelineHandler.ret + } catch (err) { + return new PassThrough().destroy(err) } - return ''; } -module.exports = _ln; + +module.exports = pipeline /***/ }), -/***/ 1275: +/***/ 809: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -var path = __nccwpck_require__(6928); -var fs = __nccwpck_require__(9896); -var glob = __nccwpck_require__(7469); -var common = __nccwpck_require__(3311); -// glob patterns use the UNIX path seperator -var globPatternRecursive = '/**'; -common.register('ls', _ls, { - cmdOptions: { - 'R': 'recursive', - 'A': 'all', - 'L': 'link', - 'a': 'all_deprecated', - 'd': 'directory', - 'l': 'long', - }, -}); - -//@ -//@ ### ls([options,] [path, ...]) -//@ ### ls([options,] path_array) -//@ -//@ Available options: -//@ -//@ + `-R`: recursive -//@ + `-A`: all files (include files beginning with `.`, except for `.` and `..`) -//@ + `-L`: follow symlinks -//@ + `-d`: list directories themselves, not their contents -//@ + `-l`: provides more details for each file. Specifically, each file is -//@ represented by a structured object with separate fields for file -//@ metadata (see -//@ [`fs.Stats`](https://nodejs.org/api/fs.html#fs_class_fs_stats)). The -//@ return value also overrides `.toString()` to resemble `ls -l`'s -//@ output format for human readability, but programmatic usage should -//@ depend on the stable object format rather than the `.toString()` -//@ representation. -//@ -//@ Examples: -//@ -//@ ```javascript -//@ ls('projs/*.js'); -//@ ls('projs/**/*.js'); // Find all js files recursively in projs -//@ ls('-R', '/users/me', '/tmp'); -//@ ls('-R', ['/users/me', '/tmp']); // same as above -//@ ls('-l', 'file.txt'); // { name: 'file.txt', mode: 33188, nlink: 1, ...} -//@ ``` -//@ -//@ Returns a [ShellString](#shellstringstr) (with array-like properties) of all -//@ the files in the given `path`, or files in the current directory if no -//@ `path` is provided. -function _ls(options, paths) { - if (options.all_deprecated) { - // We won't support the -a option as it's hard to image why it's useful - // (it includes '.' and '..' in addition to '.*' files) - // For backwards compatibility we'll dump a deprecated message and proceed as before - common.log('ls: Option -a is deprecated. Use -A instead'); - options.all = true; - } - - if (!paths) { - paths = ['.']; - } else { - paths = [].slice.call(arguments, 1); - } - - var list = []; +const assert = __nccwpck_require__(4589) +const { Readable } = __nccwpck_require__(1201) +const { InvalidArgumentError, RequestAbortedError } = __nccwpck_require__(329) +const util = __nccwpck_require__(7234) +const { getResolveErrorBodyCallback } = __nccwpck_require__(3057) +const { AsyncResource } = __nccwpck_require__(6698) - function pushFile(abs, relName, stat) { - if (process.platform === 'win32') { - relName = relName.replace(/\\/g, '/'); - } - if (options.long) { - stat = stat || (options.link ? common.statFollowLinks(abs) : common.statNoFollowLinks(abs)); - list.push(addLsAttributes(relName, stat)); - } else { - // list.push(path.relative(rel || '.', file)); - list.push(relName); +class RequestHandler extends AsyncResource { + constructor (opts, callback) { + if (!opts || typeof opts !== 'object') { + throw new InvalidArgumentError('invalid opts') } - } - paths.forEach(function (p) { - var stat; + const { signal, method, opaque, body, onInfo, responseHeaders, throwOnError, highWaterMark } = opts try { - stat = options.link ? common.statFollowLinks(p) : common.statNoFollowLinks(p); - // follow links to directories by default - if (stat.isSymbolicLink()) { - /* istanbul ignore next */ - // workaround for https://github.com/shelljs/shelljs/issues/795 - // codecov seems to have a bug that miscalculate this block as uncovered. - // but according to nyc report this block does get covered. - try { - var _stat = common.statFollowLinks(p); - if (_stat.isDirectory()) { - stat = _stat; - } - } catch (_) {} // bad symlink, treat it like a file + if (typeof callback !== 'function') { + throw new InvalidArgumentError('invalid callback') } - } catch (e) { - common.error('no such file or directory: ' + p, 2, { continue: true }); - return; - } - - // If the stat succeeded - if (stat.isDirectory() && !options.directory) { - if (options.recursive) { - // use glob, because it's simple - glob.sync(p + globPatternRecursive, { - // These options are just to make fast-glob be compatible with POSIX - // (bash) wildcard behavior. - onlyFiles: false, - // These options depend on the cmdOptions provided to ls. - dot: options.all, - followSymbolicLinks: options.link, - }).forEach(function (item) { - // Glob pattern returns the directory itself and needs to be filtered out. - if (path.relative(p, item)) { - pushFile(item, path.relative(p, item)); - } - }); - } else if (options.all) { - // use fs.readdirSync, because it's fast - fs.readdirSync(p).forEach(function (item) { - pushFile(path.join(p, item), item); - }); - } else { - // use fs.readdirSync and then filter out secret files - fs.readdirSync(p).forEach(function (item) { - if (item[0] !== '.') { - pushFile(path.join(p, item), item); - } - }); + if (highWaterMark && (typeof highWaterMark !== 'number' || highWaterMark < 0)) { + throw new InvalidArgumentError('invalid highWaterMark') } - } else { - pushFile(p, p, stat); - } - }); - // Add methods, to make this more compatible with ShellStrings - return list; -} - -function addLsAttributes(pathName, stats) { - // Note: this object will contain more information than .toString() returns - stats.name = pathName; - stats.toString = function () { - // Return a string resembling unix's `ls -l` format - return [this.mode, this.nlink, this.uid, this.gid, this.size, this.mtime, this.name].join(' '); - }; - return stats; -} - -module.exports = _ls; + if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { + throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') + } + if (method === 'CONNECT') { + throw new InvalidArgumentError('invalid method') + } -/***/ }), + if (onInfo && typeof onInfo !== 'function') { + throw new InvalidArgumentError('invalid onInfo callback') + } -/***/ 2523: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + super('UNDICI_REQUEST') + } catch (err) { + if (util.isStream(body)) { + util.destroy(body.on('error', util.nop), err) + } + throw err + } -var fs = __nccwpck_require__(9896); -var path = __nccwpck_require__(6928); -var common = __nccwpck_require__(3311); + this.method = method + this.responseHeaders = responseHeaders || null + this.opaque = opaque || null + this.callback = callback + this.res = null + this.abort = null + this.body = body + this.trailers = {} + this.context = null + this.onInfo = onInfo || null + this.throwOnError = throwOnError + this.highWaterMark = highWaterMark + this.signal = signal + this.reason = null + this.removeAbortListener = null -common.register('mkdir', _mkdir, { - cmdOptions: { - 'p': 'fullpath', - }, -}); + if (util.isStream(body)) { + body.on('error', (err) => { + this.onError(err) + }) + } -// Recursively creates `dir` -function mkdirSyncRecursive(dir) { - var baseDir = path.dirname(dir); + if (this.signal) { + if (this.signal.aborted) { + this.reason = this.signal.reason ?? new RequestAbortedError() + } else { + this.removeAbortListener = util.addAbortListener(this.signal, () => { + this.reason = this.signal.reason ?? new RequestAbortedError() + if (this.res) { + util.destroy(this.res.on('error', util.nop), this.reason) + } else if (this.abort) { + this.abort(this.reason) + } - // Prevents some potential problems arising from malformed UNCs or - // insufficient permissions. - /* istanbul ignore next */ - if (baseDir === dir) { - common.error('dirname() failed: [' + dir + ']'); + if (this.removeAbortListener) { + this.res?.off('close', this.removeAbortListener) + this.removeAbortListener() + this.removeAbortListener = null + } + }) + } + } } - // Base dir does not exist, go recursive - if (!fs.existsSync(baseDir)) { - mkdirSyncRecursive(baseDir); - } + onConnect (abort, context) { + if (this.reason) { + abort(this.reason) + return + } - try { - // Base dir created, can create dir - fs.mkdirSync(dir, parseInt('0777', 8)); - } catch (e) { - // swallow error if dir already exists - if (e.code !== 'EEXIST' || common.statNoFollowLinks(dir).isFile()) { throw e; } + assert(this.callback) + + this.abort = abort + this.context = context } -} -//@ -//@ ### mkdir([options,] dir [, dir ...]) -//@ ### mkdir([options,] dir_array) -//@ -//@ Available options: -//@ -//@ + `-p`: full path (and create intermediate directories, if necessary) -//@ -//@ Examples: -//@ -//@ ```javascript -//@ mkdir('-p', '/tmp/a/b/c/d', '/tmp/e/f/g'); -//@ mkdir('-p', ['/tmp/a/b/c/d', '/tmp/e/f/g']); // same as above -//@ ``` -//@ -//@ Creates directories. Returns a [ShellString](#shellstringstr) indicating -//@ success or failure. -function _mkdir(options, dirs) { - if (!dirs) common.error('no paths given'); + onHeaders (statusCode, rawHeaders, resume, statusMessage) { + const { callback, opaque, abort, context, responseHeaders, highWaterMark } = this - if (typeof dirs === 'string') { - dirs = [].slice.call(arguments, 1); - } - // if it's array leave it as it is + const headers = responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) - dirs.forEach(function (dir) { - try { - var stat = common.statNoFollowLinks(dir); - if (!options.fullpath) { - common.error('path already exists: ' + dir, { continue: true }); - } else if (stat.isFile()) { - common.error('cannot create directory ' + dir + ': File exists', { continue: true }); + if (statusCode < 200) { + if (this.onInfo) { + this.onInfo({ statusCode, headers }) } - return; // skip dir - } catch (e) { - // do nothing + return } - // Base dir does not exist, and no -p option given - var baseDir = path.dirname(dir); - if (!fs.existsSync(baseDir) && !options.fullpath) { - common.error('no such file or directory: ' + baseDir, { continue: true }); - return; // skip dir + const parsedHeaders = responseHeaders === 'raw' ? util.parseHeaders(rawHeaders) : headers + const contentType = parsedHeaders['content-type'] + const contentLength = parsedHeaders['content-length'] + const res = new Readable({ + resume, + abort, + contentType, + contentLength: this.method !== 'HEAD' && contentLength + ? Number(contentLength) + : null, + highWaterMark + }) + + if (this.removeAbortListener) { + res.on('close', this.removeAbortListener) } - try { - if (options.fullpath) { - mkdirSyncRecursive(path.resolve(dir)); - } else { - fs.mkdirSync(dir, parseInt('0777', 8)); - } - } catch (e) { - var reason; - if (e.code === 'EACCES') { - reason = 'Permission denied'; - } else if (e.code === 'ENOTDIR' || e.code === 'ENOENT') { - reason = 'Not a directory'; + this.callback = null + this.res = res + if (callback !== null) { + if (this.throwOnError && statusCode >= 400) { + this.runInAsyncScope(getResolveErrorBodyCallback, null, + { callback, body: res, contentType, statusCode, statusMessage, headers } + ) } else { - /* istanbul ignore next */ - throw e; + this.runInAsyncScope(callback, null, null, { + statusCode, + headers, + trailers: this.trailers, + opaque, + body: res, + context + }) } - common.error('cannot create directory ' + dir + ': ' + reason, { continue: true }); } - }); - return ''; -} // man arraykdir -module.exports = _mkdir; - - -/***/ }), - -/***/ 4913: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -var fs = __nccwpck_require__(9896); -var path = __nccwpck_require__(6928); -var common = __nccwpck_require__(3311); -var cp = __nccwpck_require__(2981); -var rm = __nccwpck_require__(5595); - -common.register('mv', _mv, { - cmdOptions: { - 'f': '!no_force', - 'n': 'no_force', - }, -}); - -// Checks if cureent file was created recently -function checkRecentCreated(sources, index) { - var lookedSource = sources[index]; - return sources.slice(0, index).some(function (src) { - return path.basename(src) === path.basename(lookedSource); - }); -} - -//@ -//@ ### mv([options ,] source [, source ...], dest') -//@ ### mv([options ,] source_array, dest') -//@ -//@ Available options: -//@ -//@ + `-f`: force (default behavior) -//@ + `-n`: no-clobber -//@ -//@ Examples: -//@ -//@ ```javascript -//@ mv('-n', 'file', 'dir/'); -//@ mv('file1', 'file2', 'dir/'); -//@ mv(['file1', 'file2'], 'dir/'); // same as above -//@ ``` -//@ -//@ Moves `source` file(s) to `dest`. Returns a [ShellString](#shellstringstr) -//@ indicating success or failure. -function _mv(options, sources, dest) { - // Get sources, dest - if (arguments.length < 3) { - common.error('missing and/or '); - } else if (arguments.length > 3) { - sources = [].slice.call(arguments, 1, arguments.length - 1); - dest = arguments[arguments.length - 1]; - } else if (typeof sources === 'string') { - sources = [sources]; - } else { - // TODO(nate): figure out if we actually need this line - common.error('invalid arguments'); } - var exists = fs.existsSync(dest); - var stats = exists && common.statFollowLinks(dest); - - // Dest is not existing dir, but multiple sources given - if ((!exists || !stats.isDirectory()) && sources.length > 1) { - common.error('dest is not a directory (too many sources)'); + onData (chunk) { + return this.res.push(chunk) } - // Dest is an existing file, but no -f given - if (exists && stats.isFile() && options.no_force) { - common.error('dest file already exists: ' + dest); + onComplete (trailers) { + util.parseHeaders(trailers, this.trailers) + this.res.push(null) } - sources.forEach(function (src, srcIndex) { - if (!fs.existsSync(src)) { - common.error('no such file or directory: ' + src, { continue: true }); - return; // skip file - } - - // If here, src exists + onError (err) { + const { res, callback, body, opaque } = this - // When copying to '/path/dir': - // thisDest = '/path/dir/file1' - var thisDest = dest; - if (fs.existsSync(dest) && common.statFollowLinks(dest).isDirectory()) { - thisDest = path.normalize(dest + '/' + path.basename(src)); + if (callback) { + // TODO: Does this need queueMicrotask? + this.callback = null + queueMicrotask(() => { + this.runInAsyncScope(callback, null, err, { opaque }) + }) } - var thisDestExists = fs.existsSync(thisDest); - - if (thisDestExists && checkRecentCreated(sources, srcIndex)) { - // cannot overwrite file created recently in current execution, but we want to continue copying other files - if (!options.no_force) { - common.error("will not overwrite just-created '" + thisDest + "' with '" + src + "'", { continue: true }); - } - return; + if (res) { + this.res = null + // Ensure all queued handlers are invoked before destroying res. + queueMicrotask(() => { + util.destroy(res, err) + }) } - if (fs.existsSync(thisDest) && options.no_force) { - common.error('dest file already exists: ' + thisDest, { continue: true }); - return; // skip file + if (body) { + this.body = null + util.destroy(body, err) } - if (path.resolve(src) === path.dirname(path.resolve(thisDest))) { - common.error('cannot move to self: ' + src, { continue: true }); - return; // skip file + if (this.removeAbortListener) { + res?.off('close', this.removeAbortListener) + this.removeAbortListener() + this.removeAbortListener = null } + } +} - try { - fs.renameSync(src, thisDest); - } catch (e) { - /* istanbul ignore next */ - if (e.code === 'EXDEV') { - // If we're trying to `mv` to an external partition, we'll actually need - // to perform a copy and then clean up the original file. If either the - // copy or the rm fails with an exception, we should allow this - // exception to pass up to the top level. - cp({ recursive: true }, src, thisDest); - rm({ recursive: true, force: true }, src); - } +function request (opts, callback) { + if (callback === undefined) { + return new Promise((resolve, reject) => { + request.call(this, opts, (err, data) => { + return err ? reject(err) : resolve(data) + }) + }) + } + + try { + this.dispatch(opts, new RequestHandler(opts, callback)) + } catch (err) { + if (typeof callback !== 'function') { + throw err } - }); // forEach(src) - return ''; -} // mv -module.exports = _mv; + const opaque = opts?.opaque + queueMicrotask(() => callback(err, { opaque })) + } +} + +module.exports = request +module.exports.RequestHandler = RequestHandler /***/ }), -/***/ 391: -/***/ (() => { +/***/ 74: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -// see dirs.js -/***/ }), +const assert = __nccwpck_require__(4589) +const { finished, PassThrough } = __nccwpck_require__(7075) +const { InvalidArgumentError, InvalidReturnValueError } = __nccwpck_require__(329) +const util = __nccwpck_require__(7234) +const { getResolveErrorBodyCallback } = __nccwpck_require__(3057) +const { AsyncResource } = __nccwpck_require__(6698) +const { addSignal, removeSignal } = __nccwpck_require__(2088) -/***/ 500: -/***/ (() => { +class StreamHandler extends AsyncResource { + constructor (opts, factory, callback) { + if (!opts || typeof opts !== 'object') { + throw new InvalidArgumentError('invalid opts') + } -// see dirs.js + const { signal, method, opaque, body, onInfo, responseHeaders, throwOnError } = opts + try { + if (typeof callback !== 'function') { + throw new InvalidArgumentError('invalid callback') + } -/***/ }), + if (typeof factory !== 'function') { + throw new InvalidArgumentError('invalid factory') + } -/***/ 4879: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { + throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') + } -var path = __nccwpck_require__(6928); -var common = __nccwpck_require__(3311); + if (method === 'CONNECT') { + throw new InvalidArgumentError('invalid method') + } -common.register('pwd', _pwd, { - allowGlobbing: false, -}); + if (onInfo && typeof onInfo !== 'function') { + throw new InvalidArgumentError('invalid onInfo callback') + } -//@ -//@ ### pwd() -//@ -//@ Returns the current directory as a [ShellString](#shellstringstr). -function _pwd() { - var pwd = path.resolve(process.cwd()); - return pwd; -} -module.exports = _pwd; + super('UNDICI_STREAM') + } catch (err) { + if (util.isStream(body)) { + util.destroy(body.on('error', util.nop), err) + } + throw err + } + this.responseHeaders = responseHeaders || null + this.opaque = opaque || null + this.factory = factory + this.callback = callback + this.res = null + this.abort = null + this.context = null + this.trailers = null + this.body = body + this.onInfo = onInfo || null + this.throwOnError = throwOnError || false -/***/ }), + if (util.isStream(body)) { + body.on('error', (err) => { + this.onError(err) + }) + } -/***/ 5595: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + addSignal(this, signal) + } -var fs = __nccwpck_require__(9896); -var common = __nccwpck_require__(3311); + onConnect (abort, context) { + if (this.reason) { + abort(this.reason) + return + } -common.register('rm', _rm, { - cmdOptions: { - 'f': 'force', - 'r': 'recursive', - 'R': 'recursive', - }, -}); + assert(this.callback) -// Recursively removes 'dir' -// Adapted from https://github.com/ryanmcgrath/wrench-js -// -// Copyright (c) 2010 Ryan McGrath -// Copyright (c) 2012 Artur Adib -// -// Licensed under the MIT License -// http://www.opensource.org/licenses/mit-license.php -function rmdirSyncRecursive(dir, force, fromSymlink) { - var files; + this.abort = abort + this.context = context + } - files = fs.readdirSync(dir); + onHeaders (statusCode, rawHeaders, resume, statusMessage) { + const { factory, opaque, context, callback, responseHeaders } = this - // Loop through and delete everything in the sub-tree after checking it - for (var i = 0; i < files.length; i++) { - var file = dir + '/' + files[i]; - var currFile = common.statNoFollowLinks(file); + const headers = responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) - if (currFile.isDirectory()) { // Recursive function back to the beginning - rmdirSyncRecursive(file, force); - } else if (force || isWriteable(file)) { - // Assume it's a file - perhaps a try/catch belongs here? - try { - common.unlinkSync(file); - } catch (e) { - /* istanbul ignore next */ - common.error('could not remove file (code ' + e.code + '): ' + file, { - continue: true, - }); + if (statusCode < 200) { + if (this.onInfo) { + this.onInfo({ statusCode, headers }) } + return } - } - // if was directory was referenced through a symbolic link, - // the contents should be removed, but not the directory itself - if (fromSymlink) return; + this.factory = null - // Now that we know everything in the sub-tree has been deleted, we can delete the main directory. - // Huzzah for the shopkeep. + let res - var result; - try { - // Retry on windows, sometimes it takes a little time before all the files in the directory are gone - var start = Date.now(); + if (this.throwOnError && statusCode >= 400) { + const parsedHeaders = responseHeaders === 'raw' ? util.parseHeaders(rawHeaders) : headers + const contentType = parsedHeaders['content-type'] + res = new PassThrough() - // TODO: replace this with a finite loop - for (;;) { - try { - result = fs.rmdirSync(dir); - if (fs.existsSync(dir)) throw { code: 'EAGAIN' }; - break; - } catch (er) { - /* istanbul ignore next */ - // In addition to error codes, also check if the directory still exists and loop again if true - if (process.platform === 'win32' && (er.code === 'ENOTEMPTY' || er.code === 'EBUSY' || er.code === 'EPERM' || er.code === 'EAGAIN')) { - if (Date.now() - start > 1000) throw er; - } else if (er.code === 'ENOENT') { - // Directory did not exist, deletion was successful - break; - } else { - throw er; - } + this.callback = null + this.runInAsyncScope(getResolveErrorBodyCallback, null, + { callback, body: res, contentType, statusCode, statusMessage, headers } + ) + } else { + if (factory === null) { + return + } + + res = this.runInAsyncScope(factory, null, { + statusCode, + headers, + opaque, + context + }) + + if ( + !res || + typeof res.write !== 'function' || + typeof res.end !== 'function' || + typeof res.on !== 'function' + ) { + throw new InvalidReturnValueError('expected Writable') } + + // TODO: Avoid finished. It registers an unnecessary amount of listeners. + finished(res, { readable: false }, (err) => { + const { callback, res, opaque, trailers, abort } = this + + this.res = null + if (err || !res.readable) { + util.destroy(res, err) + } + + this.callback = null + this.runInAsyncScope(callback, null, err || null, { opaque, trailers }) + + if (err) { + abort() + } + }) } - } catch (e) { - common.error('could not remove directory (code ' + e.code + '): ' + dir, { continue: true }); + + res.on('drain', resume) + + this.res = res + + const needDrain = res.writableNeedDrain !== undefined + ? res.writableNeedDrain + : res._writableState?.needDrain + + return needDrain !== true } - return result; -} // rmdirSyncRecursive + onData (chunk) { + const { res } = this -// Hack to determine if file has write permissions for current user -// Avoids having to check user, group, etc, but it's probably slow -function isWriteable(file) { - var writePermission = true; - try { - var __fd = fs.openSync(file, 'a'); - fs.closeSync(__fd); - } catch (e) { - writePermission = false; + return res ? res.write(chunk) : true } - return writePermission; -} + onComplete (trailers) { + const { res } = this -function handleFile(file, options) { - if (options.force || isWriteable(file)) { - // -f was passed, or file is writable, so it can be removed - common.unlinkSync(file); - } else { - common.error('permission denied: ' + file, { continue: true }); + removeSignal(this) + + if (!res) { + return + } + + this.trailers = util.parseHeaders(trailers) + + res.end() } -} -function handleDirectory(file, options) { - if (options.recursive) { - // -r was passed, so directory can be removed - rmdirSyncRecursive(file, options.force); - } else { - common.error('path is a directory', { continue: true }); + onError (err) { + const { res, callback, opaque, body } = this + + removeSignal(this) + + this.factory = null + + if (res) { + this.res = null + util.destroy(res, err) + } else if (callback) { + this.callback = null + queueMicrotask(() => { + this.runInAsyncScope(callback, null, err, { opaque }) + }) + } + + if (body) { + this.body = null + util.destroy(body, err) + } } } -function handleSymbolicLink(file, options) { - var stats; - try { - stats = common.statFollowLinks(file); - } catch (e) { - // symlink is broken, so remove the symlink itself - common.unlinkSync(file); - return; +function stream (opts, factory, callback) { + if (callback === undefined) { + return new Promise((resolve, reject) => { + stream.call(this, opts, factory, (err, data) => { + return err ? reject(err) : resolve(data) + }) + }) } - if (stats.isFile()) { - common.unlinkSync(file); - } else if (stats.isDirectory()) { - if (file[file.length - 1] === '/') { - // trailing separator, so remove the contents, not the link - if (options.recursive) { - // -r was passed, so directory can be removed - var fromSymlink = true; - rmdirSyncRecursive(file, options.force, fromSymlink); - } else { - common.error('path is a directory', { continue: true }); - } - } else { - // no trailing separator, so remove the link - common.unlinkSync(file); + try { + this.dispatch(opts, new StreamHandler(opts, factory, callback)) + } catch (err) { + if (typeof callback !== 'function') { + throw err } + const opaque = opts?.opaque + queueMicrotask(() => callback(err, { opaque })) } } -function handleFIFO(file) { - common.unlinkSync(file); -} +module.exports = stream -//@ -//@ ### rm([options,] file [, file ...]) -//@ ### rm([options,] file_array) -//@ -//@ Available options: -//@ -//@ + `-f`: force -//@ + `-r, -R`: recursive -//@ -//@ Examples: -//@ -//@ ```javascript -//@ rm('-rf', '/tmp/*'); -//@ rm('some_file.txt', 'another_file.txt'); -//@ rm(['some_file.txt', 'another_file.txt']); // same as above -//@ ``` -//@ -//@ Removes files. Returns a [ShellString](#shellstringstr) indicating success -//@ or failure. -function _rm(options, files) { - if (!files) common.error('no paths given'); - // Convert to array - files = [].slice.call(arguments, 1); +/***/ }), - files.forEach(function (file) { - var lstats; - try { - var filepath = (file[file.length - 1] === '/') - ? file.slice(0, -1) // remove the '/' so lstatSync can detect symlinks - : file; - lstats = common.statNoFollowLinks(filepath); // test for existence - } catch (e) { - // Path does not exist, no force flag given - if (!options.force) { - common.error('no such file or directory: ' + file, { continue: true }); - } - return; // skip file - } +/***/ 8648: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - // If here, path exists - if (lstats.isFile()) { - handleFile(file, options); - } else if (lstats.isDirectory()) { - handleDirectory(file, options); - } else if (lstats.isSymbolicLink()) { - handleSymbolicLink(file, options); - } else if (lstats.isFIFO()) { - handleFIFO(file); + + +const { InvalidArgumentError, SocketError } = __nccwpck_require__(329) +const { AsyncResource } = __nccwpck_require__(6698) +const util = __nccwpck_require__(7234) +const { addSignal, removeSignal } = __nccwpck_require__(2088) +const assert = __nccwpck_require__(4589) + +class UpgradeHandler extends AsyncResource { + constructor (opts, callback) { + if (!opts || typeof opts !== 'object') { + throw new InvalidArgumentError('invalid opts') } - }); // forEach(file) - return ''; -} // rm -module.exports = _rm; + if (typeof callback !== 'function') { + throw new InvalidArgumentError('invalid callback') + } -/***/ }), + const { signal, opaque, responseHeaders } = opts -/***/ 3548: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { + throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') + } -var fs = __nccwpck_require__(9896); -var common = __nccwpck_require__(3311); + super('UNDICI_UPGRADE') -common.register('sed', _sed, { - globStart: 3, // don't glob-expand regexes - canReceivePipe: true, - cmdOptions: { - 'i': 'inplace', - }, -}); + this.responseHeaders = responseHeaders || null + this.opaque = opaque || null + this.callback = callback + this.abort = null + this.context = null -//@ -//@ ### sed([options,] search_regex, replacement, file [, file ...]) -//@ ### sed([options,] search_regex, replacement, file_array) -//@ -//@ Available options: -//@ -//@ + `-i`: Replace contents of `file` in-place. _Note that no backups will be created!_ -//@ -//@ Examples: -//@ -//@ ```javascript -//@ sed('-i', 'PROGRAM_VERSION', 'v0.1.3', 'source.js'); -//@ ``` -//@ -//@ Reads an input string from `file`s, line by line, and performs a JavaScript `replace()` on -//@ each of the lines from the input string using the given `search_regex` and `replacement` string or -//@ function. Returns the new [ShellString](#shellstringstr) after replacement. -//@ -//@ Note: -//@ -//@ Like unix `sed`, ShellJS `sed` supports capture groups. Capture groups are specified -//@ using the `$n` syntax: -//@ -//@ ```javascript -//@ sed(/(\w+)\s(\w+)/, '$2, $1', 'file.txt'); -//@ ``` -//@ -//@ Also, like unix `sed`, ShellJS `sed` runs replacements on each line from the input file -//@ (split by '\n') separately, so `search_regex`es that span more than one line (or include '\n') -//@ will not match anything and nothing will be replaced. -function _sed(options, regex, replacement, files) { - // Check if this is coming from a pipe - var pipe = common.readFromPipe(); + addSignal(this, signal) + } - if (typeof replacement !== 'string' && typeof replacement !== 'function') { - if (typeof replacement === 'number') { - replacement = replacement.toString(); // fallback - } else { - common.error('invalid replacement string'); + onConnect (abort, context) { + if (this.reason) { + abort(this.reason) + return } - } - // Convert all search strings to RegExp - if (typeof regex === 'string') { - regex = RegExp(regex); + assert(this.callback) + + this.abort = abort + this.context = null } - if (!files && !pipe) { - common.error('no files given'); + onHeaders () { + throw new SocketError('bad upgrade', null) } - files = [].slice.call(arguments, 3); + onUpgrade (statusCode, rawHeaders, socket) { + assert(statusCode === 101) - if (pipe) { - files.unshift('-'); - } + const { callback, opaque, context } = this - var sed = []; - files.forEach(function (file) { - if (!fs.existsSync(file) && file !== '-') { - common.error('no such file or directory: ' + file, 2, { continue: true }); - return; - } + removeSignal(this) - var contents = file === '-' ? pipe : fs.readFileSync(file, 'utf8'); - var lines = contents.split('\n'); - var result = lines.map(function (line) { - return line.replace(regex, replacement); - }).join('\n'); + this.callback = null + const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) + this.runInAsyncScope(callback, null, null, { + headers, + socket, + opaque, + context + }) + } - sed.push(result); + onError (err) { + const { callback, opaque } = this - if (options.inplace) { - fs.writeFileSync(file, result, 'utf8'); + removeSignal(this) + + if (callback) { + this.callback = null + queueMicrotask(() => { + this.runInAsyncScope(callback, null, err, { opaque }) + }) } - }); + } +} - if (options.inplace) { - return ''; - } else { - return sed.join('\n'); +function upgrade (opts, callback) { + if (callback === undefined) { + return new Promise((resolve, reject) => { + upgrade.call(this, opts, (err, data) => { + return err ? reject(err) : resolve(data) + }) + }) + } + + try { + const upgradeHandler = new UpgradeHandler(opts, callback) + this.dispatch({ + ...opts, + method: opts.method || 'GET', + upgrade: opts.protocol || 'Websocket' + }, upgradeHandler) + } catch (err) { + if (typeof callback !== 'function') { + throw err + } + const opaque = opts?.opaque + queueMicrotask(() => callback(err, { opaque })) } } -module.exports = _sed; + +module.exports = upgrade /***/ }), -/***/ 2652: +/***/ 3609: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -var common = __nccwpck_require__(3311); -common.register('set', _set, { - allowGlobbing: false, - wrapOutput: false, -}); -//@ -//@ ### set(options) -//@ -//@ Available options: -//@ -//@ + `+/-e`: exit upon error (`config.fatal`) -//@ + `+/-v`: verbose: show all commands (`config.verbose`) -//@ + `+/-f`: disable filename expansion (globbing) -//@ -//@ Examples: -//@ -//@ ```javascript -//@ set('-e'); // exit upon first error -//@ set('+e'); // this undoes a "set('-e')" -//@ ``` -//@ -//@ Sets global configuration variables. -function _set(options) { - if (!options) { - var args = [].slice.call(arguments, 0); - if (args.length < 2) common.error('must provide an argument'); - options = args[1]; - } - var negate = (options[0] === '+'); - if (negate) { - options = '-' + options.slice(1); // parseOptions needs a '-' prefix - } - options = common.parseOptions(options, { - 'e': 'fatal', - 'v': 'verbose', - 'f': 'noglob', - }); - - if (negate) { - Object.keys(options).forEach(function (key) { - options[key] = !options[key]; - }); - } - - Object.keys(options).forEach(function (key) { - // Only change the global config if `negate` is false and the option is true - // or if `negate` is true and the option is false (aka negate !== option) - if (negate !== options[key]) { - common.config[key] = options[key]; - } - }); -} -module.exports = _set; +module.exports.request = __nccwpck_require__(809) +module.exports.stream = __nccwpck_require__(74) +module.exports.pipeline = __nccwpck_require__(8076) +module.exports.upgrade = __nccwpck_require__(8648) +module.exports.connect = __nccwpck_require__(3846) /***/ }), -/***/ 289: +/***/ 1201: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -var fs = __nccwpck_require__(9896); -var common = __nccwpck_require__(3311); +// Ported from https://github.com/nodejs/undici/pull/907 -common.register('sort', _sort, { - canReceivePipe: true, - cmdOptions: { - 'r': 'reverse', - 'n': 'numerical', - }, -}); -// parse out the number prefix of a line -function parseNumber(str) { - var match = str.match(/^\s*(\d*)\s*(.*)$/); - return { num: Number(match[1]), value: match[2] }; -} -// compare two strings case-insensitively, but examine case for strings that are -// case-insensitive equivalent -function unixCmp(a, b) { - var aLower = a.toLowerCase(); - var bLower = b.toLowerCase(); - return (aLower === bLower ? - -1 * a.localeCompare(b) : // unix sort treats case opposite how javascript does - aLower.localeCompare(bLower)); -} +const assert = __nccwpck_require__(4589) +const { Readable } = __nccwpck_require__(7075) +const { RequestAbortedError, NotSupportedError, InvalidArgumentError, AbortError } = __nccwpck_require__(329) +const util = __nccwpck_require__(7234) +const { ReadableStreamFrom } = __nccwpck_require__(7234) -// compare two strings in the fashion that unix sort's -n option works -function numericalCmp(a, b) { - var objA = parseNumber(a); - var objB = parseNumber(b); - if (objA.hasOwnProperty('num') && objB.hasOwnProperty('num')) { - return ((objA.num !== objB.num) ? - (objA.num - objB.num) : - unixCmp(objA.value, objB.value)); - } else { - return unixCmp(objA.value, objB.value); - } -} +const kConsume = Symbol('kConsume') +const kReading = Symbol('kReading') +const kBody = Symbol('kBody') +const kAbort = Symbol('kAbort') +const kContentType = Symbol('kContentType') +const kContentLength = Symbol('kContentLength') -//@ -//@ ### sort([options,] file [, file ...]) -//@ ### sort([options,] file_array) -//@ -//@ Available options: -//@ -//@ + `-r`: Reverse the results -//@ + `-n`: Compare according to numerical value -//@ -//@ Examples: -//@ -//@ ```javascript -//@ sort('foo.txt', 'bar.txt'); -//@ sort('-r', 'foo.txt'); -//@ ``` -//@ -//@ Return the contents of the `file`s, sorted line-by-line as a -//@ [ShellString](#shellstringstr). Sorting multiple files mixes their content -//@ (just as unix `sort` does). -function _sort(options, files) { - // Check if this is coming from a pipe - var pipe = common.readFromPipe(); +const noop = () => {} - if (!files && !pipe) common.error('no files given'); +class BodyReadable extends Readable { + constructor ({ + resume, + abort, + contentType = '', + contentLength, + highWaterMark = 64 * 1024 // Same as nodejs fs streams. + }) { + super({ + autoDestroy: true, + read: resume, + highWaterMark + }) - files = [].slice.call(arguments, 1); + this._readableState.dataEmitted = false - if (pipe) { - files.unshift('-'); + this[kAbort] = abort + this[kConsume] = null + this[kBody] = null + this[kContentType] = contentType + this[kContentLength] = contentLength + + // Is stream being consumed through Readable API? + // This is an optimization so that we avoid checking + // for 'data' and 'readable' listeners in the hot path + // inside push(). + this[kReading] = false } - var lines = files.reduce(function (accum, file) { - if (file !== '-') { - if (!fs.existsSync(file)) { - common.error('no such file or directory: ' + file, { continue: true }); - return accum; - } else if (common.statFollowLinks(file).isDirectory()) { - common.error('read failed: ' + file + ': Is a directory', { - continue: true, - }); - return accum; - } + destroy (err) { + if (!err && !this._readableState.endEmitted) { + err = new RequestAbortedError() } - var contents = file === '-' ? pipe : fs.readFileSync(file, 'utf8'); - return accum.concat(contents.trimRight().split('\n')); - }, []); + if (err) { + this[kAbort]() + } - var sorted = lines.sort(options.numerical ? numericalCmp : unixCmp); + return super.destroy(err) + } - if (options.reverse) { - sorted = sorted.reverse(); + _destroy (err, callback) { + // Workaround for Node "bug". If the stream is destroyed in same + // tick as it is created, then a user who is waiting for a + // promise (i.e micro tick) for installing a 'error' listener will + // never get a chance and will always encounter an unhandled exception. + if (!this[kReading]) { + setImmediate(() => { + callback(err) + }) + } else { + callback(err) + } } - return sorted.join('\n') + '\n'; -} + on (ev, ...args) { + if (ev === 'data' || ev === 'readable') { + this[kReading] = true + } + return super.on(ev, ...args) + } -module.exports = _sort; + addListener (ev, ...args) { + return this.on(ev, ...args) + } + off (ev, ...args) { + const ret = super.off(ev, ...args) + if (ev === 'data' || ev === 'readable') { + this[kReading] = ( + this.listenerCount('data') > 0 || + this.listenerCount('readable') > 0 + ) + } + return ret + } -/***/ }), + removeListener (ev, ...args) { + return this.off(ev, ...args) + } -/***/ 6588: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + push (chunk) { + if (this[kConsume] && chunk !== null) { + consumePush(this[kConsume], chunk) + return this[kReading] ? super.push(chunk) : true + } + return super.push(chunk) + } -var fs = __nccwpck_require__(9896); -var common = __nccwpck_require__(3311); + // https://fetch.spec.whatwg.org/#dom-body-text + async text () { + return consume(this, 'text') + } -common.register('tail', _tail, { - canReceivePipe: true, - cmdOptions: { - 'n': 'numLines', - }, -}); + // https://fetch.spec.whatwg.org/#dom-body-json + async json () { + return consume(this, 'json') + } -//@ -//@ ### tail([{'-n': \},] file [, file ...]) -//@ ### tail([{'-n': \},] file_array) -//@ -//@ Available options: -//@ -//@ + `-n `: Show the last `` lines of `file`s -//@ -//@ Examples: -//@ -//@ ```javascript -//@ var str = tail({'-n': 1}, 'file*.txt'); -//@ var str = tail('file1', 'file2'); -//@ var str = tail(['file1', 'file2']); // same as above -//@ ``` -//@ -//@ Read the end of a `file`. Returns a [ShellString](#shellstringstr). -function _tail(options, files) { - var tail = []; - var pipe = common.readFromPipe(); + // https://fetch.spec.whatwg.org/#dom-body-blob + async blob () { + return consume(this, 'blob') + } - if (!files && !pipe) common.error('no paths given'); + // https://fetch.spec.whatwg.org/#dom-body-bytes + async bytes () { + return consume(this, 'bytes') + } - var idx = 1; - var plusOption = false; - if (options.numLines === true) { - idx = 2; - if (arguments[1][0] === '+') { - plusOption = true; - } - options.numLines = Number(arguments[1]); - } else if (options.numLines === false) { - options.numLines = 10; + // https://fetch.spec.whatwg.org/#dom-body-arraybuffer + async arrayBuffer () { + return consume(this, 'arrayBuffer') } - // arguments[0] is a json object - if (arguments[0].numLines[0] === '+') { - plusOption = true; + + // https://fetch.spec.whatwg.org/#dom-body-formdata + async formData () { + // TODO: Implement. + throw new NotSupportedError() } - options.numLines = -1 * Math.abs(options.numLines); - files = [].slice.call(arguments, idx); - if (pipe) { - files.unshift('-'); + // https://fetch.spec.whatwg.org/#dom-body-bodyused + get bodyUsed () { + return util.isDisturbed(this) } - var shouldAppendNewline = false; - files.forEach(function (file) { - if (file !== '-') { - if (!fs.existsSync(file)) { - common.error('no such file or directory: ' + file, { continue: true }); - return; - } else if (common.statFollowLinks(file).isDirectory()) { - common.error("error reading '" + file + "': Is a directory", { - continue: true, - }); - return; + // https://fetch.spec.whatwg.org/#dom-body-body + get body () { + if (!this[kBody]) { + this[kBody] = ReadableStreamFrom(this) + if (this[kConsume]) { + // TODO: Is this the best way to force a lock? + this[kBody].getReader() // Ensure stream is locked. + assert(this[kBody].locked) } } + return this[kBody] + } - var contents = file === '-' ? pipe : fs.readFileSync(file, 'utf8'); + async dump (opts) { + let limit = Number.isFinite(opts?.limit) ? opts.limit : 128 * 1024 + const signal = opts?.signal - var lines = contents.split('\n'); - if (lines[lines.length - 1] === '') { - lines.pop(); - shouldAppendNewline = true; - } else { - shouldAppendNewline = false; + if (signal != null && (typeof signal !== 'object' || !('aborted' in signal))) { + throw new InvalidArgumentError('signal must be an AbortSignal') } - tail = tail.concat(plusOption ? lines.slice(-options.numLines - 1) : lines.slice(options.numLines)); - }); + signal?.throwIfAborted() - if (shouldAppendNewline) { - tail.push(''); // to add a trailing newline once we join + if (this._readableState.closeEmitted) { + return null + } + + return await new Promise((resolve, reject) => { + if (this[kContentLength] > limit) { + this.destroy(new AbortError()) + } + + const onAbort = () => { + this.destroy(signal.reason ?? new AbortError()) + } + signal?.addEventListener('abort', onAbort) + + this + .on('close', function () { + signal?.removeEventListener('abort', onAbort) + if (signal?.aborted) { + reject(signal.reason ?? new AbortError()) + } else { + resolve(null) + } + }) + .on('error', noop) + .on('data', function (chunk) { + limit -= chunk.length + if (limit <= 0) { + this.destroy() + } + }) + .resume() + }) } +} - return tail.join('\n'); +// https://streams.spec.whatwg.org/#readablestream-locked +function isLocked (self) { + // Consume is an implicit lock. + return (self[kBody] && self[kBody].locked === true) || self[kConsume] } -module.exports = _tail; +// https://fetch.spec.whatwg.org/#body-unusable +function isUnusable (self) { + return util.isDisturbed(self) || isLocked(self) +} +async function consume (stream, type) { + assert(!stream[kConsume]) -/***/ }), + return new Promise((resolve, reject) => { + if (isUnusable(stream)) { + const rState = stream._readableState + if (rState.destroyed && rState.closeEmitted === false) { + stream + .on('error', err => { + reject(err) + }) + .on('close', () => { + reject(new TypeError('unusable')) + }) + } else { + reject(rState.errored ?? new TypeError('unusable')) + } + } else { + queueMicrotask(() => { + stream[kConsume] = { + type, + stream, + resolve, + reject, + length: 0, + body: [] + } -/***/ 1125: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + stream + .on('error', function (err) { + consumeFinish(this[kConsume], err) + }) + .on('close', function () { + if (this[kConsume].body !== null) { + consumeFinish(this[kConsume], new RequestAbortedError()) + } + }) -var os = __nccwpck_require__(857); -var fs = __nccwpck_require__(9896); -var common = __nccwpck_require__(3311); + consumeStart(stream[kConsume]) + }) + } + }) +} -common.register('tempdir', _tempDir, { - allowGlobbing: false, - wrapOutput: false, -}); +function consumeStart (consume) { + if (consume.body === null) { + return + } -// Returns false if 'dir' is not a writeable directory, 'dir' otherwise -function writeableDir(dir) { - if (!dir || !fs.existsSync(dir)) return false; + const { _readableState: state } = consume.stream - if (!common.statFollowLinks(dir).isDirectory()) return false; + if (state.bufferIndex) { + const start = state.bufferIndex + const end = state.buffer.length + for (let n = start; n < end; n++) { + consumePush(consume, state.buffer[n]) + } + } else { + for (const chunk of state.buffer) { + consumePush(consume, chunk) + } + } - var testFile = dir + '/' + common.randomFileName(); - try { - fs.writeFileSync(testFile, ' '); - common.unlinkSync(testFile); - return dir; - } catch (e) { - /* istanbul ignore next */ - return false; + if (state.endEmitted) { + consumeEnd(this[kConsume]) + } else { + consume.stream.on('end', function () { + consumeEnd(this[kConsume]) + }) } -} -// Variable to cache the tempdir value for successive lookups. -var cachedTempDir; + consume.stream.resume() -//@ -//@ ### tempdir() -//@ -//@ Examples: -//@ -//@ ```javascript -//@ var tmp = tempdir(); // "/tmp" for most *nix platforms -//@ ``` -//@ -//@ Searches and returns string containing a writeable, platform-dependent temporary directory. -//@ Follows Python's [tempfile algorithm](http://docs.python.org/library/tempfile.html#tempfile.tempdir). -function _tempDir() { - if (cachedTempDir) return cachedTempDir; + while (consume.stream.read() != null) { + // Loop + } +} - cachedTempDir = writeableDir(os.tmpdir()) || - writeableDir(process.env.TMPDIR) || - writeableDir(process.env.TEMP) || - writeableDir(process.env.TMP) || - writeableDir(process.env.Wimp$ScrapDir) || // RiscOS - writeableDir('C:\\TEMP') || // Windows - writeableDir('C:\\TMP') || // Windows - writeableDir('\\TEMP') || // Windows - writeableDir('\\TMP') || // Windows - writeableDir('/tmp') || - writeableDir('/var/tmp') || - writeableDir('/usr/tmp') || - writeableDir('.'); // last resort +/** + * @param {Buffer[]} chunks + * @param {number} length + */ +function chunksDecode (chunks, length) { + if (chunks.length === 0 || length === 0) { + return '' + } + const buffer = chunks.length === 1 ? chunks[0] : Buffer.concat(chunks, length) + const bufferLength = buffer.length - return cachedTempDir; + // Skip BOM. + const start = + bufferLength > 2 && + buffer[0] === 0xef && + buffer[1] === 0xbb && + buffer[2] === 0xbf + ? 3 + : 0 + return buffer.utf8Slice(start, bufferLength) } -// Indicates if the tempdir value is currently cached. This is exposed for tests -// only. The return value should only be tested for truthiness. -function isCached() { - return cachedTempDir; -} +/** + * @param {Buffer[]} chunks + * @param {number} length + * @returns {Uint8Array} + */ +function chunksConcat (chunks, length) { + if (chunks.length === 0 || length === 0) { + return new Uint8Array(0) + } + if (chunks.length === 1) { + // fast-path + return new Uint8Array(chunks[0]) + } + const buffer = new Uint8Array(Buffer.allocUnsafeSlow(length).buffer) -// Clears the cached tempDir value, if one is cached. This is exposed for tests -// only. -function clearCache() { - cachedTempDir = undefined; + let offset = 0 + for (let i = 0; i < chunks.length; ++i) { + const chunk = chunks[i] + buffer.set(chunk, offset) + offset += chunk.length + } + + return buffer } -module.exports.tempDir = _tempDir; -module.exports.isCached = isCached; -module.exports.clearCache = clearCache; +function consumeEnd (consume) { + const { type, body, resolve, stream, length } = consume + try { + if (type === 'text') { + resolve(chunksDecode(body, length)) + } else if (type === 'json') { + resolve(JSON.parse(chunksDecode(body, length))) + } else if (type === 'arrayBuffer') { + resolve(chunksConcat(body, length).buffer) + } else if (type === 'blob') { + resolve(new Blob(body, { type: stream[kContentType] })) + } else if (type === 'bytes') { + resolve(chunksConcat(body, length)) + } -/***/ }), + consumeFinish(consume) + } catch (err) { + stream.destroy(err) + } +} -/***/ 6682: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +function consumePush (consume, chunk) { + consume.length += chunk.length + consume.body.push(chunk) +} -var fs = __nccwpck_require__(9896); -var common = __nccwpck_require__(3311); +function consumeFinish (consume, err) { + if (consume.body === null) { + return + } -common.register('test', _test, { - cmdOptions: { - 'b': 'block', - 'c': 'character', - 'd': 'directory', - 'e': 'exists', - 'f': 'file', - 'L': 'link', - 'p': 'pipe', - 'S': 'socket', - }, - wrapOutput: false, - allowGlobbing: false, -}); - - -//@ -//@ ### test(expression) -//@ -//@ Available expression primaries: -//@ -//@ + `'-b', 'path'`: true if path is a block device -//@ + `'-c', 'path'`: true if path is a character device -//@ + `'-d', 'path'`: true if path is a directory -//@ + `'-e', 'path'`: true if path exists -//@ + `'-f', 'path'`: true if path is a regular file -//@ + `'-L', 'path'`: true if path is a symbolic link -//@ + `'-p', 'path'`: true if path is a pipe (FIFO) -//@ + `'-S', 'path'`: true if path is a socket -//@ -//@ Examples: -//@ -//@ ```javascript -//@ if (test('-d', path)) { /* do something with dir */ }; -//@ if (!test('-f', path)) continue; // skip if it's not a regular file -//@ ``` -//@ -//@ Evaluates `expression` using the available primaries and returns -//@ corresponding boolean value. -function _test(options, path) { - if (!path) common.error('no path given'); - - var canInterpret = false; - Object.keys(options).forEach(function (key) { - if (options[key] === true) { - canInterpret = true; - } - }); - - if (!canInterpret) common.error('could not interpret expression'); - - if (options.link) { - try { - return common.statNoFollowLinks(path).isSymbolicLink(); - } catch (e) { - return false; - } + if (err) { + consume.reject(err) + } else { + consume.resolve() } - if (!fs.existsSync(path)) return false; - - if (options.exists) return true; - - var stats = common.statFollowLinks(path); - - if (options.block) return stats.isBlockDevice(); - - if (options.character) return stats.isCharacterDevice(); - - if (options.directory) return stats.isDirectory(); - - if (options.file) return stats.isFile(); - - /* istanbul ignore next */ - if (options.pipe) return stats.isFIFO(); - - /* istanbul ignore next */ - if (options.socket) return stats.isSocket(); + consume.type = null + consume.stream = null + consume.resolve = null + consume.reject = null + consume.length = 0 + consume.body = null +} - /* istanbul ignore next */ - return false; // fallback -} // test -module.exports = _test; +module.exports = { Readable: BodyReadable, chunksDecode } /***/ }), -/***/ 4511: +/***/ 3057: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -var fs = __nccwpck_require__(9896); -var path = __nccwpck_require__(6928); -var common = __nccwpck_require__(3311); +const assert = __nccwpck_require__(4589) +const { + ResponseStatusCodeError +} = __nccwpck_require__(329) -common.register('to', _to, { - pipeOnly: true, - wrapOutput: false, -}); +const { chunksDecode } = __nccwpck_require__(1201) +const CHUNK_LIMIT = 128 * 1024 -//@ -//@ ### ShellString.prototype.to(file) -//@ -//@ Examples: -//@ -//@ ```javascript -//@ cat('input.txt').to('output.txt'); -//@ ``` -//@ -//@ Analogous to the redirection operator `>` in Unix, but works with -//@ `ShellStrings` (such as those returned by `cat`, `grep`, etc.). _Like Unix -//@ redirections, `to()` will overwrite any existing file!_ Returns the same -//@ [ShellString](#shellstringstr) this operated on, to support chaining. -function _to(options, file) { - if (!file) common.error('wrong arguments'); +async function getResolveErrorBodyCallback ({ callback, body, contentType, statusCode, statusMessage, headers }) { + assert(body) - if (!fs.existsSync(path.dirname(file))) { - common.error('no such file or directory: ' + path.dirname(file)); - } + let chunks = [] + let length = 0 try { - fs.writeFileSync(file, this.stdout || this.toString(), 'utf8'); - return this; - } catch (e) { - /* istanbul ignore next */ - common.error('could not write to file (code ' + e.code + '): ' + file, { continue: true }); + for await (const chunk of body) { + chunks.push(chunk) + length += chunk.length + if (length > CHUNK_LIMIT) { + chunks = [] + length = 0 + break + } + } + } catch { + chunks = [] + length = 0 + // Do nothing.... } -} -module.exports = _to; + const message = `Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}` -/***/ }), - -/***/ 230: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + if (statusCode === 204 || !contentType || !length) { + queueMicrotask(() => callback(new ResponseStatusCodeError(message, statusCode, headers))) + return + } -var fs = __nccwpck_require__(9896); -var path = __nccwpck_require__(6928); -var common = __nccwpck_require__(3311); + const stackTraceLimit = Error.stackTraceLimit + Error.stackTraceLimit = 0 + let payload -common.register('toEnd', _toEnd, { - pipeOnly: true, - wrapOutput: false, -}); + try { + if (isContentTypeApplicationJson(contentType)) { + payload = JSON.parse(chunksDecode(chunks, length)) + } else if (isContentTypeText(contentType)) { + payload = chunksDecode(chunks, length) + } + } catch { + // process in a callback to avoid throwing in the microtask queue + } finally { + Error.stackTraceLimit = stackTraceLimit + } + queueMicrotask(() => callback(new ResponseStatusCodeError(message, statusCode, headers, payload))) +} -//@ -//@ ### ShellString.prototype.toEnd(file) -//@ -//@ Examples: -//@ -//@ ```javascript -//@ cat('input.txt').toEnd('output.txt'); -//@ ``` -//@ -//@ Analogous to the redirect-and-append operator `>>` in Unix, but works with -//@ `ShellStrings` (such as those returned by `cat`, `grep`, etc.). Returns the -//@ same [ShellString](#shellstringstr) this operated on, to support chaining. -function _toEnd(options, file) { - if (!file) common.error('wrong arguments'); +const isContentTypeApplicationJson = (contentType) => { + return ( + contentType.length > 15 && + contentType[11] === '/' && + contentType[0] === 'a' && + contentType[1] === 'p' && + contentType[2] === 'p' && + contentType[3] === 'l' && + contentType[4] === 'i' && + contentType[5] === 'c' && + contentType[6] === 'a' && + contentType[7] === 't' && + contentType[8] === 'i' && + contentType[9] === 'o' && + contentType[10] === 'n' && + contentType[12] === 'j' && + contentType[13] === 's' && + contentType[14] === 'o' && + contentType[15] === 'n' + ) +} - if (!fs.existsSync(path.dirname(file))) { - common.error('no such file or directory: ' + path.dirname(file)); - } +const isContentTypeText = (contentType) => { + return ( + contentType.length > 4 && + contentType[4] === '/' && + contentType[0] === 't' && + contentType[1] === 'e' && + contentType[2] === 'x' && + contentType[3] === 't' + ) +} - try { - fs.appendFileSync(file, this.stdout || this.toString(), 'utf8'); - return this; - } catch (e) { - /* istanbul ignore next */ - common.error('could not append to file (code ' + e.code + '): ' + file, { continue: true }); - } +module.exports = { + getResolveErrorBodyCallback, + isContentTypeApplicationJson, + isContentTypeText } -module.exports = _toEnd; /***/ }), -/***/ 8155: +/***/ 3242: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -var fs = __nccwpck_require__(9896); -var common = __nccwpck_require__(3311); -common.register('touch', _touch, { - cmdOptions: { - 'a': 'atime_only', - 'c': 'no_create', - 'd': 'date', - 'm': 'mtime_only', - 'r': 'reference', - }, -}); -//@ -//@ ### touch([options,] file [, file ...]) -//@ ### touch([options,] file_array) -//@ -//@ Available options: -//@ -//@ + `-a`: Change only the access time -//@ + `-c`: Do not create any files -//@ + `-m`: Change only the modification time -//@ + `{'-d': someDate}`, `{date: someDate}`: Use a `Date` instance (ex. `someDate`) -//@ instead of current time -//@ + `{'-r': file}`, `{reference: file}`: Use `file`'s times instead of current -//@ time -//@ -//@ Examples: -//@ -//@ ```javascript -//@ touch('source.js'); -//@ touch('-c', 'path/to/file.js'); -//@ touch({ '-r': 'referenceFile.txt' }, 'path/to/file.js'); -//@ touch({ '-d': new Date('December 17, 1995 03:24:00'), '-m': true }, 'path/to/file.js'); -//@ touch({ date: new Date('December 17, 1995 03:24:00') }, 'path/to/file.js'); -//@ ``` -//@ -//@ Update the access and modification times of each file to the current time. -//@ A file argument that does not exist is created empty, unless `-c` is supplied. -//@ This is a partial implementation of -//@ [`touch(1)`](http://linux.die.net/man/1/touch). Returns a -//@ [ShellString](#shellstringstr) indicating success or failure. -function _touch(opts, files) { - if (!files) { - common.error('no files given'); - } else if (typeof files === 'string') { - files = [].slice.call(arguments, 1); - } else { - common.error('file arg should be a string file path or an Array of string file paths'); - } +const net = __nccwpck_require__(7030) +const assert = __nccwpck_require__(4589) +const util = __nccwpck_require__(7234) +const { InvalidArgumentError, ConnectTimeoutError } = __nccwpck_require__(329) +const timers = __nccwpck_require__(5969) - files.forEach(function (f) { - touchFile(opts, f); - }); - return ''; -} +function noop () {} -function touchFile(opts, file) { - var stat = tryStatFile(file); +let tls // include tls conditionally since it is not always available - if (stat && stat.isDirectory()) { - // don't error just exit - return; - } +// TODO: session re-use does not wait for the first +// connection to resolve the session and might therefore +// resolve the same servername multiple times even when +// re-use is enabled. - // if the file doesn't already exist and the user has specified --no-create then - // this script is finished - if (!stat && opts.no_create) { - return; - } +let SessionCache +// FIXME: remove workaround when the Node bug is fixed +// https://github.com/nodejs/node/issues/49344#issuecomment-1741776308 +if (global.FinalizationRegistry && !(process.env.NODE_V8_COVERAGE || process.env.UNDICI_NO_FG)) { + SessionCache = class WeakSessionCache { + constructor (maxCachedSessions) { + this._maxCachedSessions = maxCachedSessions + this._sessionCache = new Map() + this._sessionRegistry = new global.FinalizationRegistry((key) => { + if (this._sessionCache.size < this._maxCachedSessions) { + return + } - // open the file and then close it. this will create it if it doesn't exist but will - // not truncate the file - fs.closeSync(fs.openSync(file, 'a')); + const ref = this._sessionCache.get(key) + if (ref !== undefined && ref.deref() === undefined) { + this._sessionCache.delete(key) + } + }) + } - // - // Set timestamps - // + get (sessionKey) { + const ref = this._sessionCache.get(sessionKey) + return ref ? ref.deref() : null + } - // setup some defaults - var now = new Date(); - var mtime = opts.date || now; - var atime = opts.date || now; + set (sessionKey, session) { + if (this._maxCachedSessions === 0) { + return + } - // use reference file - if (opts.reference) { - var refStat = tryStatFile(opts.reference); - if (!refStat) { - common.error('failed to get attributess of ' + opts.reference); + this._sessionCache.set(sessionKey, new WeakRef(session)) + this._sessionRegistry.register(session, sessionKey) } - mtime = refStat.mtime; - atime = refStat.atime; - } else if (opts.date) { - mtime = opts.date; - atime = opts.date; } +} else { + SessionCache = class SimpleSessionCache { + constructor (maxCachedSessions) { + this._maxCachedSessions = maxCachedSessions + this._sessionCache = new Map() + } - if (opts.atime_only && opts.mtime_only) { - // keep the new values of mtime and atime like GNU - } else if (opts.atime_only) { - mtime = stat.mtime; - } else if (opts.mtime_only) { - atime = stat.atime; - } + get (sessionKey) { + return this._sessionCache.get(sessionKey) + } - fs.utimesSync(file, atime, mtime); -} + set (sessionKey, session) { + if (this._maxCachedSessions === 0) { + return + } -module.exports = _touch; + if (this._sessionCache.size >= this._maxCachedSessions) { + // remove the oldest session + const { value: oldestKey } = this._sessionCache.keys().next() + this._sessionCache.delete(oldestKey) + } -function tryStatFile(filePath) { - try { - return common.statFollowLinks(filePath); - } catch (e) { - return null; + this._sessionCache.set(sessionKey, session) + } } } - -/***/ }), - -/***/ 2155: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -var fs = __nccwpck_require__(9896); -var common = __nccwpck_require__(3311); - -// add c spaces to the left of str -function lpad(c, str) { - var res = '' + str; - if (res.length < c) { - res = Array((c - res.length) + 1).join(' ') + res; +function buildConnector ({ allowH2, maxCachedSessions, socketPath, timeout, session: customSession, ...opts }) { + if (maxCachedSessions != null && (!Number.isInteger(maxCachedSessions) || maxCachedSessions < 0)) { + throw new InvalidArgumentError('maxCachedSessions must be a positive integer or zero') } - return res; -} -common.register('uniq', _uniq, { - canReceivePipe: true, - cmdOptions: { - 'i': 'ignoreCase', - 'c': 'count', - 'd': 'duplicates', - }, -}); + const options = { path: socketPath, ...opts } + const sessionCache = new SessionCache(maxCachedSessions == null ? 100 : maxCachedSessions) + timeout = timeout == null ? 10e3 : timeout + allowH2 = allowH2 != null ? allowH2 : false + return function connect ({ hostname, host, protocol, port, servername, localAddress, httpSocket }, callback) { + let socket + if (protocol === 'https:') { + if (!tls) { + tls = __nccwpck_require__(1692) + } + servername = servername || options.servername || util.getServerName(host) || null -//@ -//@ ### uniq([options,] [input, [output]]) -//@ -//@ Available options: -//@ -//@ + `-i`: Ignore case while comparing -//@ + `-c`: Prefix lines by the number of occurrences -//@ + `-d`: Only print duplicate lines, one for each group of identical lines -//@ -//@ Examples: -//@ -//@ ```javascript -//@ uniq('foo.txt'); -//@ uniq('-i', 'foo.txt'); -//@ uniq('-cd', 'foo.txt', 'bar.txt'); -//@ ``` -//@ -//@ Filter adjacent matching lines from `input`. Returns a -//@ [ShellString](#shellstringstr). -function _uniq(options, input, output) { - // Check if this is coming from a pipe - var pipe = common.readFromPipe(); + const sessionKey = servername || hostname + assert(sessionKey) - if (!pipe) { - if (!input) common.error('no input given'); + const session = customSession || sessionCache.get(sessionKey) || null - if (!fs.existsSync(input)) { - common.error(input + ': No such file or directory'); - } else if (common.statFollowLinks(input).isDirectory()) { - common.error("error reading '" + input + "'"); - } - } - if (output && fs.existsSync(output) && common.statFollowLinks(output).isDirectory()) { - common.error(output + ': Is a directory'); - } + port = port || 443 - var lines = (input ? fs.readFileSync(input, 'utf8') : pipe) - .trimRight() - .split('\n'); + socket = tls.connect({ + highWaterMark: 16384, // TLS in node can't have bigger HWM anyway... + ...options, + servername, + session, + localAddress, + // TODO(HTTP/2): Add support for h2c + ALPNProtocols: allowH2 ? ['http/1.1', 'h2'] : ['http/1.1'], + socket: httpSocket, // upgrade socket connection + port, + host: hostname + }) - var compare = function (a, b) { - return options.ignoreCase ? - a.toLocaleLowerCase().localeCompare(b.toLocaleLowerCase()) : - a.localeCompare(b); - }; - var uniqed = lines.reduceRight(function (res, e) { - // Perform uniq -c on the input - if (res.length === 0) { - return [{ count: 1, ln: e }]; - } else if (compare(res[0].ln, e) === 0) { - return [{ count: res[0].count + 1, ln: e }].concat(res.slice(1)); + socket + .on('session', function (session) { + // TODO (fix): Can a session become invalid once established? Don't think so? + sessionCache.set(sessionKey, session) + }) } else { - return [{ count: 1, ln: e }].concat(res); - } - }, []).filter(function (obj) { - // Do we want only duplicated objects? - return options.duplicates ? obj.count > 1 : true; - }).map(function (obj) { - // Are we tracking the counts of each line? - return (options.count ? (lpad(7, obj.count) + ' ') : '') + obj.ln; - }).join('\n') + '\n'; - - if (output) { - (new common.ShellString(uniqed)).to(output); - // if uniq writes to output, nothing is passed to the next command in the pipeline (if any) - return ''; - } else { - return uniqed; - } -} - -module.exports = _uniq; + assert(!httpSocket, 'httpSocket can only be sent on TLS update') + port = port || 80 -/***/ }), + socket = net.connect({ + highWaterMark: 64 * 1024, // Same as nodejs fs streams. + ...options, + localAddress, + port, + host: hostname + }) + } -/***/ 1721: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // Set TCP keep alive options on the socket here instead of in connect() for the case of assigning the socket + if (options.keepAlive == null || options.keepAlive) { + const keepAliveInitialDelay = options.keepAliveInitialDelay === undefined ? 60e3 : options.keepAliveInitialDelay + socket.setKeepAlive(true, keepAliveInitialDelay) + } -var fs = __nccwpck_require__(9896); -var path = __nccwpck_require__(6928); -var common = __nccwpck_require__(3311); + const clearConnectTimeout = setupConnectTimeout(new WeakRef(socket), { timeout, hostname, port }) -common.register('which', _which, { - allowGlobbing: false, - cmdOptions: { - 'a': 'all', - }, -}); + socket + .setNoDelay(true) + .once(protocol === 'https:' ? 'secureConnect' : 'connect', function () { + queueMicrotask(clearConnectTimeout) -// XP's system default value for `PATHEXT` system variable, just in case it's not -// set on Windows. -var XP_DEFAULT_PATHEXT = '.com;.exe;.bat;.cmd;.vbs;.vbe;.js;.jse;.wsf;.wsh'; + if (callback) { + const cb = callback + callback = null + cb(null, this) + } + }) + .on('error', function (err) { + queueMicrotask(clearConnectTimeout) -// For earlier versions of NodeJS that doesn't have a list of constants (< v6) -var FILE_EXECUTABLE_MODE = 1; + if (callback) { + const cb = callback + callback = null + cb(err) + } + }) -function isWindowsPlatform() { - return process.platform === 'win32'; + return socket + } } -// Cross-platform method for splitting environment `PATH` variables -function splitPath(p) { - return p ? p.split(path.delimiter) : []; -} +/** + * @param {WeakRef} socketWeakRef + * @param {object} opts + * @param {number} opts.timeout + * @param {string} opts.hostname + * @param {number} opts.port + * @returns {() => void} + */ +const setupConnectTimeout = process.platform === 'win32' + ? (socketWeakRef, opts) => { + if (!opts.timeout) { + return noop + } -// Tests are running all cases for this func but it stays uncovered by codecov due to unknown reason -/* istanbul ignore next */ -function isExecutable(pathName) { - try { - // TODO(node-support): replace with fs.constants.X_OK once remove support for node < v6 - fs.accessSync(pathName, FILE_EXECUTABLE_MODE); - } catch (err) { - return false; + let s1 = null + let s2 = null + const fastTimer = timers.setFastTimeout(() => { + // setImmediate is added to make sure that we prioritize socket error events over timeouts + s1 = setImmediate(() => { + // Windows needs an extra setImmediate probably due to implementation differences in the socket logic + s2 = setImmediate(() => onConnectTimeout(socketWeakRef.deref(), opts)) + }) + }, opts.timeout) + return () => { + timers.clearFastTimeout(fastTimer) + clearImmediate(s1) + clearImmediate(s2) + } + } + : (socketWeakRef, opts) => { + if (!opts.timeout) { + return noop + } + + let s1 = null + const fastTimer = timers.setFastTimeout(() => { + // setImmediate is added to make sure that we prioritize socket error events over timeouts + s1 = setImmediate(() => { + onConnectTimeout(socketWeakRef.deref(), opts) + }) + }, opts.timeout) + return () => { + timers.clearFastTimeout(fastTimer) + clearImmediate(s1) + } + } + +/** + * @param {net.Socket} socket + * @param {object} opts + * @param {number} opts.timeout + * @param {string} opts.hostname + * @param {number} opts.port + */ +function onConnectTimeout (socket, opts) { + // The socket could be already garbage collected + if (socket == null) { + return } - return true; -} -function checkPath(pathName) { - return fs.existsSync(pathName) && !common.statFollowLinks(pathName).isDirectory() - && (isWindowsPlatform() || isExecutable(pathName)); + let message = 'Connect Timeout Error' + if (Array.isArray(socket.autoSelectFamilyAttemptedAddresses)) { + message += ` (attempted addresses: ${socket.autoSelectFamilyAttemptedAddresses.join(', ')},` + } else { + message += ` (attempted address: ${opts.hostname}:${opts.port},` + } + + message += ` timeout: ${opts.timeout}ms)` + + util.destroy(socket, new ConnectTimeoutError(message)) } -//@ -//@ ### which(command) -//@ -//@ Examples: -//@ -//@ ```javascript -//@ var nodeExec = which('node'); -//@ ``` -//@ -//@ Searches for `command` in the system's `PATH`. On Windows, this uses the -//@ `PATHEXT` variable to append the extension if it's not already executable. -//@ Returns a [ShellString](#shellstringstr) containing the absolute path to -//@ `command`. -function _which(options, cmd) { - if (!cmd) common.error('must specify command'); +module.exports = buildConnector - var isWindows = isWindowsPlatform(); - var pathArray = splitPath(process.env.PATH); - var queryMatches = []; +/***/ }), - // No relative/absolute paths provided? - if (!cmd.includes('/')) { - // Assume that there are no extensions to append to queries (this is the - // case for unix) - var pathExtArray = ['']; - if (isWindows) { - // In case the PATHEXT variable is somehow not set (e.g. - // child_process.spawn with an empty environment), use the XP default. - var pathExtEnv = process.env.PATHEXT || XP_DEFAULT_PATHEXT; - pathExtArray = splitPath(pathExtEnv.toUpperCase()); - } +/***/ 8429: +/***/ ((module) => { - // Search for command in PATH - for (var k = 0; k < pathArray.length; k++) { - // already found it - if (queryMatches.length > 0 && !options.all) break; - var attempt = path.resolve(pathArray[k], cmd); - if (isWindows) { - attempt = attempt.toUpperCase(); - } +/** @type {Record} */ +const headerNameLowerCasedRecord = {} - var match = attempt.match(/\.[^<>:"/|?*.]+$/); - if (match && pathExtArray.includes(match[0])) { // this is Windows-only - // The user typed a query with the file extension, like - // `which('node.exe')` - if (checkPath(attempt)) { - queryMatches.push(attempt); - break; - } - } else { // All-platforms - // Cycle through the PATHEXT array, and check each extension - // Note: the array is always [''] on Unix - for (var i = 0; i < pathExtArray.length; i++) { - var ext = pathExtArray[i]; - var newAttempt = attempt + ext; - if (checkPath(newAttempt)) { - queryMatches.push(newAttempt); - break; - } - } - } - } - } else if (checkPath(cmd)) { // a valid absolute or relative path - queryMatches.push(path.resolve(cmd)); - } +// https://developer.mozilla.org/docs/Web/HTTP/Headers +const wellknownHeaderNames = [ + 'Accept', + 'Accept-Encoding', + 'Accept-Language', + 'Accept-Ranges', + 'Access-Control-Allow-Credentials', + 'Access-Control-Allow-Headers', + 'Access-Control-Allow-Methods', + 'Access-Control-Allow-Origin', + 'Access-Control-Expose-Headers', + 'Access-Control-Max-Age', + 'Access-Control-Request-Headers', + 'Access-Control-Request-Method', + 'Age', + 'Allow', + 'Alt-Svc', + 'Alt-Used', + 'Authorization', + 'Cache-Control', + 'Clear-Site-Data', + 'Connection', + 'Content-Disposition', + 'Content-Encoding', + 'Content-Language', + 'Content-Length', + 'Content-Location', + 'Content-Range', + 'Content-Security-Policy', + 'Content-Security-Policy-Report-Only', + 'Content-Type', + 'Cookie', + 'Cross-Origin-Embedder-Policy', + 'Cross-Origin-Opener-Policy', + 'Cross-Origin-Resource-Policy', + 'Date', + 'Device-Memory', + 'Downlink', + 'ECT', + 'ETag', + 'Expect', + 'Expect-CT', + 'Expires', + 'Forwarded', + 'From', + 'Host', + 'If-Match', + 'If-Modified-Since', + 'If-None-Match', + 'If-Range', + 'If-Unmodified-Since', + 'Keep-Alive', + 'Last-Modified', + 'Link', + 'Location', + 'Max-Forwards', + 'Origin', + 'Permissions-Policy', + 'Pragma', + 'Proxy-Authenticate', + 'Proxy-Authorization', + 'RTT', + 'Range', + 'Referer', + 'Referrer-Policy', + 'Refresh', + 'Retry-After', + 'Sec-WebSocket-Accept', + 'Sec-WebSocket-Extensions', + 'Sec-WebSocket-Key', + 'Sec-WebSocket-Protocol', + 'Sec-WebSocket-Version', + 'Server', + 'Server-Timing', + 'Service-Worker-Allowed', + 'Service-Worker-Navigation-Preload', + 'Set-Cookie', + 'SourceMap', + 'Strict-Transport-Security', + 'Supports-Loading-Mode', + 'TE', + 'Timing-Allow-Origin', + 'Trailer', + 'Transfer-Encoding', + 'Upgrade', + 'Upgrade-Insecure-Requests', + 'User-Agent', + 'Vary', + 'Via', + 'WWW-Authenticate', + 'X-Content-Type-Options', + 'X-DNS-Prefetch-Control', + 'X-Frame-Options', + 'X-Permitted-Cross-Domain-Policies', + 'X-Powered-By', + 'X-Requested-With', + 'X-XSS-Protection' +] - if (queryMatches.length > 0) { - return options.all ? queryMatches : queryMatches[0]; - } - return options.all ? [] : null; +for (let i = 0; i < wellknownHeaderNames.length; ++i) { + const key = wellknownHeaderNames[i] + const lowerCasedKey = key.toLowerCase() + headerNameLowerCasedRecord[key] = headerNameLowerCasedRecord[lowerCasedKey] = + lowerCasedKey +} + +// Note: object prototypes should not be able to be referenced. e.g. `Object#hasOwnProperty`. +Object.setPrototypeOf(headerNameLowerCasedRecord, null) + +module.exports = { + wellknownHeaderNames, + headerNameLowerCasedRecord } -module.exports = _which; /***/ }), -/***/ 965: +/***/ 7820: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -// Note: since nyc uses this module to output coverage, any lines -// that are in the direct sync flow of nyc's outputCoverage are -// ignored, since we can never get coverage for them. -// grab a reference to node's real process object right away -var process = global.process -const processOk = function (process) { - return process && - typeof process === 'object' && - typeof process.removeListener === 'function' && - typeof process.emit === 'function' && - typeof process.reallyExit === 'function' && - typeof process.listeners === 'function' && - typeof process.kill === 'function' && - typeof process.pid === 'number' && - typeof process.on === 'function' +const diagnosticsChannel = __nccwpck_require__(3053) +const util = __nccwpck_require__(7975) + +const undiciDebugLog = util.debuglog('undici') +const fetchDebuglog = util.debuglog('fetch') +const websocketDebuglog = util.debuglog('websocket') +let isClientSet = false +const channels = { + // Client + beforeConnect: diagnosticsChannel.channel('undici:client:beforeConnect'), + connected: diagnosticsChannel.channel('undici:client:connected'), + connectError: diagnosticsChannel.channel('undici:client:connectError'), + sendHeaders: diagnosticsChannel.channel('undici:client:sendHeaders'), + // Request + create: diagnosticsChannel.channel('undici:request:create'), + bodySent: diagnosticsChannel.channel('undici:request:bodySent'), + headers: diagnosticsChannel.channel('undici:request:headers'), + trailers: diagnosticsChannel.channel('undici:request:trailers'), + error: diagnosticsChannel.channel('undici:request:error'), + // WebSocket + open: diagnosticsChannel.channel('undici:websocket:open'), + close: diagnosticsChannel.channel('undici:websocket:close'), + socketError: diagnosticsChannel.channel('undici:websocket:socket_error'), + ping: diagnosticsChannel.channel('undici:websocket:ping'), + pong: diagnosticsChannel.channel('undici:websocket:pong') } -// some kind of non-node environment, just no-op -/* istanbul ignore if */ -if (!processOk(process)) { - module.exports = function () { - return function () {} - } -} else { - var assert = __nccwpck_require__(2613) - var signals = __nccwpck_require__(3116) - var isWin = /^win/i.test(process.platform) +if (undiciDebugLog.enabled || fetchDebuglog.enabled) { + const debuglog = fetchDebuglog.enabled ? fetchDebuglog : undiciDebugLog - var EE = __nccwpck_require__(4434) - /* istanbul ignore if */ - if (typeof EE !== 'function') { - EE = EE.EventEmitter - } + // Track all Client events + diagnosticsChannel.channel('undici:client:beforeConnect').subscribe(evt => { + const { + connectParams: { version, protocol, port, host } + } = evt + debuglog( + 'connecting to %s using %s%s', + `${host}${port ? `:${port}` : ''}`, + protocol, + version + ) + }) - var emitter - if (process.__signal_exit_emitter__) { - emitter = process.__signal_exit_emitter__ - } else { - emitter = process.__signal_exit_emitter__ = new EE() - emitter.count = 0 - emitter.emitted = {} - } + diagnosticsChannel.channel('undici:client:connected').subscribe(evt => { + const { + connectParams: { version, protocol, port, host } + } = evt + debuglog( + 'connected to %s using %s%s', + `${host}${port ? `:${port}` : ''}`, + protocol, + version + ) + }) - // Because this emitter is a global, we have to check to see if a - // previous version of this library failed to enable infinite listeners. - // I know what you're about to say. But literally everything about - // signal-exit is a compromise with evil. Get used to it. - if (!emitter.infinite) { - emitter.setMaxListeners(Infinity) - emitter.infinite = true - } + diagnosticsChannel.channel('undici:client:connectError').subscribe(evt => { + const { + connectParams: { version, protocol, port, host }, + error + } = evt + debuglog( + 'connection to %s using %s%s errored - %s', + `${host}${port ? `:${port}` : ''}`, + protocol, + version, + error.message + ) + }) - module.exports = function (cb, opts) { - /* istanbul ignore if */ - if (!processOk(global.process)) { - return function () {} - } - assert.equal(typeof cb, 'function', 'a callback must be provided for exit handler') + diagnosticsChannel.channel('undici:client:sendHeaders').subscribe(evt => { + const { + request: { method, path, origin } + } = evt + debuglog('sending request to %s %s/%s', method, origin, path) + }) - if (loaded === false) { - load() - } + // Track Request events + diagnosticsChannel.channel('undici:request:headers').subscribe(evt => { + const { + request: { method, path, origin }, + response: { statusCode } + } = evt + debuglog( + 'received response to %s %s/%s - HTTP %d', + method, + origin, + path, + statusCode + ) + }) - var ev = 'exit' - if (opts && opts.alwaysLast) { - ev = 'afterexit' - } + diagnosticsChannel.channel('undici:request:trailers').subscribe(evt => { + const { + request: { method, path, origin } + } = evt + debuglog('trailers received from %s %s/%s', method, origin, path) + }) - var remove = function () { - emitter.removeListener(ev, cb) - if (emitter.listeners('exit').length === 0 && - emitter.listeners('afterexit').length === 0) { - unload() - } - } - emitter.on(ev, cb) + diagnosticsChannel.channel('undici:request:error').subscribe(evt => { + const { + request: { method, path, origin }, + error + } = evt + debuglog( + 'request to %s %s/%s errored - %s', + method, + origin, + path, + error.message + ) + }) - return remove - } + isClientSet = true +} - var unload = function unload () { - if (!loaded || !processOk(global.process)) { - return - } - loaded = false +if (websocketDebuglog.enabled) { + if (!isClientSet) { + const debuglog = undiciDebugLog.enabled ? undiciDebugLog : websocketDebuglog + diagnosticsChannel.channel('undici:client:beforeConnect').subscribe(evt => { + const { + connectParams: { version, protocol, port, host } + } = evt + debuglog( + 'connecting to %s%s using %s%s', + host, + port ? `:${port}` : '', + protocol, + version + ) + }) - signals.forEach(function (sig) { - try { - process.removeListener(sig, sigListeners[sig]) - } catch (er) {} + diagnosticsChannel.channel('undici:client:connected').subscribe(evt => { + const { + connectParams: { version, protocol, port, host } + } = evt + debuglog( + 'connected to %s%s using %s%s', + host, + port ? `:${port}` : '', + protocol, + version + ) }) - process.emit = originalProcessEmit - process.reallyExit = originalProcessReallyExit - emitter.count -= 1 - } - module.exports.unload = unload - var emit = function emit (event, code, signal) { - /* istanbul ignore if */ - if (emitter.emitted[event]) { - return - } - emitter.emitted[event] = true - emitter.emit(event, code, signal) + diagnosticsChannel.channel('undici:client:connectError').subscribe(evt => { + const { + connectParams: { version, protocol, port, host }, + error + } = evt + debuglog( + 'connection to %s%s using %s%s errored - %s', + host, + port ? `:${port}` : '', + protocol, + version, + error.message + ) + }) + + diagnosticsChannel.channel('undici:client:sendHeaders').subscribe(evt => { + const { + request: { method, path, origin } + } = evt + debuglog('sending request to %s %s/%s', method, origin, path) + }) } - // { : , ... } - var sigListeners = {} - signals.forEach(function (sig) { - sigListeners[sig] = function listener () { - /* istanbul ignore if */ - if (!processOk(global.process)) { - return - } - // If there are no other listeners, an exit is coming! - // Simplest way: remove us and then re-send the signal. - // We know that this will kill the process, so we can - // safely emit now. - var listeners = process.listeners(sig) - if (listeners.length === emitter.count) { - unload() - emit('exit', null, sig) - /* istanbul ignore next */ - emit('afterexit', null, sig) - /* istanbul ignore next */ - if (isWin && sig === 'SIGHUP') { - // "SIGHUP" throws an `ENOSYS` error on Windows, - // so use a supported signal instead - sig = 'SIGINT' - } - /* istanbul ignore next */ - process.kill(process.pid, sig) - } - } + // Track all WebSocket events + diagnosticsChannel.channel('undici:websocket:open').subscribe(evt => { + const { + address: { address, port } + } = evt + websocketDebuglog('connection opened %s%s', address, port ? `:${port}` : '') }) - module.exports.signals = function () { - return signals - } + diagnosticsChannel.channel('undici:websocket:close').subscribe(evt => { + const { websocket, code, reason } = evt + websocketDebuglog( + 'closed connection to %s - %s %s', + websocket.url, + code, + reason + ) + }) - var loaded = false + diagnosticsChannel.channel('undici:websocket:socket_error').subscribe(err => { + websocketDebuglog('connection errored - %s', err.message) + }) - var load = function load () { - if (loaded || !processOk(global.process)) { - return - } - loaded = true + diagnosticsChannel.channel('undici:websocket:ping').subscribe(evt => { + websocketDebuglog('ping received') + }) - // This is the number of onSignalExit's that are in play. - // It's important so that we can count the correct number of - // listeners on signals, and don't wait for the other one to - // handle it instead of us. - emitter.count += 1 + diagnosticsChannel.channel('undici:websocket:pong').subscribe(evt => { + websocketDebuglog('pong received') + }) +} - signals = signals.filter(function (sig) { - try { - process.on(sig, sigListeners[sig]) - return true - } catch (er) { - return false - } - }) - - process.emit = processEmit - process.reallyExit = processReallyExit - } - module.exports.load = load - - var originalProcessReallyExit = process.reallyExit - var processReallyExit = function processReallyExit (code) { - /* istanbul ignore if */ - if (!processOk(global.process)) { - return - } - process.exitCode = code || /* istanbul ignore next */ 0 - emit('exit', process.exitCode, null) - /* istanbul ignore next */ - emit('afterexit', process.exitCode, null) - /* istanbul ignore next */ - originalProcessReallyExit.call(process, process.exitCode) - } - - var originalProcessEmit = process.emit - var processEmit = function processEmit (ev, arg) { - if (ev === 'exit' && processOk(global.process)) { - /* istanbul ignore else */ - if (arg !== undefined) { - process.exitCode = arg - } - var ret = originalProcessEmit.apply(this, arguments) - /* istanbul ignore next */ - emit('exit', process.exitCode, null) - /* istanbul ignore next */ - emit('afterexit', process.exitCode, null) - /* istanbul ignore next */ - return ret - } else { - return originalProcessEmit.apply(this, arguments) - } - } -} +module.exports = { + channels +} /***/ }), -/***/ 3116: +/***/ 329: /***/ ((module) => { -// This is not the set of all possible signals. -// -// It IS, however, the set of all signals that trigger -// an exit on either Linux or BSD systems. Linux is a -// superset of the signal names supported on BSD, and -// the unknown signals just fail to register, so we can -// catch that easily enough. -// -// Don't bother with SIGKILL. It's uncatchable, which -// means that we can't fire any callbacks anyway. -// -// If a user does happen to register a handler on a non- -// fatal signal like SIGWINCH or something, and then -// exit, it'll end up firing `process.emit('exit')`, so -// the handler will be fired anyway. -// -// SIGBUS, SIGFPE, SIGSEGV and SIGILL, when not raised -// artificially, inherently leave the process in a -// state from which it is not safe to try and enter JS -// listeners. -module.exports = [ - 'SIGABRT', - 'SIGALRM', - 'SIGHUP', - 'SIGINT', - 'SIGTERM' -] - -if (process.platform !== 'win32') { - module.exports.push( - 'SIGVTALRM', - 'SIGXCPU', - 'SIGXFSZ', - 'SIGUSR2', - 'SIGTRAP', - 'SIGSYS', - 'SIGQUIT', - 'SIGIOT' - // should detect profiler and enable/disable accordingly. - // see #21 - // 'SIGPROF' - ) -} - -if (process.platform === 'linux') { - module.exports.push( - 'SIGIO', - 'SIGPOLL', - 'SIGPWR', - 'SIGSTKFLT', - 'SIGUNUSED' - ) -} -/***/ }), +const kUndiciError = Symbol.for('undici.error.UND_ERR') +class UndiciError extends Error { + constructor (message) { + super(message) + this.name = 'UndiciError' + this.code = 'UND_ERR' + } -/***/ 3366: -/***/ ((module) => { + static [Symbol.hasInstance] (instance) { + return instance && instance[kUndiciError] === true + } -"use strict"; + [kUndiciError] = true +} +const kConnectTimeoutError = Symbol.for('undici.error.UND_ERR_CONNECT_TIMEOUT') +class ConnectTimeoutError extends UndiciError { + constructor (message) { + super(message) + this.name = 'ConnectTimeoutError' + this.message = message || 'Connect Timeout Error' + this.code = 'UND_ERR_CONNECT_TIMEOUT' + } -module.exports = input => { - const LF = typeof input === 'string' ? '\n' : '\n'.charCodeAt(); - const CR = typeof input === 'string' ? '\r' : '\r'.charCodeAt(); + static [Symbol.hasInstance] (instance) { + return instance && instance[kConnectTimeoutError] === true + } - if (input[input.length - 1] === LF) { - input = input.slice(0, input.length - 1); - } + [kConnectTimeoutError] = true +} - if (input[input.length - 1] === CR) { - input = input.slice(0, input.length - 1); - } +const kHeadersTimeoutError = Symbol.for('undici.error.UND_ERR_HEADERS_TIMEOUT') +class HeadersTimeoutError extends UndiciError { + constructor (message) { + super(message) + this.name = 'HeadersTimeoutError' + this.message = message || 'Headers Timeout Error' + this.code = 'UND_ERR_HEADERS_TIMEOUT' + } - return input; -}; + static [Symbol.hasInstance] (instance) { + return instance && instance[kHeadersTimeoutError] === true + } + [kHeadersTimeoutError] = true +} -/***/ }), +const kHeadersOverflowError = Symbol.for('undici.error.UND_ERR_HEADERS_OVERFLOW') +class HeadersOverflowError extends UndiciError { + constructor (message) { + super(message) + this.name = 'HeadersOverflowError' + this.message = message || 'Headers Overflow Error' + this.code = 'UND_ERR_HEADERS_OVERFLOW' + } -/***/ 1512: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + static [Symbol.hasInstance] (instance) { + return instance && instance[kHeadersOverflowError] === true + } -"use strict"; -/*! - * to-regex-range - * - * Copyright (c) 2015-present, Jon Schlinkert. - * Released under the MIT License. - */ + [kHeadersOverflowError] = true +} +const kBodyTimeoutError = Symbol.for('undici.error.UND_ERR_BODY_TIMEOUT') +class BodyTimeoutError extends UndiciError { + constructor (message) { + super(message) + this.name = 'BodyTimeoutError' + this.message = message || 'Body Timeout Error' + this.code = 'UND_ERR_BODY_TIMEOUT' + } + static [Symbol.hasInstance] (instance) { + return instance && instance[kBodyTimeoutError] === true + } -const isNumber = __nccwpck_require__(3491); + [kBodyTimeoutError] = true +} -const toRegexRange = (min, max, options) => { - if (isNumber(min) === false) { - throw new TypeError('toRegexRange: expected the first argument to be a number'); +const kResponseStatusCodeError = Symbol.for('undici.error.UND_ERR_RESPONSE_STATUS_CODE') +class ResponseStatusCodeError extends UndiciError { + constructor (message, statusCode, headers, body) { + super(message) + this.name = 'ResponseStatusCodeError' + this.message = message || 'Response Status Code Error' + this.code = 'UND_ERR_RESPONSE_STATUS_CODE' + this.body = body + this.status = statusCode + this.statusCode = statusCode + this.headers = headers } - if (max === void 0 || min === max) { - return String(min); + static [Symbol.hasInstance] (instance) { + return instance && instance[kResponseStatusCodeError] === true } - if (isNumber(max) === false) { - throw new TypeError('toRegexRange: expected the second argument to be a number.'); - } + [kResponseStatusCodeError] = true +} - let opts = { relaxZeros: true, ...options }; - if (typeof opts.strictZeros === 'boolean') { - opts.relaxZeros = opts.strictZeros === false; +const kInvalidArgumentError = Symbol.for('undici.error.UND_ERR_INVALID_ARG') +class InvalidArgumentError extends UndiciError { + constructor (message) { + super(message) + this.name = 'InvalidArgumentError' + this.message = message || 'Invalid Argument Error' + this.code = 'UND_ERR_INVALID_ARG' } - let relax = String(opts.relaxZeros); - let shorthand = String(opts.shorthand); - let capture = String(opts.capture); - let wrap = String(opts.wrap); - let cacheKey = min + ':' + max + '=' + relax + shorthand + capture + wrap; - - if (toRegexRange.cache.hasOwnProperty(cacheKey)) { - return toRegexRange.cache[cacheKey].result; + static [Symbol.hasInstance] (instance) { + return instance && instance[kInvalidArgumentError] === true } - let a = Math.min(min, max); - let b = Math.max(min, max); + [kInvalidArgumentError] = true +} - if (Math.abs(a - b) === 1) { - let result = min + '|' + max; - if (opts.capture) { - return `(${result})`; - } - if (opts.wrap === false) { - return result; - } - return `(?:${result})`; +const kInvalidReturnValueError = Symbol.for('undici.error.UND_ERR_INVALID_RETURN_VALUE') +class InvalidReturnValueError extends UndiciError { + constructor (message) { + super(message) + this.name = 'InvalidReturnValueError' + this.message = message || 'Invalid Return Value Error' + this.code = 'UND_ERR_INVALID_RETURN_VALUE' } - let isPadded = hasPadding(min) || hasPadding(max); - let state = { min, max, a, b }; - let positives = []; - let negatives = []; - - if (isPadded) { - state.isPadded = isPadded; - state.maxLen = String(state.max).length; + static [Symbol.hasInstance] (instance) { + return instance && instance[kInvalidReturnValueError] === true } - if (a < 0) { - let newMin = b < 0 ? Math.abs(b) : 1; - negatives = splitToPatterns(newMin, Math.abs(a), state, opts); - a = state.a = 0; + [kInvalidReturnValueError] = true +} + +const kAbortError = Symbol.for('undici.error.UND_ERR_ABORT') +class AbortError extends UndiciError { + constructor (message) { + super(message) + this.name = 'AbortError' + this.message = message || 'The operation was aborted' + this.code = 'UND_ERR_ABORT' } - if (b >= 0) { - positives = splitToPatterns(a, b, state, opts); + static [Symbol.hasInstance] (instance) { + return instance && instance[kAbortError] === true } - state.negatives = negatives; - state.positives = positives; - state.result = collatePatterns(negatives, positives, opts); + [kAbortError] = true +} - if (opts.capture === true) { - state.result = `(${state.result})`; - } else if (opts.wrap !== false && (positives.length + negatives.length) > 1) { - state.result = `(?:${state.result})`; +const kRequestAbortedError = Symbol.for('undici.error.UND_ERR_ABORTED') +class RequestAbortedError extends AbortError { + constructor (message) { + super(message) + this.name = 'AbortError' + this.message = message || 'Request aborted' + this.code = 'UND_ERR_ABORTED' } - toRegexRange.cache[cacheKey] = state; - return state.result; -}; + static [Symbol.hasInstance] (instance) { + return instance && instance[kRequestAbortedError] === true + } -function collatePatterns(neg, pos, options) { - let onlyNegative = filterPatterns(neg, pos, '-', false, options) || []; - let onlyPositive = filterPatterns(pos, neg, '', false, options) || []; - let intersected = filterPatterns(neg, pos, '-?', true, options) || []; - let subpatterns = onlyNegative.concat(intersected).concat(onlyPositive); - return subpatterns.join('|'); + [kRequestAbortedError] = true } -function splitToRanges(min, max) { - let nines = 1; - let zeros = 1; - - let stop = countNines(min, nines); - let stops = new Set([max]); - - while (min <= stop && stop <= max) { - stops.add(stop); - nines += 1; - stop = countNines(min, nines); +const kInformationalError = Symbol.for('undici.error.UND_ERR_INFO') +class InformationalError extends UndiciError { + constructor (message) { + super(message) + this.name = 'InformationalError' + this.message = message || 'Request information' + this.code = 'UND_ERR_INFO' } - stop = countZeros(max + 1, zeros) - 1; - - while (min < stop && stop <= max) { - stops.add(stop); - zeros += 1; - stop = countZeros(max + 1, zeros) - 1; + static [Symbol.hasInstance] (instance) { + return instance && instance[kInformationalError] === true } - stops = [...stops]; - stops.sort(compare); - return stops; + [kInformationalError] = true } -/** - * Convert a range to a regex pattern - * @param {Number} `start` - * @param {Number} `stop` - * @return {String} - */ +const kRequestContentLengthMismatchError = Symbol.for('undici.error.UND_ERR_REQ_CONTENT_LENGTH_MISMATCH') +class RequestContentLengthMismatchError extends UndiciError { + constructor (message) { + super(message) + this.name = 'RequestContentLengthMismatchError' + this.message = message || 'Request body length does not match content-length header' + this.code = 'UND_ERR_REQ_CONTENT_LENGTH_MISMATCH' + } -function rangeToPattern(start, stop, options) { - if (start === stop) { - return { pattern: start, count: [], digits: 0 }; + static [Symbol.hasInstance] (instance) { + return instance && instance[kRequestContentLengthMismatchError] === true } - let zipped = zip(start, stop); - let digits = zipped.length; - let pattern = ''; - let count = 0; + [kRequestContentLengthMismatchError] = true +} - for (let i = 0; i < digits; i++) { - let [startDigit, stopDigit] = zipped[i]; +const kResponseContentLengthMismatchError = Symbol.for('undici.error.UND_ERR_RES_CONTENT_LENGTH_MISMATCH') +class ResponseContentLengthMismatchError extends UndiciError { + constructor (message) { + super(message) + this.name = 'ResponseContentLengthMismatchError' + this.message = message || 'Response body length does not match content-length header' + this.code = 'UND_ERR_RES_CONTENT_LENGTH_MISMATCH' + } - if (startDigit === stopDigit) { - pattern += startDigit; + static [Symbol.hasInstance] (instance) { + return instance && instance[kResponseContentLengthMismatchError] === true + } - } else if (startDigit !== '0' || stopDigit !== '9') { - pattern += toCharacterClass(startDigit, stopDigit, options); + [kResponseContentLengthMismatchError] = true +} - } else { - count++; - } +const kClientDestroyedError = Symbol.for('undici.error.UND_ERR_DESTROYED') +class ClientDestroyedError extends UndiciError { + constructor (message) { + super(message) + this.name = 'ClientDestroyedError' + this.message = message || 'The client is destroyed' + this.code = 'UND_ERR_DESTROYED' } - if (count) { - pattern += options.shorthand === true ? '\\d' : '[0-9]'; + static [Symbol.hasInstance] (instance) { + return instance && instance[kClientDestroyedError] === true } - return { pattern, count: [count], digits }; + [kClientDestroyedError] = true } -function splitToPatterns(min, max, tok, options) { - let ranges = splitToRanges(min, max); - let tokens = []; - let start = min; - let prev; - - for (let i = 0; i < ranges.length; i++) { - let max = ranges[i]; - let obj = rangeToPattern(String(start), String(max), options); - let zeros = ''; +const kClientClosedError = Symbol.for('undici.error.UND_ERR_CLOSED') +class ClientClosedError extends UndiciError { + constructor (message) { + super(message) + this.name = 'ClientClosedError' + this.message = message || 'The client is closed' + this.code = 'UND_ERR_CLOSED' + } - if (!tok.isPadded && prev && prev.pattern === obj.pattern) { - if (prev.count.length > 1) { - prev.count.pop(); - } + static [Symbol.hasInstance] (instance) { + return instance && instance[kClientClosedError] === true + } - prev.count.push(obj.count[0]); - prev.string = prev.pattern + toQuantifier(prev.count); - start = max + 1; - continue; - } + [kClientClosedError] = true +} - if (tok.isPadded) { - zeros = padZeros(max, tok, options); - } +const kSocketError = Symbol.for('undici.error.UND_ERR_SOCKET') +class SocketError extends UndiciError { + constructor (message, socket) { + super(message) + this.name = 'SocketError' + this.message = message || 'Socket error' + this.code = 'UND_ERR_SOCKET' + this.socket = socket + } - obj.string = zeros + obj.pattern + toQuantifier(obj.count); - tokens.push(obj); - start = max + 1; - prev = obj; + static [Symbol.hasInstance] (instance) { + return instance && instance[kSocketError] === true } - return tokens; + [kSocketError] = true } -function filterPatterns(arr, comparison, prefix, intersection, options) { - let result = []; +const kNotSupportedError = Symbol.for('undici.error.UND_ERR_NOT_SUPPORTED') +class NotSupportedError extends UndiciError { + constructor (message) { + super(message) + this.name = 'NotSupportedError' + this.message = message || 'Not supported error' + this.code = 'UND_ERR_NOT_SUPPORTED' + } - for (let ele of arr) { - let { string } = ele; + static [Symbol.hasInstance] (instance) { + return instance && instance[kNotSupportedError] === true + } - // only push if _both_ are negative... - if (!intersection && !contains(comparison, 'string', string)) { - result.push(prefix + string); - } + [kNotSupportedError] = true +} - // or _both_ are positive - if (intersection && contains(comparison, 'string', string)) { - result.push(prefix + string); - } +const kBalancedPoolMissingUpstreamError = Symbol.for('undici.error.UND_ERR_BPL_MISSING_UPSTREAM') +class BalancedPoolMissingUpstreamError extends UndiciError { + constructor (message) { + super(message) + this.name = 'MissingUpstreamError' + this.message = message || 'No upstream has been added to the BalancedPool' + this.code = 'UND_ERR_BPL_MISSING_UPSTREAM' } - return result; -} -/** - * Zip strings - */ + static [Symbol.hasInstance] (instance) { + return instance && instance[kBalancedPoolMissingUpstreamError] === true + } -function zip(a, b) { - let arr = []; - for (let i = 0; i < a.length; i++) arr.push([a[i], b[i]]); - return arr; + [kBalancedPoolMissingUpstreamError] = true } -function compare(a, b) { - return a > b ? 1 : b > a ? -1 : 0; -} +const kHTTPParserError = Symbol.for('undici.error.UND_ERR_HTTP_PARSER') +class HTTPParserError extends Error { + constructor (message, code, data) { + super(message) + this.name = 'HTTPParserError' + this.code = code ? `HPE_${code}` : undefined + this.data = data ? data.toString() : undefined + } -function contains(arr, key, val) { - return arr.some(ele => ele[key] === val); -} + static [Symbol.hasInstance] (instance) { + return instance && instance[kHTTPParserError] === true + } -function countNines(min, len) { - return Number(String(min).slice(0, -len) + '9'.repeat(len)); + [kHTTPParserError] = true } -function countZeros(integer, zeros) { - return integer - (integer % Math.pow(10, zeros)); -} +const kResponseExceededMaxSizeError = Symbol.for('undici.error.UND_ERR_RES_EXCEEDED_MAX_SIZE') +class ResponseExceededMaxSizeError extends UndiciError { + constructor (message) { + super(message) + this.name = 'ResponseExceededMaxSizeError' + this.message = message || 'Response content exceeded max size' + this.code = 'UND_ERR_RES_EXCEEDED_MAX_SIZE' + } -function toQuantifier(digits) { - let [start = 0, stop = ''] = digits; - if (stop || start > 1) { - return `{${start + (stop ? ',' + stop : '')}}`; + static [Symbol.hasInstance] (instance) { + return instance && instance[kResponseExceededMaxSizeError] === true } - return ''; -} -function toCharacterClass(a, b, options) { - return `[${a}${(b - a === 1) ? '' : '-'}${b}]`; + [kResponseExceededMaxSizeError] = true } -function hasPadding(str) { - return /^-?(0+)\d/.test(str); -} +const kRequestRetryError = Symbol.for('undici.error.UND_ERR_REQ_RETRY') +class RequestRetryError extends UndiciError { + constructor (message, code, { headers, data }) { + super(message) + this.name = 'RequestRetryError' + this.message = message || 'Request retry error' + this.code = 'UND_ERR_REQ_RETRY' + this.statusCode = code + this.data = data + this.headers = headers + } -function padZeros(value, tok, options) { - if (!tok.isPadded) { - return value; + static [Symbol.hasInstance] (instance) { + return instance && instance[kRequestRetryError] === true } - let diff = Math.abs(tok.maxLen - String(value).length); - let relax = options.relaxZeros !== false; + [kRequestRetryError] = true +} - switch (diff) { - case 0: - return ''; - case 1: - return relax ? '0?' : '0'; - case 2: - return relax ? '0{0,2}' : '00'; - default: { - return relax ? `0{0,${diff}}` : `0{${diff}}`; - } +const kResponseError = Symbol.for('undici.error.UND_ERR_RESPONSE') +class ResponseError extends UndiciError { + constructor (message, code, { headers, data }) { + super(message) + this.name = 'ResponseError' + this.message = message || 'Response error' + this.code = 'UND_ERR_RESPONSE' + this.statusCode = code + this.data = data + this.headers = headers + } + + static [Symbol.hasInstance] (instance) { + return instance && instance[kResponseError] === true } + + [kResponseError] = true } -/** - * Cache - */ +const kSecureProxyConnectionError = Symbol.for('undici.error.UND_ERR_PRX_TLS') +class SecureProxyConnectionError extends UndiciError { + constructor (cause, message, options) { + super(message, { cause, ...(options ?? {}) }) + this.name = 'SecureProxyConnectionError' + this.message = message || 'Secure Proxy Connection failed' + this.code = 'UND_ERR_PRX_TLS' + this.cause = cause + } -toRegexRange.cache = {}; -toRegexRange.clearCache = () => (toRegexRange.cache = {}); + static [Symbol.hasInstance] (instance) { + return instance && instance[kSecureProxyConnectionError] === true + } -/** - * Expose `toRegexRange` - */ + [kSecureProxyConnectionError] = true +} -module.exports = toRegexRange; +module.exports = { + AbortError, + HTTPParserError, + UndiciError, + HeadersTimeoutError, + HeadersOverflowError, + BodyTimeoutError, + RequestContentLengthMismatchError, + ConnectTimeoutError, + ResponseStatusCodeError, + InvalidArgumentError, + InvalidReturnValueError, + RequestAbortedError, + ClientDestroyedError, + ClientClosedError, + InformationalError, + SocketError, + NotSupportedError, + ResponseContentLengthMismatchError, + BalancedPoolMissingUpstreamError, + ResponseExceededMaxSizeError, + RequestRetryError, + ResponseError, + SecureProxyConnectionError +} /***/ }), -/***/ 2937: +/***/ 4053: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -module.exports = __nccwpck_require__(1043); -/***/ }), +const { + InvalidArgumentError, + NotSupportedError +} = __nccwpck_require__(329) +const assert = __nccwpck_require__(4589) +const { + isValidHTTPToken, + isValidHeaderValue, + isStream, + destroy, + isBuffer, + isFormDataLike, + isIterable, + isBlobLike, + buildURL, + validateHandler, + getServerName, + normalizedMethodRecords +} = __nccwpck_require__(7234) +const { channels } = __nccwpck_require__(7820) +const { headerNameLowerCasedRecord } = __nccwpck_require__(8429) -/***/ 1043: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { +// Verifies that a given path is valid does not contain control chars \x00 to \x20 +const invalidPathRegex = /[^\u0021-\u00ff]/ -"use strict"; +const kHandler = Symbol('handler') +class Request { + constructor (origin, { + path, + method, + body, + headers, + query, + idempotent, + blocking, + upgrade, + headersTimeout, + bodyTimeout, + reset, + throwOnError, + expectContinue, + servername + }, handler) { + if (typeof path !== 'string') { + throw new InvalidArgumentError('path must be a string') + } else if ( + path[0] !== '/' && + !(path.startsWith('http://') || path.startsWith('https://')) && + method !== 'CONNECT' + ) { + throw new InvalidArgumentError('path must be an absolute URL or start with a slash') + } else if (invalidPathRegex.test(path)) { + throw new InvalidArgumentError('invalid request path') + } -var net = __nccwpck_require__(9278); -var tls = __nccwpck_require__(4756); -var http = __nccwpck_require__(8611); -var https = __nccwpck_require__(5692); -var events = __nccwpck_require__(4434); -var assert = __nccwpck_require__(2613); -var util = __nccwpck_require__(9023); + if (typeof method !== 'string') { + throw new InvalidArgumentError('method must be a string') + } else if (normalizedMethodRecords[method] === undefined && !isValidHTTPToken(method)) { + throw new InvalidArgumentError('invalid request method') + } + if (upgrade && typeof upgrade !== 'string') { + throw new InvalidArgumentError('upgrade must be a string') + } -exports.httpOverHttp = httpOverHttp; -exports.httpsOverHttp = httpsOverHttp; -exports.httpOverHttps = httpOverHttps; -exports.httpsOverHttps = httpsOverHttps; + if (headersTimeout != null && (!Number.isFinite(headersTimeout) || headersTimeout < 0)) { + throw new InvalidArgumentError('invalid headersTimeout') + } + if (bodyTimeout != null && (!Number.isFinite(bodyTimeout) || bodyTimeout < 0)) { + throw new InvalidArgumentError('invalid bodyTimeout') + } -function httpOverHttp(options) { - var agent = new TunnelingAgent(options); - agent.request = http.request; - return agent; -} + if (reset != null && typeof reset !== 'boolean') { + throw new InvalidArgumentError('invalid reset') + } -function httpsOverHttp(options) { - var agent = new TunnelingAgent(options); - agent.request = http.request; - agent.createSocket = createSecureSocket; - agent.defaultPort = 443; - return agent; -} + if (expectContinue != null && typeof expectContinue !== 'boolean') { + throw new InvalidArgumentError('invalid expectContinue') + } -function httpOverHttps(options) { - var agent = new TunnelingAgent(options); - agent.request = https.request; - return agent; -} + this.headersTimeout = headersTimeout -function httpsOverHttps(options) { - var agent = new TunnelingAgent(options); - agent.request = https.request; - agent.createSocket = createSecureSocket; - agent.defaultPort = 443; - return agent; -} + this.bodyTimeout = bodyTimeout + this.throwOnError = throwOnError === true -function TunnelingAgent(options) { - var self = this; - self.options = options || {}; - self.proxyOptions = self.options.proxy || {}; - self.maxSockets = self.options.maxSockets || http.Agent.defaultMaxSockets; - self.requests = []; - self.sockets = []; + this.method = method - self.on('free', function onFree(socket, host, port, localAddress) { - var options = toOptions(host, port, localAddress); - for (var i = 0, len = self.requests.length; i < len; ++i) { - var pending = self.requests[i]; - if (pending.host === options.host && pending.port === options.port) { - // Detect the request to connect same origin server, - // reuse the connection. - self.requests.splice(i, 1); - pending.request.onSocket(socket); - return; + this.abort = null + + if (body == null) { + this.body = null + } else if (isStream(body)) { + this.body = body + + const rState = this.body._readableState + if (!rState || !rState.autoDestroy) { + this.endHandler = function autoDestroy () { + destroy(this) + } + this.body.on('end', this.endHandler) } - } - socket.destroy(); - self.removeSocket(socket); - }); -} -util.inherits(TunnelingAgent, events.EventEmitter); -TunnelingAgent.prototype.addRequest = function addRequest(req, host, port, localAddress) { - var self = this; - var options = mergeOptions({request: req}, self.options, toOptions(host, port, localAddress)); + this.errorHandler = err => { + if (this.abort) { + this.abort(err) + } else { + this.error = err + } + } + this.body.on('error', this.errorHandler) + } else if (isBuffer(body)) { + this.body = body.byteLength ? body : null + } else if (ArrayBuffer.isView(body)) { + this.body = body.buffer.byteLength ? Buffer.from(body.buffer, body.byteOffset, body.byteLength) : null + } else if (body instanceof ArrayBuffer) { + this.body = body.byteLength ? Buffer.from(body) : null + } else if (typeof body === 'string') { + this.body = body.length ? Buffer.from(body) : null + } else if (isFormDataLike(body) || isIterable(body) || isBlobLike(body)) { + this.body = body + } else { + throw new InvalidArgumentError('body must be a string, a Buffer, a Readable stream, an iterable, or an async iterable') + } - if (self.sockets.length >= this.maxSockets) { - // We are over limit so we'll add it to the queue. - self.requests.push(options); - return; - } + this.completed = false - // If we are under maxSockets create a new one. - self.createSocket(options, function(socket) { - socket.on('free', onFree); - socket.on('close', onCloseOrRemove); - socket.on('agentRemove', onCloseOrRemove); - req.onSocket(socket); + this.aborted = false - function onFree() { - self.emit('free', socket, options); - } + this.upgrade = upgrade || null - function onCloseOrRemove(err) { - self.removeSocket(socket); - socket.removeListener('free', onFree); - socket.removeListener('close', onCloseOrRemove); - socket.removeListener('agentRemove', onCloseOrRemove); - } - }); -}; + this.path = query ? buildURL(path, query) : path -TunnelingAgent.prototype.createSocket = function createSocket(options, cb) { - var self = this; - var placeholder = {}; - self.sockets.push(placeholder); + this.origin = origin - var connectOptions = mergeOptions({}, self.proxyOptions, { - method: 'CONNECT', - path: options.host + ':' + options.port, - agent: false, - headers: { - host: options.host + ':' + options.port - } - }); - if (options.localAddress) { - connectOptions.localAddress = options.localAddress; - } - if (connectOptions.proxyAuth) { - connectOptions.headers = connectOptions.headers || {}; - connectOptions.headers['Proxy-Authorization'] = 'Basic ' + - new Buffer(connectOptions.proxyAuth).toString('base64'); - } + this.idempotent = idempotent == null + ? method === 'HEAD' || method === 'GET' + : idempotent - debug('making CONNECT request'); - var connectReq = self.request(connectOptions); - connectReq.useChunkedEncodingByDefault = false; // for v0.6 - connectReq.once('response', onResponse); // for v0.6 - connectReq.once('upgrade', onUpgrade); // for v0.6 - connectReq.once('connect', onConnect); // for v0.7 or later - connectReq.once('error', onError); - connectReq.end(); + this.blocking = blocking == null ? false : blocking - function onResponse(res) { - // Very hacky. This is necessary to avoid http-parser leaks. - res.upgrade = true; - } + this.reset = reset == null ? null : reset - function onUpgrade(res, socket, head) { - // Hacky. - process.nextTick(function() { - onConnect(res, socket, head); - }); - } + this.host = null - function onConnect(res, socket, head) { - connectReq.removeAllListeners(); - socket.removeAllListeners(); + this.contentLength = null - if (res.statusCode !== 200) { - debug('tunneling socket could not be established, statusCode=%d', - res.statusCode); - socket.destroy(); - var error = new Error('tunneling socket could not be established, ' + - 'statusCode=' + res.statusCode); - error.code = 'ECONNRESET'; - options.request.emit('error', error); - self.removeSocket(placeholder); - return; - } - if (head.length > 0) { - debug('got illegal response body from proxy'); - socket.destroy(); - var error = new Error('got illegal response body from proxy'); - error.code = 'ECONNRESET'; - options.request.emit('error', error); - self.removeSocket(placeholder); - return; - } - debug('tunneling connection has established'); - self.sockets[self.sockets.indexOf(placeholder)] = socket; - return cb(socket); - } + this.contentType = null - function onError(cause) { - connectReq.removeAllListeners(); + this.headers = [] - debug('tunneling socket could not be established, cause=%s\n', - cause.message, cause.stack); - var error = new Error('tunneling socket could not be established, ' + - 'cause=' + cause.message); - error.code = 'ECONNRESET'; - options.request.emit('error', error); - self.removeSocket(placeholder); - } -}; + // Only for H2 + this.expectContinue = expectContinue != null ? expectContinue : false -TunnelingAgent.prototype.removeSocket = function removeSocket(socket) { - var pos = this.sockets.indexOf(socket) - if (pos === -1) { - return; - } - this.sockets.splice(pos, 1); + if (Array.isArray(headers)) { + if (headers.length % 2 !== 0) { + throw new InvalidArgumentError('headers array must be even') + } + for (let i = 0; i < headers.length; i += 2) { + processHeader(this, headers[i], headers[i + 1]) + } + } else if (headers && typeof headers === 'object') { + if (headers[Symbol.iterator]) { + for (const header of headers) { + if (!Array.isArray(header) || header.length !== 2) { + throw new InvalidArgumentError('headers must be in key-value pair format') + } + processHeader(this, header[0], header[1]) + } + } else { + const keys = Object.keys(headers) + for (let i = 0; i < keys.length; ++i) { + processHeader(this, keys[i], headers[keys[i]]) + } + } + } else if (headers != null) { + throw new InvalidArgumentError('headers must be an object or an array') + } - var pending = this.requests.shift(); - if (pending) { - // If we have pending requests and a socket gets closed a new one - // needs to be created to take over in the pool for the one that closed. - this.createSocket(pending, function(socket) { - pending.request.onSocket(socket); - }); - } -}; + validateHandler(handler, method, upgrade) -function createSecureSocket(options, cb) { - var self = this; - TunnelingAgent.prototype.createSocket.call(self, options, function(socket) { - var hostHeader = options.request.getHeader('host'); - var tlsOptions = mergeOptions({}, self.options, { - socket: socket, - servername: hostHeader ? hostHeader.replace(/:.*$/, '') : options.host - }); + this.servername = servername || getServerName(this.host) - // 0 is dummy port for v0.6 - var secureSocket = tls.connect(0, tlsOptions); - self.sockets[self.sockets.indexOf(socket)] = secureSocket; - cb(secureSocket); - }); -} + this[kHandler] = handler + if (channels.create.hasSubscribers) { + channels.create.publish({ request: this }) + } + } -function toOptions(host, port, localAddress) { - if (typeof host === 'string') { // since v0.10 - return { - host: host, - port: port, - localAddress: localAddress - }; + onBodySent (chunk) { + if (this[kHandler].onBodySent) { + try { + return this[kHandler].onBodySent(chunk) + } catch (err) { + this.abort(err) + } + } } - return host; // for v0.11 or later -} -function mergeOptions(target) { - for (var i = 1, len = arguments.length; i < len; ++i) { - var overrides = arguments[i]; - if (typeof overrides === 'object') { - var keys = Object.keys(overrides); - for (var j = 0, keyLen = keys.length; j < keyLen; ++j) { - var k = keys[j]; - if (overrides[k] !== undefined) { - target[k] = overrides[k]; - } + onRequestSent () { + if (channels.bodySent.hasSubscribers) { + channels.bodySent.publish({ request: this }) + } + + if (this[kHandler].onRequestSent) { + try { + return this[kHandler].onRequestSent() + } catch (err) { + this.abort(err) } } } - return target; -} + onConnect (abort) { + assert(!this.aborted) + assert(!this.completed) -var debug; -if (process.env.NODE_DEBUG && /\btunnel\b/.test(process.env.NODE_DEBUG)) { - debug = function() { - var args = Array.prototype.slice.call(arguments); - if (typeof args[0] === 'string') { - args[0] = 'TUNNEL: ' + args[0]; + if (this.error) { + abort(this.error) } else { - args.unshift('TUNNEL:'); + this.abort = abort + return this[kHandler].onConnect(abort) } - console.error.apply(console, args); } -} else { - debug = function() {}; -} -exports.debug = debug; // for test + onResponseStarted () { + return this[kHandler].onResponseStarted?.() + } -/***/ }), + onHeaders (statusCode, headers, resume, statusText) { + assert(!this.aborted) + assert(!this.completed) -/***/ 9153: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + if (channels.headers.hasSubscribers) { + channels.headers.publish({ request: this, response: { statusCode, headers, statusText } }) + } -"use strict"; + try { + return this[kHandler].onHeaders(statusCode, headers, resume, statusText) + } catch (err) { + this.abort(err) + } + } + onData (chunk) { + assert(!this.aborted) + assert(!this.completed) -const Client = __nccwpck_require__(6466) -const Dispatcher = __nccwpck_require__(8016) -const errors = __nccwpck_require__(6738) -const Pool = __nccwpck_require__(7279) -const BalancedPool = __nccwpck_require__(3700) -const Agent = __nccwpck_require__(2308) -const util = __nccwpck_require__(5069) -const { InvalidArgumentError } = errors -const api = __nccwpck_require__(7450) -const buildConnector = __nccwpck_require__(9323) -const MockClient = __nccwpck_require__(9518) -const MockAgent = __nccwpck_require__(2280) -const MockPool = __nccwpck_require__(2947) -const mockErrors = __nccwpck_require__(3866) -const ProxyAgent = __nccwpck_require__(4469) -const RetryHandler = __nccwpck_require__(1698) -const { getGlobalDispatcher, setGlobalDispatcher } = __nccwpck_require__(5334) -const DecoratorHandler = __nccwpck_require__(507) -const RedirectHandler = __nccwpck_require__(6858) -const createRedirectInterceptor = __nccwpck_require__(7646) - -let hasCrypto -try { - __nccwpck_require__(6982) - hasCrypto = true -} catch { - hasCrypto = false -} + try { + return this[kHandler].onData(chunk) + } catch (err) { + this.abort(err) + return false + } + } -Object.assign(Dispatcher.prototype, api) + onUpgrade (statusCode, headers, socket) { + assert(!this.aborted) + assert(!this.completed) -module.exports.Dispatcher = Dispatcher -module.exports.Client = Client -module.exports.Pool = Pool -module.exports.BalancedPool = BalancedPool -module.exports.Agent = Agent -module.exports.ProxyAgent = ProxyAgent -module.exports.RetryHandler = RetryHandler + return this[kHandler].onUpgrade(statusCode, headers, socket) + } -module.exports.DecoratorHandler = DecoratorHandler -module.exports.RedirectHandler = RedirectHandler -module.exports.createRedirectInterceptor = createRedirectInterceptor + onComplete (trailers) { + this.onFinally() -module.exports.buildConnector = buildConnector -module.exports.errors = errors + assert(!this.aborted) -function makeDispatcher (fn) { - return (url, opts, handler) => { - if (typeof opts === 'function') { - handler = opts - opts = null + this.completed = true + if (channels.trailers.hasSubscribers) { + channels.trailers.publish({ request: this, trailers }) } - if (!url || (typeof url !== 'string' && typeof url !== 'object' && !(url instanceof URL))) { - throw new InvalidArgumentError('invalid url') + try { + return this[kHandler].onComplete(trailers) + } catch (err) { + // TODO (fix): This might be a bad idea? + this.onError(err) } + } - if (opts != null && typeof opts !== 'object') { - throw new InvalidArgumentError('invalid opts') - } + onError (error) { + this.onFinally() - if (opts && opts.path != null) { - if (typeof opts.path !== 'string') { - throw new InvalidArgumentError('invalid opts.path') - } + if (channels.error.hasSubscribers) { + channels.error.publish({ request: this, error }) + } - let path = opts.path - if (!opts.path.startsWith('/')) { - path = `/${path}` - } + if (this.aborted) { + return + } + this.aborted = true - url = new URL(util.parseOrigin(url).origin + path) - } else { - if (!opts) { - opts = typeof url === 'object' ? url : {} - } + return this[kHandler].onError(error) + } - url = util.parseURL(url) + onFinally () { + if (this.errorHandler) { + this.body.off('error', this.errorHandler) + this.errorHandler = null } - const { agent, dispatcher = getGlobalDispatcher() } = opts - - if (agent) { - throw new InvalidArgumentError('unsupported opts.agent. Did you mean opts.client?') + if (this.endHandler) { + this.body.off('end', this.endHandler) + this.endHandler = null } + } - return fn.call(dispatcher, { - ...opts, - origin: url.origin, - path: url.search ? `${url.pathname}${url.search}` : url.pathname, - method: opts.method || (opts.body ? 'PUT' : 'GET') - }, handler) + addHeader (key, value) { + processHeader(this, key, value) + return this } } -module.exports.setGlobalDispatcher = setGlobalDispatcher -module.exports.getGlobalDispatcher = getGlobalDispatcher +function processHeader (request, key, val) { + if (val && (typeof val === 'object' && !Array.isArray(val))) { + throw new InvalidArgumentError(`invalid ${key} header`) + } else if (val === undefined) { + return + } + + let headerName = headerNameLowerCasedRecord[key] -if (util.nodeMajor > 16 || (util.nodeMajor === 16 && util.nodeMinor >= 8)) { - let fetchImpl = null - module.exports.fetch = async function fetch (resource) { - if (!fetchImpl) { - fetchImpl = (__nccwpck_require__(8130).fetch) + if (headerName === undefined) { + headerName = key.toLowerCase() + if (headerNameLowerCasedRecord[headerName] === undefined && !isValidHTTPToken(headerName)) { + throw new InvalidArgumentError('invalid header key') } + } - try { - return await fetchImpl(...arguments) - } catch (err) { - if (typeof err === 'object') { - Error.captureStackTrace(err, this) + if (Array.isArray(val)) { + const arr = [] + for (let i = 0; i < val.length; i++) { + if (typeof val[i] === 'string') { + if (!isValidHeaderValue(val[i])) { + throw new InvalidArgumentError(`invalid ${key} header`) + } + arr.push(val[i]) + } else if (val[i] === null) { + arr.push('') + } else if (typeof val[i] === 'object') { + throw new InvalidArgumentError(`invalid ${key} header`) + } else { + arr.push(`${val[i]}`) } - - throw err } + val = arr + } else if (typeof val === 'string') { + if (!isValidHeaderValue(val)) { + throw new InvalidArgumentError(`invalid ${key} header`) + } + } else if (val === null) { + val = '' + } else { + val = `${val}` } - module.exports.Headers = __nccwpck_require__(3640).Headers - module.exports.Response = __nccwpck_require__(5743).Response - module.exports.Request = __nccwpck_require__(4555).Request - module.exports.FormData = __nccwpck_require__(322).FormData - module.exports.File = __nccwpck_require__(7206).File - module.exports.FileReader = __nccwpck_require__(695).FileReader - - const { setGlobalOrigin, getGlobalOrigin } = __nccwpck_require__(4407) - module.exports.setGlobalOrigin = setGlobalOrigin - module.exports.getGlobalOrigin = getGlobalOrigin - - const { CacheStorage } = __nccwpck_require__(265) - const { kConstruct } = __nccwpck_require__(4193) + if (request.host === null && headerName === 'host') { + if (typeof val !== 'string') { + throw new InvalidArgumentError('invalid host header') + } + // Consumed by Client + request.host = val + } else if (request.contentLength === null && headerName === 'content-length') { + request.contentLength = parseInt(val, 10) + if (!Number.isFinite(request.contentLength)) { + throw new InvalidArgumentError('invalid content-length header') + } + } else if (request.contentType === null && headerName === 'content-type') { + request.contentType = val + request.headers.push(key, val) + } else if (headerName === 'transfer-encoding' || headerName === 'keep-alive' || headerName === 'upgrade') { + throw new InvalidArgumentError(`invalid ${headerName} header`) + } else if (headerName === 'connection') { + const value = typeof val === 'string' ? val.toLowerCase() : null + if (value !== 'close' && value !== 'keep-alive') { + throw new InvalidArgumentError('invalid connection header') + } - // Cache & CacheStorage are tightly coupled with fetch. Even if it may run - // in an older version of Node, it doesn't have any use without fetch. - module.exports.caches = new CacheStorage(kConstruct) + if (value === 'close') { + request.reset = true + } + } else if (headerName === 'expect') { + throw new NotSupportedError('expect header not supported') + } else { + request.headers.push(key, val) + } } -if (util.nodeMajor >= 16) { - const { deleteCookie, getCookies, getSetCookies, setCookie } = __nccwpck_require__(1433) - - module.exports.deleteCookie = deleteCookie - module.exports.getCookies = getCookies - module.exports.getSetCookies = getSetCookies - module.exports.setCookie = setCookie +module.exports = Request - const { parseMIMEType, serializeAMimeType } = __nccwpck_require__(4955) - module.exports.parseMIMEType = parseMIMEType - module.exports.serializeAMimeType = serializeAMimeType -} +/***/ }), -if (util.nodeMajor >= 18 && hasCrypto) { - const { WebSocket } = __nccwpck_require__(5778) +/***/ 7417: +/***/ ((module) => { - module.exports.WebSocket = WebSocket +module.exports = { + kClose: Symbol('close'), + kDestroy: Symbol('destroy'), + kDispatch: Symbol('dispatch'), + kUrl: Symbol('url'), + kWriting: Symbol('writing'), + kResuming: Symbol('resuming'), + kQueue: Symbol('queue'), + kConnect: Symbol('connect'), + kConnecting: Symbol('connecting'), + kKeepAliveDefaultTimeout: Symbol('default keep alive timeout'), + kKeepAliveMaxTimeout: Symbol('max keep alive timeout'), + kKeepAliveTimeoutThreshold: Symbol('keep alive timeout threshold'), + kKeepAliveTimeoutValue: Symbol('keep alive timeout'), + kKeepAlive: Symbol('keep alive'), + kHeadersTimeout: Symbol('headers timeout'), + kBodyTimeout: Symbol('body timeout'), + kServerName: Symbol('server name'), + kLocalAddress: Symbol('local address'), + kHost: Symbol('host'), + kNoRef: Symbol('no ref'), + kBodyUsed: Symbol('used'), + kBody: Symbol('abstracted request body'), + kRunning: Symbol('running'), + kBlocking: Symbol('blocking'), + kPending: Symbol('pending'), + kSize: Symbol('size'), + kBusy: Symbol('busy'), + kQueued: Symbol('queued'), + kFree: Symbol('free'), + kConnected: Symbol('connected'), + kClosed: Symbol('closed'), + kNeedDrain: Symbol('need drain'), + kReset: Symbol('reset'), + kDestroyed: Symbol.for('nodejs.stream.destroyed'), + kResume: Symbol('resume'), + kOnError: Symbol('on error'), + kMaxHeadersSize: Symbol('max headers size'), + kRunningIdx: Symbol('running index'), + kPendingIdx: Symbol('pending index'), + kError: Symbol('error'), + kClients: Symbol('clients'), + kClient: Symbol('client'), + kParser: Symbol('parser'), + kOnDestroyed: Symbol('destroy callbacks'), + kPipelining: Symbol('pipelining'), + kSocket: Symbol('socket'), + kHostHeader: Symbol('host header'), + kConnector: Symbol('connector'), + kStrictContentLength: Symbol('strict content length'), + kMaxRedirections: Symbol('maxRedirections'), + kMaxRequests: Symbol('maxRequestsPerClient'), + kProxy: Symbol('proxy agent options'), + kCounter: Symbol('socket request counter'), + kInterceptors: Symbol('dispatch interceptors'), + kMaxResponseSize: Symbol('max response size'), + kHTTP2Session: Symbol('http2Session'), + kHTTP2SessionState: Symbol('http2Session state'), + kRetryHandlerDefaultRetry: Symbol('retry agent default retry'), + kConstruct: Symbol('constructable'), + kListeners: Symbol('listeners'), + kHTTPContext: Symbol('http context'), + kMaxConcurrentStreams: Symbol('max concurrent streams'), + kNoProxyAgent: Symbol('no proxy agent'), + kHttpProxyAgent: Symbol('http proxy agent'), + kHttpsProxyAgent: Symbol('https proxy agent') } -module.exports.request = makeDispatcher(api.request) -module.exports.stream = makeDispatcher(api.stream) -module.exports.pipeline = makeDispatcher(api.pipeline) -module.exports.connect = makeDispatcher(api.connect) -module.exports.upgrade = makeDispatcher(api.upgrade) - -module.exports.MockClient = MockClient -module.exports.MockPool = MockPool -module.exports.MockAgent = MockAgent -module.exports.mockErrors = mockErrors - /***/ }), -/***/ 2308: +/***/ 550: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; - - -const { InvalidArgumentError } = __nccwpck_require__(6738) -const { kClients, kRunning, kClose, kDestroy, kDispatch, kInterceptors } = __nccwpck_require__(1028) -const DispatcherBase = __nccwpck_require__(7172) -const Pool = __nccwpck_require__(7279) -const Client = __nccwpck_require__(6466) -const util = __nccwpck_require__(5069) -const createRedirectInterceptor = __nccwpck_require__(7646) -const { WeakRef, FinalizationRegistry } = __nccwpck_require__(199)() - -const kOnConnect = Symbol('onConnect') -const kOnDisconnect = Symbol('onDisconnect') -const kOnConnectionError = Symbol('onConnectionError') -const kMaxRedirections = Symbol('maxRedirections') -const kOnDrain = Symbol('onDrain') -const kFactory = Symbol('factory') -const kFinalizer = Symbol('finalizer') -const kOptions = Symbol('options') -function defaultFactory (origin, opts) { - return opts && opts.connections === 1 - ? new Client(origin, opts) - : new Pool(origin, opts) -} -class Agent extends DispatcherBase { - constructor ({ factory = defaultFactory, maxRedirections = 0, connect, ...options } = {}) { - super() +const { + wellknownHeaderNames, + headerNameLowerCasedRecord +} = __nccwpck_require__(8429) - if (typeof factory !== 'function') { - throw new InvalidArgumentError('factory must be a function.') +class TstNode { + /** @type {any} */ + value = null + /** @type {null | TstNode} */ + left = null + /** @type {null | TstNode} */ + middle = null + /** @type {null | TstNode} */ + right = null + /** @type {number} */ + code + /** + * @param {string} key + * @param {any} value + * @param {number} index + */ + constructor (key, value, index) { + if (index === undefined || index >= key.length) { + throw new TypeError('Unreachable') } - - if (connect != null && typeof connect !== 'function' && typeof connect !== 'object') { - throw new InvalidArgumentError('connect must be a function or an object') + const code = this.code = key.charCodeAt(index) + // check code is ascii string + if (code > 0x7F) { + throw new TypeError('key must be ascii string') } - - if (!Number.isInteger(maxRedirections) || maxRedirections < 0) { - throw new InvalidArgumentError('maxRedirections must be a positive number') + if (key.length !== ++index) { + this.middle = new TstNode(key, value, index) + } else { + this.value = value } + } - if (connect && typeof connect !== 'function') { - connect = { ...connect } + /** + * @param {string} key + * @param {any} value + */ + add (key, value) { + const length = key.length + if (length === 0) { + throw new TypeError('Unreachable') } - - this[kInterceptors] = options.interceptors && options.interceptors.Agent && Array.isArray(options.interceptors.Agent) - ? options.interceptors.Agent - : [createRedirectInterceptor({ maxRedirections })] - - this[kOptions] = { ...util.deepClone(options), connect } - this[kOptions].interceptors = options.interceptors - ? { ...options.interceptors } - : undefined - this[kMaxRedirections] = maxRedirections - this[kFactory] = factory - this[kClients] = new Map() - this[kFinalizer] = new FinalizationRegistry(/* istanbul ignore next: gc is undeterministic */ key => { - const ref = this[kClients].get(key) - if (ref !== undefined && ref.deref() === undefined) { - this[kClients].delete(key) + let index = 0 + let node = this + while (true) { + const code = key.charCodeAt(index) + // check code is ascii string + if (code > 0x7F) { + throw new TypeError('key must be ascii string') + } + if (node.code === code) { + if (length === ++index) { + node.value = value + break + } else if (node.middle !== null) { + node = node.middle + } else { + node.middle = new TstNode(key, value, index) + break + } + } else if (node.code < code) { + if (node.left !== null) { + node = node.left + } else { + node.left = new TstNode(key, value, index) + break + } + } else if (node.right !== null) { + node = node.right + } else { + node.right = new TstNode(key, value, index) + break } - }) - - const agent = this - - this[kOnDrain] = (origin, targets) => { - agent.emit('drain', origin, [agent, ...targets]) - } - - this[kOnConnect] = (origin, targets) => { - agent.emit('connect', origin, [agent, ...targets]) - } - - this[kOnDisconnect] = (origin, targets, err) => { - agent.emit('disconnect', origin, [agent, ...targets], err) - } - - this[kOnConnectionError] = (origin, targets, err) => { - agent.emit('connectionError', origin, [agent, ...targets], err) } } - get [kRunning] () { - let ret = 0 - for (const ref of this[kClients].values()) { - const client = ref.deref() - /* istanbul ignore next: gc is undeterministic */ - if (client) { - ret += client[kRunning] + /** + * @param {Uint8Array} key + * @return {TstNode | null} + */ + search (key) { + const keylength = key.length + let index = 0 + let node = this + while (node !== null && index < keylength) { + let code = key[index] + // A-Z + // First check if it is bigger than 0x5a. + // Lowercase letters have higher char codes than uppercase ones. + // Also we assume that headers will mostly contain lowercase characters. + if (code <= 0x5a && code >= 0x41) { + // Lowercase for uppercase. + code |= 32 + } + while (node !== null) { + if (code === node.code) { + if (keylength === ++index) { + // Returns Node since it is the last key. + return node + } + node = node.middle + break + } + node = node.code < code ? node.left : node.right } } - return ret + return null } +} - [kDispatch] (opts, handler) { - let key - if (opts.origin && (typeof opts.origin === 'string' || opts.origin instanceof URL)) { - key = String(opts.origin) - } else { - throw new InvalidArgumentError('opts.origin must be a non-empty string or URL.') - } - - const ref = this[kClients].get(key) - - let dispatcher = ref ? ref.deref() : null - if (!dispatcher) { - dispatcher = this[kFactory](opts.origin, this[kOptions]) - .on('drain', this[kOnDrain]) - .on('connect', this[kOnConnect]) - .on('disconnect', this[kOnDisconnect]) - .on('connectionError', this[kOnConnectionError]) +class TernarySearchTree { + /** @type {TstNode | null} */ + node = null - this[kClients].set(key, new WeakRef(dispatcher)) - this[kFinalizer].register(dispatcher, key) + /** + * @param {string} key + * @param {any} value + * */ + insert (key, value) { + if (this.node === null) { + this.node = new TstNode(key, value, 0) + } else { + this.node.add(key, value) } - - return dispatcher.dispatch(opts, handler) } - async [kClose] () { - const closePromises = [] - for (const ref of this[kClients].values()) { - const client = ref.deref() - /* istanbul ignore else: gc is undeterministic */ - if (client) { - closePromises.push(client.close()) - } - } - - await Promise.all(closePromises) + /** + * @param {Uint8Array} key + * @return {any} + */ + lookup (key) { + return this.node?.search(key)?.value ?? null } +} - async [kDestroy] (err) { - const destroyPromises = [] - for (const ref of this[kClients].values()) { - const client = ref.deref() - /* istanbul ignore else: gc is undeterministic */ - if (client) { - destroyPromises.push(client.destroy(err)) - } - } +const tree = new TernarySearchTree() - await Promise.all(destroyPromises) - } +for (let i = 0; i < wellknownHeaderNames.length; ++i) { + const key = headerNameLowerCasedRecord[wellknownHeaderNames[i]] + tree.insert(key, key) } -module.exports = Agent +module.exports = { + TernarySearchTree, + tree +} /***/ }), -/***/ 9761: +/***/ 7234: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -const { addAbortListener } = __nccwpck_require__(5069) -const { RequestAbortedError } = __nccwpck_require__(6738) - -const kListener = Symbol('kListener') -const kSignal = Symbol('kSignal') -function abort (self) { - if (self.abort) { - self.abort() - } else { - self.onError(new RequestAbortedError()) - } -} -function addSignal (self, signal) { - self[kSignal] = null - self[kListener] = null +const assert = __nccwpck_require__(4589) +const { kDestroyed, kBodyUsed, kListeners, kBody } = __nccwpck_require__(7417) +const { IncomingMessage } = __nccwpck_require__(7067) +const stream = __nccwpck_require__(7075) +const net = __nccwpck_require__(7030) +const { Blob } = __nccwpck_require__(4573) +const nodeUtil = __nccwpck_require__(7975) +const { stringify } = __nccwpck_require__(1792) +const { EventEmitter: EE } = __nccwpck_require__(8474) +const { InvalidArgumentError } = __nccwpck_require__(329) +const { headerNameLowerCasedRecord } = __nccwpck_require__(8429) +const { tree } = __nccwpck_require__(550) - if (!signal) { - return - } +const [nodeMajor, nodeMinor] = process.versions.node.split('.').map(v => Number(v)) - if (signal.aborted) { - abort(self) - return +class BodyAsyncIterable { + constructor (body) { + this[kBody] = body + this[kBodyUsed] = false } - self[kSignal] = signal - self[kListener] = () => { - abort(self) + async * [Symbol.asyncIterator] () { + assert(!this[kBodyUsed], 'disturbed') + this[kBodyUsed] = true + yield * this[kBody] } - - addAbortListener(self[kSignal], self[kListener]) } -function removeSignal (self) { - if (!self[kSignal]) { - return - } +function wrapRequestBody (body) { + if (isStream(body)) { + // TODO (fix): Provide some way for the user to cache the file to e.g. /tmp + // so that it can be dispatched again? + // TODO (fix): Do we need 100-expect support to provide a way to do this properly? + if (bodyLength(body) === 0) { + body + .on('data', function () { + assert(false) + }) + } - if ('removeEventListener' in self[kSignal]) { - self[kSignal].removeEventListener('abort', self[kListener]) + if (typeof body.readableDidRead !== 'boolean') { + body[kBodyUsed] = false + EE.prototype.on.call(body, 'data', function () { + this[kBodyUsed] = true + }) + } + + return body + } else if (body && typeof body.pipeTo === 'function') { + // TODO (fix): We can't access ReadableStream internal state + // to determine whether or not it has been disturbed. This is just + // a workaround. + return new BodyAsyncIterable(body) + } else if ( + body && + typeof body !== 'string' && + !ArrayBuffer.isView(body) && + isIterable(body) + ) { + // TODO: Should we allow re-using iterable if !this.opts.idempotent + // or through some other flag? + return new BodyAsyncIterable(body) } else { - self[kSignal].removeListener('abort', self[kListener]) + return body } - - self[kSignal] = null - self[kListener] = null -} - -module.exports = { - addSignal, - removeSignal } +function nop () {} -/***/ }), - -/***/ 6829: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -"use strict"; - - -const { AsyncResource } = __nccwpck_require__(290) -const { InvalidArgumentError, RequestAbortedError, SocketError } = __nccwpck_require__(6738) -const util = __nccwpck_require__(5069) -const { addSignal, removeSignal } = __nccwpck_require__(9761) +function isStream (obj) { + return obj && typeof obj === 'object' && typeof obj.pipe === 'function' && typeof obj.on === 'function' +} -class ConnectHandler extends AsyncResource { - constructor (opts, callback) { - if (!opts || typeof opts !== 'object') { - throw new InvalidArgumentError('invalid opts') - } +// based on https://github.com/node-fetch/fetch-blob/blob/8ab587d34080de94140b54f07168451e7d0b655e/index.js#L229-L241 (MIT License) +function isBlobLike (object) { + if (object === null) { + return false + } else if (object instanceof Blob) { + return true + } else if (typeof object !== 'object') { + return false + } else { + const sTag = object[Symbol.toStringTag] - if (typeof callback !== 'function') { - throw new InvalidArgumentError('invalid callback') - } + return (sTag === 'Blob' || sTag === 'File') && ( + ('stream' in object && typeof object.stream === 'function') || + ('arrayBuffer' in object && typeof object.arrayBuffer === 'function') + ) + } +} - const { signal, opaque, responseHeaders } = opts +function buildURL (url, queryParams) { + if (url.includes('?') || url.includes('#')) { + throw new Error('Query params cannot be passed when url already contains "?" or "#".') + } - if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { - throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') - } + const stringified = stringify(queryParams) - super('UNDICI_CONNECT') + if (stringified) { + url += '?' + stringified + } - this.opaque = opaque || null - this.responseHeaders = responseHeaders || null - this.callback = callback - this.abort = null + return url +} - addSignal(this, signal) - } +function isValidPort (port) { + const value = parseInt(port, 10) + return ( + value === Number(port) && + value >= 0 && + value <= 65535 + ) +} - onConnect (abort, context) { - if (!this.callback) { - throw new RequestAbortedError() +function isHttpOrHttpsPrefixed (value) { + return ( + value != null && + value[0] === 'h' && + value[1] === 't' && + value[2] === 't' && + value[3] === 'p' && + ( + value[4] === ':' || + ( + value[4] === 's' && + value[5] === ':' + ) + ) + ) +} + +function parseURL (url) { + if (typeof url === 'string') { + url = new URL(url) + + if (!isHttpOrHttpsPrefixed(url.origin || url.protocol)) { + throw new InvalidArgumentError('Invalid URL protocol: the URL must start with `http:` or `https:`.') } - this.abort = abort - this.context = context + return url } - onHeaders () { - throw new SocketError('bad connect', null) + if (!url || typeof url !== 'object') { + throw new InvalidArgumentError('Invalid URL: The URL argument must be a non-null object.') } - onUpgrade (statusCode, rawHeaders, socket) { - const { callback, opaque, context } = this + if (!(url instanceof URL)) { + if (url.port != null && url.port !== '' && isValidPort(url.port) === false) { + throw new InvalidArgumentError('Invalid URL: port must be a valid integer or a string representation of an integer.') + } - removeSignal(this) + if (url.path != null && typeof url.path !== 'string') { + throw new InvalidArgumentError('Invalid URL path: the path must be a string or null/undefined.') + } - this.callback = null + if (url.pathname != null && typeof url.pathname !== 'string') { + throw new InvalidArgumentError('Invalid URL pathname: the pathname must be a string or null/undefined.') + } - let headers = rawHeaders - // Indicates is an HTTP2Session - if (headers != null) { - headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) + if (url.hostname != null && typeof url.hostname !== 'string') { + throw new InvalidArgumentError('Invalid URL hostname: the hostname must be a string or null/undefined.') } - this.runInAsyncScope(callback, null, null, { - statusCode, - headers, - socket, - opaque, - context - }) - } + if (url.origin != null && typeof url.origin !== 'string') { + throw new InvalidArgumentError('Invalid URL origin: the origin must be a string or null/undefined.') + } - onError (err) { - const { callback, opaque } = this + if (!isHttpOrHttpsPrefixed(url.origin || url.protocol)) { + throw new InvalidArgumentError('Invalid URL protocol: the URL must start with `http:` or `https:`.') + } - removeSignal(this) + const port = url.port != null + ? url.port + : (url.protocol === 'https:' ? 443 : 80) + let origin = url.origin != null + ? url.origin + : `${url.protocol || ''}//${url.hostname || ''}:${port}` + let path = url.path != null + ? url.path + : `${url.pathname || ''}${url.search || ''}` - if (callback) { - this.callback = null - queueMicrotask(() => { - this.runInAsyncScope(callback, null, err, { opaque }) - }) + if (origin[origin.length - 1] === '/') { + origin = origin.slice(0, origin.length - 1) } - } -} - -function connect (opts, callback) { - if (callback === undefined) { - return new Promise((resolve, reject) => { - connect.call(this, opts, (err, data) => { - return err ? reject(err) : resolve(data) - }) - }) - } - try { - const connectHandler = new ConnectHandler(opts, callback) - this.dispatch({ ...opts, method: 'CONNECT' }, connectHandler) - } catch (err) { - if (typeof callback !== 'function') { - throw err + if (path && path[0] !== '/') { + path = `/${path}` } - const opaque = opts && opts.opaque - queueMicrotask(() => callback(err, { opaque })) + // new URL(path, origin) is unsafe when `path` contains an absolute URL + // From https://developer.mozilla.org/en-US/docs/Web/API/URL/URL: + // If first parameter is a relative URL, second param is required, and will be used as the base URL. + // If first parameter is an absolute URL, a given second param will be ignored. + return new URL(`${origin}${path}`) } -} -module.exports = connect + if (!isHttpOrHttpsPrefixed(url.origin || url.protocol)) { + throw new InvalidArgumentError('Invalid URL protocol: the URL must start with `http:` or `https:`.') + } + return url +} -/***/ }), +function parseOrigin (url) { + url = parseURL(url) -/***/ 4994: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + if (url.pathname !== '/' || url.search || url.hash) { + throw new InvalidArgumentError('invalid url') + } -"use strict"; + return url +} +function getHostname (host) { + if (host[0] === '[') { + const idx = host.indexOf(']') -const { - Readable, - Duplex, - PassThrough -} = __nccwpck_require__(2203) -const { - InvalidArgumentError, - InvalidReturnValueError, - RequestAbortedError -} = __nccwpck_require__(6738) -const util = __nccwpck_require__(5069) -const { AsyncResource } = __nccwpck_require__(290) -const { addSignal, removeSignal } = __nccwpck_require__(9761) -const assert = __nccwpck_require__(2613) + assert(idx !== -1) + return host.substring(1, idx) + } -const kResume = Symbol('resume') + const idx = host.indexOf(':') + if (idx === -1) return host -class PipelineRequest extends Readable { - constructor () { - super({ autoDestroy: true }) + return host.substring(0, idx) +} - this[kResume] = null +// IP addresses are not valid server names per RFC6066 +// > Currently, the only server names supported are DNS hostnames +function getServerName (host) { + if (!host) { + return null } - _read () { - const { [kResume]: resume } = this + assert(typeof host === 'string') - if (resume) { - this[kResume] = null - resume() - } + const servername = getHostname(host) + if (net.isIP(servername)) { + return '' } - _destroy (err, callback) { - this._read() + return servername +} - callback(err) - } +function deepClone (obj) { + return JSON.parse(JSON.stringify(obj)) } -class PipelineResponse extends Readable { - constructor (resume) { - super({ autoDestroy: true }) - this[kResume] = resume - } +function isAsyncIterable (obj) { + return !!(obj != null && typeof obj[Symbol.asyncIterator] === 'function') +} - _read () { - this[kResume]() +function isIterable (obj) { + return !!(obj != null && (typeof obj[Symbol.iterator] === 'function' || typeof obj[Symbol.asyncIterator] === 'function')) +} + +function bodyLength (body) { + if (body == null) { + return 0 + } else if (isStream(body)) { + const state = body._readableState + return state && state.objectMode === false && state.ended === true && Number.isFinite(state.length) + ? state.length + : null + } else if (isBlobLike(body)) { + return body.size != null ? body.size : null + } else if (isBuffer(body)) { + return body.byteLength } - _destroy (err, callback) { - if (!err && !this._readableState.endEmitted) { - err = new RequestAbortedError() - } + return null +} - callback(err) - } +function isDestroyed (body) { + return body && !!(body.destroyed || body[kDestroyed] || (stream.isDestroyed?.(body))) } -class PipelineHandler extends AsyncResource { - constructor (opts, handler) { - if (!opts || typeof opts !== 'object') { - throw new InvalidArgumentError('invalid opts') - } +function destroy (stream, err) { + if (stream == null || !isStream(stream) || isDestroyed(stream)) { + return + } - if (typeof handler !== 'function') { - throw new InvalidArgumentError('invalid handler') + if (typeof stream.destroy === 'function') { + if (Object.getPrototypeOf(stream).constructor === IncomingMessage) { + // See: https://github.com/nodejs/node/pull/38505/files + stream.socket = null } - const { signal, method, opaque, onInfo, responseHeaders } = opts + stream.destroy(err) + } else if (err) { + queueMicrotask(() => { + stream.emit('error', err) + }) + } - if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { - throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') - } + if (stream.destroyed !== true) { + stream[kDestroyed] = true + } +} - if (method === 'CONNECT') { - throw new InvalidArgumentError('invalid method') - } +const KEEPALIVE_TIMEOUT_EXPR = /timeout=(\d+)/ +function parseKeepAliveTimeout (val) { + const m = val.toString().match(KEEPALIVE_TIMEOUT_EXPR) + return m ? parseInt(m[1], 10) * 1000 : null +} - if (onInfo && typeof onInfo !== 'function') { - throw new InvalidArgumentError('invalid onInfo callback') - } +/** + * Retrieves a header name and returns its lowercase value. + * @param {string | Buffer} value Header name + * @returns {string} + */ +function headerNameToString (value) { + return typeof value === 'string' + ? headerNameLowerCasedRecord[value] ?? value.toLowerCase() + : tree.lookup(value) ?? value.toString('latin1').toLowerCase() +} - super('UNDICI_PIPELINE') +/** + * Receive the buffer as a string and return its lowercase value. + * @param {Buffer} value Header name + * @returns {string} + */ +function bufferToLowerCasedHeaderName (value) { + return tree.lookup(value) ?? value.toString('latin1').toLowerCase() +} - this.opaque = opaque || null - this.responseHeaders = responseHeaders || null - this.handler = handler - this.abort = null - this.context = null - this.onInfo = onInfo || null +/** + * @param {Record | (Buffer | string | (Buffer | string)[])[]} headers + * @param {Record} [obj] + * @returns {Record} + */ +function parseHeaders (headers, obj) { + if (obj === undefined) obj = {} + for (let i = 0; i < headers.length; i += 2) { + const key = headerNameToString(headers[i]) + let val = obj[key] - this.req = new PipelineRequest().on('error', util.nop) + if (val) { + if (typeof val === 'string') { + val = [val] + obj[key] = val + } + val.push(headers[i + 1].toString('utf8')) + } else { + const headersValue = headers[i + 1] + if (typeof headersValue === 'string') { + obj[key] = headersValue + } else { + obj[key] = Array.isArray(headersValue) ? headersValue.map(x => x.toString('utf8')) : headersValue.toString('utf8') + } + } + } - this.ret = new Duplex({ - readableObjectMode: opts.objectMode, - autoDestroy: true, - read: () => { - const { body } = this + // See https://github.com/nodejs/node/pull/46528 + if ('content-length' in obj && 'content-disposition' in obj) { + obj['content-disposition'] = Buffer.from(obj['content-disposition']).toString('latin1') + } - if (body && body.resume) { - body.resume() - } - }, - write: (chunk, encoding, callback) => { - const { req } = this + return obj +} - if (req.push(chunk, encoding) || req._readableState.destroyed) { - callback() - } else { - req[kResume] = callback - } - }, - destroy: (err, callback) => { - const { body, req, res, ret, abort } = this +function parseRawHeaders (headers) { + const len = headers.length + const ret = new Array(len) - if (!err && !ret._readableState.endEmitted) { - err = new RequestAbortedError() - } + let hasContentLength = false + let contentDispositionIdx = -1 + let key + let val + let kLen = 0 - if (abort && err) { - abort() - } + for (let n = 0; n < headers.length; n += 2) { + key = headers[n] + val = headers[n + 1] - util.destroy(body, err) - util.destroy(req, err) - util.destroy(res, err) + typeof key !== 'string' && (key = key.toString()) + typeof val !== 'string' && (val = val.toString('utf8')) - removeSignal(this) + kLen = key.length + if (kLen === 14 && key[7] === '-' && (key === 'content-length' || key.toLowerCase() === 'content-length')) { + hasContentLength = true + } else if (kLen === 19 && key[7] === '-' && (key === 'content-disposition' || key.toLowerCase() === 'content-disposition')) { + contentDispositionIdx = n + 1 + } + ret[n] = key + ret[n + 1] = val + } - callback(err) - } - }).on('prefinish', () => { - const { req } = this + // See https://github.com/nodejs/node/pull/46528 + if (hasContentLength && contentDispositionIdx !== -1) { + ret[contentDispositionIdx] = Buffer.from(ret[contentDispositionIdx]).toString('latin1') + } - // Node < 15 does not call _final in same tick. - req.push(null) - }) + return ret +} - this.res = null +function isBuffer (buffer) { + // See, https://github.com/mcollina/undici/pull/319 + return buffer instanceof Uint8Array || Buffer.isBuffer(buffer) +} - addSignal(this, signal) +function validateHandler (handler, method, upgrade) { + if (!handler || typeof handler !== 'object') { + throw new InvalidArgumentError('handler must be an object') } - onConnect (abort, context) { - const { ret, res } = this - - assert(!res, 'pipeline cannot be retried') - - if (ret.destroyed) { - throw new RequestAbortedError() - } + if (typeof handler.onConnect !== 'function') { + throw new InvalidArgumentError('invalid onConnect method') + } - this.abort = abort - this.context = context + if (typeof handler.onError !== 'function') { + throw new InvalidArgumentError('invalid onError method') } - onHeaders (statusCode, rawHeaders, resume) { - const { opaque, handler, context } = this + if (typeof handler.onBodySent !== 'function' && handler.onBodySent !== undefined) { + throw new InvalidArgumentError('invalid onBodySent method') + } - if (statusCode < 200) { - if (this.onInfo) { - const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) - this.onInfo({ statusCode, headers }) - } - return + if (upgrade || method === 'CONNECT') { + if (typeof handler.onUpgrade !== 'function') { + throw new InvalidArgumentError('invalid onUpgrade method') } - - this.res = new PipelineResponse(resume) - - let body - try { - this.handler = null - const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) - body = this.runInAsyncScope(handler, null, { - statusCode, - headers, - opaque, - body: this.res, - context - }) - } catch (err) { - this.res.on('error', util.nop) - throw err + } else { + if (typeof handler.onHeaders !== 'function') { + throw new InvalidArgumentError('invalid onHeaders method') } - if (!body || typeof body.on !== 'function') { - throw new InvalidReturnValueError('expected Readable') + if (typeof handler.onData !== 'function') { + throw new InvalidArgumentError('invalid onData method') } - body - .on('data', (chunk) => { - const { ret, body } = this + if (typeof handler.onComplete !== 'function') { + throw new InvalidArgumentError('invalid onComplete method') + } + } +} - if (!ret.push(chunk) && body.pause) { - body.pause() - } - }) - .on('error', (err) => { - const { ret } = this +// A body is disturbed if it has been read from and it cannot +// be re-used without losing state or data. +function isDisturbed (body) { + // TODO (fix): Why is body[kBodyUsed] needed? + return !!(body && (stream.isDisturbed(body) || body[kBodyUsed])) +} - util.destroy(ret, err) - }) - .on('end', () => { - const { ret } = this +function isErrored (body) { + return !!(body && stream.isErrored(body)) +} - ret.push(null) - }) - .on('close', () => { - const { ret } = this +function isReadable (body) { + return !!(body && stream.isReadable(body)) +} - if (!ret._readableState.ended) { - util.destroy(ret, new RequestAbortedError()) - } - }) +function getSocketInfo (socket) { + return { + localAddress: socket.localAddress, + localPort: socket.localPort, + remoteAddress: socket.remoteAddress, + remotePort: socket.remotePort, + remoteFamily: socket.remoteFamily, + timeout: socket.timeout, + bytesWritten: socket.bytesWritten, + bytesRead: socket.bytesRead + } +} - this.body = body +/** @type {globalThis['ReadableStream']} */ +function ReadableStreamFrom (iterable) { + // We cannot use ReadableStream.from here because it does not return a byte stream. + + let iterator + return new ReadableStream( + { + async start () { + iterator = iterable[Symbol.asyncIterator]() + }, + async pull (controller) { + const { done, value } = await iterator.next() + if (done) { + queueMicrotask(() => { + controller.close() + controller.byobRequest?.respond(0) + }) + } else { + const buf = Buffer.isBuffer(value) ? value : Buffer.from(value) + if (buf.byteLength) { + controller.enqueue(new Uint8Array(buf)) + } + } + return controller.desiredSize > 0 + }, + async cancel (reason) { + await iterator.return() + }, + type: 'bytes' + } + ) +} + +// The chunk should be a FormData instance and contains +// all the required methods. +function isFormDataLike (object) { + return ( + object && + typeof object === 'object' && + typeof object.append === 'function' && + typeof object.delete === 'function' && + typeof object.get === 'function' && + typeof object.getAll === 'function' && + typeof object.has === 'function' && + typeof object.set === 'function' && + object[Symbol.toStringTag] === 'FormData' + ) +} + +function addAbortListener (signal, listener) { + if ('addEventListener' in signal) { + signal.addEventListener('abort', listener, { once: true }) + return () => signal.removeEventListener('abort', listener) } + signal.addListener('abort', listener) + return () => signal.removeListener('abort', listener) +} - onData (chunk) { - const { res } = this - return res.push(chunk) +const hasToWellFormed = typeof String.prototype.toWellFormed === 'function' +const hasIsWellFormed = typeof String.prototype.isWellFormed === 'function' + +/** + * @param {string} val + */ +function toUSVString (val) { + return hasToWellFormed ? `${val}`.toWellFormed() : nodeUtil.toUSVString(val) +} + +/** + * @param {string} val + */ +// TODO: move this to webidl +function isUSVString (val) { + return hasIsWellFormed ? `${val}`.isWellFormed() : toUSVString(val) === `${val}` +} + +/** + * @see https://tools.ietf.org/html/rfc7230#section-3.2.6 + * @param {number} c + */ +function isTokenCharCode (c) { + switch (c) { + case 0x22: + case 0x28: + case 0x29: + case 0x2c: + case 0x2f: + case 0x3a: + case 0x3b: + case 0x3c: + case 0x3d: + case 0x3e: + case 0x3f: + case 0x40: + case 0x5b: + case 0x5c: + case 0x5d: + case 0x7b: + case 0x7d: + // DQUOTE and "(),/:;<=>?@[\]{}" + return false + default: + // VCHAR %x21-7E + return c >= 0x21 && c <= 0x7e } +} - onComplete (trailers) { - const { res } = this - res.push(null) +/** + * @param {string} characters + */ +function isValidHTTPToken (characters) { + if (characters.length === 0) { + return false + } + for (let i = 0; i < characters.length; ++i) { + if (!isTokenCharCode(characters.charCodeAt(i))) { + return false + } } + return true +} - onError (err) { - const { ret } = this - this.handler = null - util.destroy(ret, err) +// headerCharRegex have been lifted from +// https://github.com/nodejs/node/blob/main/lib/_http_common.js + +/** + * Matches if val contains an invalid field-vchar + * field-value = *( field-content / obs-fold ) + * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ] + * field-vchar = VCHAR / obs-text + */ +const headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/ + +/** + * @param {string} characters + */ +function isValidHeaderValue (characters) { + return !headerCharRegex.test(characters) +} + +// Parsed accordingly to RFC 9110 +// https://www.rfc-editor.org/rfc/rfc9110#field.content-range +function parseRangeHeader (range) { + if (range == null || range === '') return { start: 0, end: null, size: null } + + const m = range ? range.match(/^bytes (\d+)-(\d+)\/(\d+)?$/) : null + return m + ? { + start: parseInt(m[1]), + end: m[2] ? parseInt(m[2]) : null, + size: m[3] ? parseInt(m[3]) : null + } + : null +} + +function addListener (obj, name, listener) { + const listeners = (obj[kListeners] ??= []) + listeners.push([name, listener]) + obj.on(name, listener) + return obj +} + +function removeAllListeners (obj) { + for (const [name, listener] of obj[kListeners] ?? []) { + obj.removeListener(name, listener) } + obj[kListeners] = null } -function pipeline (opts, handler) { +function errorRequest (client, request, err) { try { - const pipelineHandler = new PipelineHandler(opts, handler) - this.dispatch({ ...opts, body: pipelineHandler.req }, pipelineHandler) - return pipelineHandler.ret + request.onError(err) + assert(request.aborted) } catch (err) { - return new PassThrough().destroy(err) + client.emit('error', err) } } -module.exports = pipeline +const kEnumerableProperty = Object.create(null) +kEnumerableProperty.enumerable = true +const normalizedMethodRecordsBase = { + delete: 'DELETE', + DELETE: 'DELETE', + get: 'GET', + GET: 'GET', + head: 'HEAD', + HEAD: 'HEAD', + options: 'OPTIONS', + OPTIONS: 'OPTIONS', + post: 'POST', + POST: 'POST', + put: 'PUT', + PUT: 'PUT' +} -/***/ }), +const normalizedMethodRecords = { + ...normalizedMethodRecordsBase, + patch: 'patch', + PATCH: 'PATCH' +} -/***/ 5462: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +// Note: object prototypes should not be able to be referenced. e.g. `Object#hasOwnProperty`. +Object.setPrototypeOf(normalizedMethodRecordsBase, null) +Object.setPrototypeOf(normalizedMethodRecords, null) -"use strict"; +module.exports = { + kEnumerableProperty, + nop, + isDisturbed, + isErrored, + isReadable, + toUSVString, + isUSVString, + isBlobLike, + parseOrigin, + parseURL, + getServerName, + isStream, + isIterable, + isAsyncIterable, + isDestroyed, + headerNameToString, + bufferToLowerCasedHeaderName, + addListener, + removeAllListeners, + errorRequest, + parseRawHeaders, + parseHeaders, + parseKeepAliveTimeout, + destroy, + bodyLength, + deepClone, + ReadableStreamFrom, + isBuffer, + validateHandler, + getSocketInfo, + isFormDataLike, + buildURL, + addAbortListener, + isValidHTTPToken, + isValidHeaderValue, + isTokenCharCode, + parseRangeHeader, + normalizedMethodRecordsBase, + normalizedMethodRecords, + isValidPort, + isHttpOrHttpsPrefixed, + nodeMajor, + nodeMinor, + safeHTTPMethods: ['GET', 'HEAD', 'OPTIONS', 'TRACE'], + wrapRequestBody +} -const Readable = __nccwpck_require__(5776) -const { - InvalidArgumentError, - RequestAbortedError -} = __nccwpck_require__(6738) -const util = __nccwpck_require__(5069) -const { getResolveErrorBodyCallback } = __nccwpck_require__(9252) -const { AsyncResource } = __nccwpck_require__(290) -const { addSignal, removeSignal } = __nccwpck_require__(9761) +/***/ }), -class RequestHandler extends AsyncResource { - constructor (opts, callback) { - if (!opts || typeof opts !== 'object') { - throw new InvalidArgumentError('invalid opts') - } +/***/ 4779: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - const { signal, method, opaque, body, onInfo, responseHeaders, throwOnError, highWaterMark } = opts - try { - if (typeof callback !== 'function') { - throw new InvalidArgumentError('invalid callback') - } - if (highWaterMark && (typeof highWaterMark !== 'number' || highWaterMark < 0)) { - throw new InvalidArgumentError('invalid highWaterMark') - } +const { InvalidArgumentError } = __nccwpck_require__(329) +const { kClients, kRunning, kClose, kDestroy, kDispatch, kInterceptors } = __nccwpck_require__(7417) +const DispatcherBase = __nccwpck_require__(555) +const Pool = __nccwpck_require__(4105) +const Client = __nccwpck_require__(9143) +const util = __nccwpck_require__(7234) +const createRedirectInterceptor = __nccwpck_require__(2642) - if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { - throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') - } +const kOnConnect = Symbol('onConnect') +const kOnDisconnect = Symbol('onDisconnect') +const kOnConnectionError = Symbol('onConnectionError') +const kMaxRedirections = Symbol('maxRedirections') +const kOnDrain = Symbol('onDrain') +const kFactory = Symbol('factory') +const kOptions = Symbol('options') - if (method === 'CONNECT') { - throw new InvalidArgumentError('invalid method') - } +function defaultFactory (origin, opts) { + return opts && opts.connections === 1 + ? new Client(origin, opts) + : new Pool(origin, opts) +} - if (onInfo && typeof onInfo !== 'function') { - throw new InvalidArgumentError('invalid onInfo callback') - } +class Agent extends DispatcherBase { + constructor ({ factory = defaultFactory, maxRedirections = 0, connect, ...options } = {}) { + super() - super('UNDICI_REQUEST') - } catch (err) { - if (util.isStream(body)) { - util.destroy(body.on('error', util.nop), err) - } - throw err + if (typeof factory !== 'function') { + throw new InvalidArgumentError('factory must be a function.') } - this.responseHeaders = responseHeaders || null - this.opaque = opaque || null - this.callback = callback - this.res = null - this.abort = null - this.body = body - this.trailers = {} - this.context = null - this.onInfo = onInfo || null - this.throwOnError = throwOnError - this.highWaterMark = highWaterMark - - if (util.isStream(body)) { - body.on('error', (err) => { - this.onError(err) - }) + if (connect != null && typeof connect !== 'function' && typeof connect !== 'object') { + throw new InvalidArgumentError('connect must be a function or an object') } - addSignal(this, signal) - } + if (!Number.isInteger(maxRedirections) || maxRedirections < 0) { + throw new InvalidArgumentError('maxRedirections must be a positive number') + } - onConnect (abort, context) { - if (!this.callback) { - throw new RequestAbortedError() + if (connect && typeof connect !== 'function') { + connect = { ...connect } } - this.abort = abort - this.context = context - } + this[kInterceptors] = options.interceptors?.Agent && Array.isArray(options.interceptors.Agent) + ? options.interceptors.Agent + : [createRedirectInterceptor({ maxRedirections })] - onHeaders (statusCode, rawHeaders, resume, statusMessage) { - const { callback, opaque, abort, context, responseHeaders, highWaterMark } = this + this[kOptions] = { ...util.deepClone(options), connect } + this[kOptions].interceptors = options.interceptors + ? { ...options.interceptors } + : undefined + this[kMaxRedirections] = maxRedirections + this[kFactory] = factory + this[kClients] = new Map() - const headers = responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) + this[kOnDrain] = (origin, targets) => { + this.emit('drain', origin, [this, ...targets]) + } - if (statusCode < 200) { - if (this.onInfo) { - this.onInfo({ statusCode, headers }) - } - return + this[kOnConnect] = (origin, targets) => { + this.emit('connect', origin, [this, ...targets]) } - const parsedHeaders = responseHeaders === 'raw' ? util.parseHeaders(rawHeaders) : headers - const contentType = parsedHeaders['content-type'] - const body = new Readable({ resume, abort, contentType, highWaterMark }) + this[kOnDisconnect] = (origin, targets, err) => { + this.emit('disconnect', origin, [this, ...targets], err) + } - this.callback = null - this.res = body - if (callback !== null) { - if (this.throwOnError && statusCode >= 400) { - this.runInAsyncScope(getResolveErrorBodyCallback, null, - { callback, body, contentType, statusCode, statusMessage, headers } - ) - } else { - this.runInAsyncScope(callback, null, null, { - statusCode, - headers, - trailers: this.trailers, - opaque, - body, - context - }) - } + this[kOnConnectionError] = (origin, targets, err) => { + this.emit('connectionError', origin, [this, ...targets], err) } } - onData (chunk) { - const { res } = this - return res.push(chunk) + get [kRunning] () { + let ret = 0 + for (const client of this[kClients].values()) { + ret += client[kRunning] + } + return ret } - onComplete (trailers) { - const { res } = this - - removeSignal(this) - - util.parseHeaders(trailers, this.trailers) - - res.push(null) - } + [kDispatch] (opts, handler) { + let key + if (opts.origin && (typeof opts.origin === 'string' || opts.origin instanceof URL)) { + key = String(opts.origin) + } else { + throw new InvalidArgumentError('opts.origin must be a non-empty string or URL.') + } - onError (err) { - const { res, callback, body, opaque } = this + let dispatcher = this[kClients].get(key) - removeSignal(this) + if (!dispatcher) { + dispatcher = this[kFactory](opts.origin, this[kOptions]) + .on('drain', this[kOnDrain]) + .on('connect', this[kOnConnect]) + .on('disconnect', this[kOnDisconnect]) + .on('connectionError', this[kOnConnectionError]) - if (callback) { - // TODO: Does this need queueMicrotask? - this.callback = null - queueMicrotask(() => { - this.runInAsyncScope(callback, null, err, { opaque }) - }) + // This introduces a tiny memory leak, as dispatchers are never removed from the map. + // TODO(mcollina): remove te timer when the client/pool do not have any more + // active connections. + this[kClients].set(key, dispatcher) } - if (res) { - this.res = null - // Ensure all queued handlers are invoked before destroying res. - queueMicrotask(() => { - util.destroy(res, err) - }) - } + return dispatcher.dispatch(opts, handler) + } - if (body) { - this.body = null - util.destroy(body, err) + async [kClose] () { + const closePromises = [] + for (const client of this[kClients].values()) { + closePromises.push(client.close()) } - } -} + this[kClients].clear() -function request (opts, callback) { - if (callback === undefined) { - return new Promise((resolve, reject) => { - request.call(this, opts, (err, data) => { - return err ? reject(err) : resolve(data) - }) - }) + await Promise.all(closePromises) } - try { - this.dispatch(opts, new RequestHandler(opts, callback)) - } catch (err) { - if (typeof callback !== 'function') { - throw err + async [kDestroy] (err) { + const destroyPromises = [] + for (const client of this[kClients].values()) { + destroyPromises.push(client.destroy(err)) } - const opaque = opts && opts.opaque - queueMicrotask(() => callback(err, { opaque })) + this[kClients].clear() + + await Promise.all(destroyPromises) } } -module.exports = request -module.exports.RequestHandler = RequestHandler +module.exports = Agent /***/ }), -/***/ 1163: +/***/ 6895: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -const { finished, PassThrough } = __nccwpck_require__(2203) const { - InvalidArgumentError, - InvalidReturnValueError, - RequestAbortedError -} = __nccwpck_require__(6738) -const util = __nccwpck_require__(5069) -const { getResolveErrorBodyCallback } = __nccwpck_require__(9252) -const { AsyncResource } = __nccwpck_require__(290) -const { addSignal, removeSignal } = __nccwpck_require__(9761) + BalancedPoolMissingUpstreamError, + InvalidArgumentError +} = __nccwpck_require__(329) +const { + PoolBase, + kClients, + kNeedDrain, + kAddClient, + kRemoveClient, + kGetDispatcher +} = __nccwpck_require__(5398) +const Pool = __nccwpck_require__(4105) +const { kUrl, kInterceptors } = __nccwpck_require__(7417) +const { parseOrigin } = __nccwpck_require__(7234) +const kFactory = Symbol('factory') -class StreamHandler extends AsyncResource { - constructor (opts, factory, callback) { - if (!opts || typeof opts !== 'object') { - throw new InvalidArgumentError('invalid opts') - } +const kOptions = Symbol('options') +const kGreatestCommonDivisor = Symbol('kGreatestCommonDivisor') +const kCurrentWeight = Symbol('kCurrentWeight') +const kIndex = Symbol('kIndex') +const kWeight = Symbol('kWeight') +const kMaxWeightPerServer = Symbol('kMaxWeightPerServer') +const kErrorPenalty = Symbol('kErrorPenalty') - const { signal, method, opaque, body, onInfo, responseHeaders, throwOnError } = opts +/** + * Calculate the greatest common divisor of two numbers by + * using the Euclidean algorithm. + * + * @param {number} a + * @param {number} b + * @returns {number} + */ +function getGreatestCommonDivisor (a, b) { + if (a === 0) return b - try { - if (typeof callback !== 'function') { - throw new InvalidArgumentError('invalid callback') - } + while (b !== 0) { + const t = b + b = a % b + a = t + } + return a +} - if (typeof factory !== 'function') { - throw new InvalidArgumentError('invalid factory') - } +function defaultFactory (origin, opts) { + return new Pool(origin, opts) +} - if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { - throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') - } +class BalancedPool extends PoolBase { + constructor (upstreams = [], { factory = defaultFactory, ...opts } = {}) { + super() - if (method === 'CONNECT') { - throw new InvalidArgumentError('invalid method') - } + this[kOptions] = opts + this[kIndex] = -1 + this[kCurrentWeight] = 0 - if (onInfo && typeof onInfo !== 'function') { - throw new InvalidArgumentError('invalid onInfo callback') - } + this[kMaxWeightPerServer] = this[kOptions].maxWeightPerServer || 100 + this[kErrorPenalty] = this[kOptions].errorPenalty || 15 - super('UNDICI_STREAM') - } catch (err) { - if (util.isStream(body)) { - util.destroy(body.on('error', util.nop), err) - } - throw err + if (!Array.isArray(upstreams)) { + upstreams = [upstreams] } - this.responseHeaders = responseHeaders || null - this.opaque = opaque || null - this.factory = factory - this.callback = callback - this.res = null - this.abort = null - this.context = null - this.trailers = null - this.body = body - this.onInfo = onInfo || null - this.throwOnError = throwOnError || false - - if (util.isStream(body)) { - body.on('error', (err) => { - this.onError(err) - }) + if (typeof factory !== 'function') { + throw new InvalidArgumentError('factory must be a function.') } - addSignal(this, signal) - } + this[kInterceptors] = opts.interceptors?.BalancedPool && Array.isArray(opts.interceptors.BalancedPool) + ? opts.interceptors.BalancedPool + : [] + this[kFactory] = factory - onConnect (abort, context) { - if (!this.callback) { - throw new RequestAbortedError() + for (const upstream of upstreams) { + this.addUpstream(upstream) } - - this.abort = abort - this.context = context + this._updateBalancedPoolStats() } - onHeaders (statusCode, rawHeaders, resume, statusMessage) { - const { factory, opaque, context, callback, responseHeaders } = this - - const headers = responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) + addUpstream (upstream) { + const upstreamOrigin = parseOrigin(upstream).origin - if (statusCode < 200) { - if (this.onInfo) { - this.onInfo({ statusCode, headers }) - } - return + if (this[kClients].find((pool) => ( + pool[kUrl].origin === upstreamOrigin && + pool.closed !== true && + pool.destroyed !== true + ))) { + return this } + const pool = this[kFactory](upstreamOrigin, Object.assign({}, this[kOptions])) - this.factory = null - - let res - - if (this.throwOnError && statusCode >= 400) { - const parsedHeaders = responseHeaders === 'raw' ? util.parseHeaders(rawHeaders) : headers - const contentType = parsedHeaders['content-type'] - res = new PassThrough() - - this.callback = null - this.runInAsyncScope(getResolveErrorBodyCallback, null, - { callback, body: res, contentType, statusCode, statusMessage, headers } - ) - } else { - if (factory === null) { - return - } + this[kAddClient](pool) + pool.on('connect', () => { + pool[kWeight] = Math.min(this[kMaxWeightPerServer], pool[kWeight] + this[kErrorPenalty]) + }) - res = this.runInAsyncScope(factory, null, { - statusCode, - headers, - opaque, - context - }) + pool.on('connectionError', () => { + pool[kWeight] = Math.max(1, pool[kWeight] - this[kErrorPenalty]) + this._updateBalancedPoolStats() + }) - if ( - !res || - typeof res.write !== 'function' || - typeof res.end !== 'function' || - typeof res.on !== 'function' - ) { - throw new InvalidReturnValueError('expected Writable') + pool.on('disconnect', (...args) => { + const err = args[2] + if (err && err.code === 'UND_ERR_SOCKET') { + // decrease the weight of the pool. + pool[kWeight] = Math.max(1, pool[kWeight] - this[kErrorPenalty]) + this._updateBalancedPoolStats() } + }) - // TODO: Avoid finished. It registers an unnecessary amount of listeners. - finished(res, { readable: false }, (err) => { - const { callback, res, opaque, trailers, abort } = this + for (const client of this[kClients]) { + client[kWeight] = this[kMaxWeightPerServer] + } - this.res = null - if (err || !res.readable) { - util.destroy(res, err) - } + this._updateBalancedPoolStats() - this.callback = null - this.runInAsyncScope(callback, null, err || null, { opaque, trailers }) + return this + } - if (err) { - abort() - } - }) + _updateBalancedPoolStats () { + let result = 0 + for (let i = 0; i < this[kClients].length; i++) { + result = getGreatestCommonDivisor(this[kClients][i][kWeight], result) } - res.on('drain', resume) + this[kGreatestCommonDivisor] = result + } - this.res = res + removeUpstream (upstream) { + const upstreamOrigin = parseOrigin(upstream).origin - const needDrain = res.writableNeedDrain !== undefined - ? res.writableNeedDrain - : res._writableState && res._writableState.needDrain + const pool = this[kClients].find((pool) => ( + pool[kUrl].origin === upstreamOrigin && + pool.closed !== true && + pool.destroyed !== true + )) - return needDrain !== true - } + if (pool) { + this[kRemoveClient](pool) + } - onData (chunk) { - const { res } = this + return this + } - return res ? res.write(chunk) : true + get upstreams () { + return this[kClients] + .filter(dispatcher => dispatcher.closed !== true && dispatcher.destroyed !== true) + .map((p) => p[kUrl].origin) } - onComplete (trailers) { - const { res } = this + [kGetDispatcher] () { + // We validate that pools is greater than 0, + // otherwise we would have to wait until an upstream + // is added, which might never happen. + if (this[kClients].length === 0) { + throw new BalancedPoolMissingUpstreamError() + } - removeSignal(this) + const dispatcher = this[kClients].find(dispatcher => ( + !dispatcher[kNeedDrain] && + dispatcher.closed !== true && + dispatcher.destroyed !== true + )) - if (!res) { + if (!dispatcher) { return } - this.trailers = util.parseHeaders(trailers) - - res.end() - } + const allClientsBusy = this[kClients].map(pool => pool[kNeedDrain]).reduce((a, b) => a && b, true) - onError (err) { - const { res, callback, opaque, body } = this + if (allClientsBusy) { + return + } - removeSignal(this) + let counter = 0 - this.factory = null + let maxWeightIndex = this[kClients].findIndex(pool => !pool[kNeedDrain]) - if (res) { - this.res = null - util.destroy(res, err) - } else if (callback) { - this.callback = null - queueMicrotask(() => { - this.runInAsyncScope(callback, null, err, { opaque }) - }) - } + while (counter++ < this[kClients].length) { + this[kIndex] = (this[kIndex] + 1) % this[kClients].length + const pool = this[kClients][this[kIndex]] - if (body) { - this.body = null - util.destroy(body, err) - } - } -} + // find pool index with the largest weight + if (pool[kWeight] > this[kClients][maxWeightIndex][kWeight] && !pool[kNeedDrain]) { + maxWeightIndex = this[kIndex] + } -function stream (opts, factory, callback) { - if (callback === undefined) { - return new Promise((resolve, reject) => { - stream.call(this, opts, factory, (err, data) => { - return err ? reject(err) : resolve(data) - }) - }) - } + // decrease the current weight every `this[kClients].length`. + if (this[kIndex] === 0) { + // Set the current weight to the next lower weight. + this[kCurrentWeight] = this[kCurrentWeight] - this[kGreatestCommonDivisor] - try { - this.dispatch(opts, new StreamHandler(opts, factory, callback)) - } catch (err) { - if (typeof callback !== 'function') { - throw err + if (this[kCurrentWeight] <= 0) { + this[kCurrentWeight] = this[kMaxWeightPerServer] + } + } + if (pool[kWeight] >= this[kCurrentWeight] && (!pool[kNeedDrain])) { + return pool + } } - const opaque = opts && opts.opaque - queueMicrotask(() => callback(err, { opaque })) + + this[kCurrentWeight] = this[kClients][maxWeightIndex][kWeight] + this[kIndex] = maxWeightIndex + return this[kClients][maxWeightIndex] } } -module.exports = stream +module.exports = BalancedPool /***/ }), -/***/ 9375: +/***/ 6323: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; - -const { InvalidArgumentError, RequestAbortedError, SocketError } = __nccwpck_require__(6738) -const { AsyncResource } = __nccwpck_require__(290) -const util = __nccwpck_require__(5069) -const { addSignal, removeSignal } = __nccwpck_require__(9761) -const assert = __nccwpck_require__(2613) -class UpgradeHandler extends AsyncResource { - constructor (opts, callback) { - if (!opts || typeof opts !== 'object') { - throw new InvalidArgumentError('invalid opts') - } +/* global WebAssembly */ - if (typeof callback !== 'function') { - throw new InvalidArgumentError('invalid callback') - } +const assert = __nccwpck_require__(4589) +const util = __nccwpck_require__(7234) +const { channels } = __nccwpck_require__(7820) +const timers = __nccwpck_require__(5969) +const { + RequestContentLengthMismatchError, + ResponseContentLengthMismatchError, + RequestAbortedError, + HeadersTimeoutError, + HeadersOverflowError, + SocketError, + InformationalError, + BodyTimeoutError, + HTTPParserError, + ResponseExceededMaxSizeError +} = __nccwpck_require__(329) +const { + kUrl, + kReset, + kClient, + kParser, + kBlocking, + kRunning, + kPending, + kSize, + kWriting, + kQueue, + kNoRef, + kKeepAliveDefaultTimeout, + kHostHeader, + kPendingIdx, + kRunningIdx, + kError, + kPipelining, + kSocket, + kKeepAliveTimeoutValue, + kMaxHeadersSize, + kKeepAliveMaxTimeout, + kKeepAliveTimeoutThreshold, + kHeadersTimeout, + kBodyTimeout, + kStrictContentLength, + kMaxRequests, + kCounter, + kMaxResponseSize, + kOnError, + kResume, + kHTTPContext +} = __nccwpck_require__(7417) - const { signal, opaque, responseHeaders } = opts +const constants = __nccwpck_require__(1114) +const EMPTY_BUF = Buffer.alloc(0) +const FastBuffer = Buffer[Symbol.species] +const addListener = util.addListener +const removeAllListeners = util.removeAllListeners - if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { - throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') - } +let extractBody - super('UNDICI_UPGRADE') +async function lazyllhttp () { + const llhttpWasmData = process.env.JEST_WORKER_ID ? __nccwpck_require__(3312) : undefined - this.responseHeaders = responseHeaders || null - this.opaque = opaque || null - this.callback = callback - this.abort = null - this.context = null + let mod + try { + mod = await WebAssembly.compile(__nccwpck_require__(9768)) + } catch (e) { + /* istanbul ignore next */ - addSignal(this, signal) + // We could check if the error was caused by the simd option not + // being enabled, but the occurring of this other error + // * https://github.com/emscripten-core/emscripten/issues/11495 + // got me to remove that check to avoid breaking Node 12. + mod = await WebAssembly.compile(llhttpWasmData || __nccwpck_require__(3312)) } - onConnect (abort, context) { - if (!this.callback) { - throw new RequestAbortedError() - } + return await WebAssembly.instantiate(mod, { + env: { + /* eslint-disable camelcase */ - this.abort = abort - this.context = null - } + wasm_on_url: (p, at, len) => { + /* istanbul ignore next */ + return 0 + }, + wasm_on_status: (p, at, len) => { + assert(currentParser.ptr === p) + const start = at - currentBufferPtr + currentBufferRef.byteOffset + return currentParser.onStatus(new FastBuffer(currentBufferRef.buffer, start, len)) || 0 + }, + wasm_on_message_begin: (p) => { + assert(currentParser.ptr === p) + return currentParser.onMessageBegin() || 0 + }, + wasm_on_header_field: (p, at, len) => { + assert(currentParser.ptr === p) + const start = at - currentBufferPtr + currentBufferRef.byteOffset + return currentParser.onHeaderField(new FastBuffer(currentBufferRef.buffer, start, len)) || 0 + }, + wasm_on_header_value: (p, at, len) => { + assert(currentParser.ptr === p) + const start = at - currentBufferPtr + currentBufferRef.byteOffset + return currentParser.onHeaderValue(new FastBuffer(currentBufferRef.buffer, start, len)) || 0 + }, + wasm_on_headers_complete: (p, statusCode, upgrade, shouldKeepAlive) => { + assert(currentParser.ptr === p) + return currentParser.onHeadersComplete(statusCode, Boolean(upgrade), Boolean(shouldKeepAlive)) || 0 + }, + wasm_on_body: (p, at, len) => { + assert(currentParser.ptr === p) + const start = at - currentBufferPtr + currentBufferRef.byteOffset + return currentParser.onBody(new FastBuffer(currentBufferRef.buffer, start, len)) || 0 + }, + wasm_on_message_complete: (p) => { + assert(currentParser.ptr === p) + return currentParser.onMessageComplete() || 0 + } - onHeaders () { - throw new SocketError('bad upgrade', null) - } + /* eslint-enable camelcase */ + } + }) +} - onUpgrade (statusCode, rawHeaders, socket) { - const { callback, opaque, context } = this +let llhttpInstance = null +let llhttpPromise = lazyllhttp() +llhttpPromise.catch() - assert.strictEqual(statusCode, 101) +let currentParser = null +let currentBufferRef = null +let currentBufferSize = 0 +let currentBufferPtr = null - removeSignal(this) +const USE_NATIVE_TIMER = 0 +const USE_FAST_TIMER = 1 - this.callback = null - const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) - this.runInAsyncScope(callback, null, null, { - headers, - socket, - opaque, - context - }) - } +// Use fast timers for headers and body to take eventual event loop +// latency into account. +const TIMEOUT_HEADERS = 2 | USE_FAST_TIMER +const TIMEOUT_BODY = 4 | USE_FAST_TIMER - onError (err) { - const { callback, opaque } = this +// Use native timers to ignore event loop latency for keep-alive +// handling. +const TIMEOUT_KEEP_ALIVE = 8 | USE_NATIVE_TIMER - removeSignal(this) +class Parser { + constructor (client, socket, { exports }) { + assert(Number.isFinite(client[kMaxHeadersSize]) && client[kMaxHeadersSize] > 0) - if (callback) { - this.callback = null - queueMicrotask(() => { - this.runInAsyncScope(callback, null, err, { opaque }) - }) - } - } -} + this.llhttp = exports + this.ptr = this.llhttp.llhttp_alloc(constants.TYPE.RESPONSE) + this.client = client + this.socket = socket + this.timeout = null + this.timeoutValue = null + this.timeoutType = null + this.statusCode = null + this.statusText = '' + this.upgrade = false + this.headers = [] + this.headersSize = 0 + this.headersMaxSize = client[kMaxHeadersSize] + this.shouldKeepAlive = false + this.paused = false + this.resume = this.resume.bind(this) -function upgrade (opts, callback) { - if (callback === undefined) { - return new Promise((resolve, reject) => { - upgrade.call(this, opts, (err, data) => { - return err ? reject(err) : resolve(data) - }) - }) - } + this.bytesRead = 0 - try { - const upgradeHandler = new UpgradeHandler(opts, callback) - this.dispatch({ - ...opts, - method: opts.method || 'GET', - upgrade: opts.protocol || 'Websocket' - }, upgradeHandler) - } catch (err) { - if (typeof callback !== 'function') { - throw err - } - const opaque = opts && opts.opaque - queueMicrotask(() => callback(err, { opaque })) + this.keepAlive = '' + this.contentLength = '' + this.connection = '' + this.maxResponseSize = client[kMaxResponseSize] } -} - -module.exports = upgrade + setTimeout (delay, type) { + // If the existing timer and the new timer are of different timer type + // (fast or native) or have different delay, we need to clear the existing + // timer and set a new one. + if ( + delay !== this.timeoutValue || + (type & USE_FAST_TIMER) ^ (this.timeoutType & USE_FAST_TIMER) + ) { + // If a timeout is already set, clear it with clearTimeout of the fast + // timer implementation, as it can clear fast and native timers. + if (this.timeout) { + timers.clearTimeout(this.timeout) + this.timeout = null + } -/***/ }), + if (delay) { + if (type & USE_FAST_TIMER) { + this.timeout = timers.setFastTimeout(onParserTimeout, delay, new WeakRef(this)) + } else { + this.timeout = setTimeout(onParserTimeout, delay, new WeakRef(this)) + this.timeout.unref() + } + } -/***/ 7450: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + this.timeoutValue = delay + } else if (this.timeout) { + // istanbul ignore else: only for jest + if (this.timeout.refresh) { + this.timeout.refresh() + } + } -"use strict"; + this.timeoutType = type + } + resume () { + if (this.socket.destroyed || !this.paused) { + return + } -module.exports.request = __nccwpck_require__(5462) -module.exports.stream = __nccwpck_require__(1163) -module.exports.pipeline = __nccwpck_require__(4994) -module.exports.upgrade = __nccwpck_require__(9375) -module.exports.connect = __nccwpck_require__(6829) + assert(this.ptr != null) + assert(currentParser == null) + this.llhttp.llhttp_resume(this.ptr) -/***/ }), - -/***/ 5776: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -"use strict"; -// Ported from https://github.com/nodejs/undici/pull/907 + assert(this.timeoutType === TIMEOUT_BODY) + if (this.timeout) { + // istanbul ignore else: only for jest + if (this.timeout.refresh) { + this.timeout.refresh() + } + } + this.paused = false + this.execute(this.socket.read() || EMPTY_BUF) // Flush parser. + this.readMore() + } + readMore () { + while (!this.paused && this.ptr) { + const chunk = this.socket.read() + if (chunk === null) { + break + } + this.execute(chunk) + } + } -const assert = __nccwpck_require__(2613) -const { Readable } = __nccwpck_require__(2203) -const { RequestAbortedError, NotSupportedError, InvalidArgumentError } = __nccwpck_require__(6738) -const util = __nccwpck_require__(5069) -const { ReadableStreamFrom, toUSVString } = __nccwpck_require__(5069) + execute (data) { + assert(this.ptr != null) + assert(currentParser == null) + assert(!this.paused) -let Blob + const { socket, llhttp } = this -const kConsume = Symbol('kConsume') -const kReading = Symbol('kReading') -const kBody = Symbol('kBody') -const kAbort = Symbol('abort') -const kContentType = Symbol('kContentType') + if (data.length > currentBufferSize) { + if (currentBufferPtr) { + llhttp.free(currentBufferPtr) + } + currentBufferSize = Math.ceil(data.length / 4096) * 4096 + currentBufferPtr = llhttp.malloc(currentBufferSize) + } -const noop = () => {} + new Uint8Array(llhttp.memory.buffer, currentBufferPtr, currentBufferSize).set(data) -module.exports = class BodyReadable extends Readable { - constructor ({ - resume, - abort, - contentType = '', - highWaterMark = 64 * 1024 // Same as nodejs fs streams. - }) { - super({ - autoDestroy: true, - read: resume, - highWaterMark - }) + // Call `execute` on the wasm parser. + // We pass the `llhttp_parser` pointer address, the pointer address of buffer view data, + // and finally the length of bytes to parse. + // The return value is an error code or `constants.ERROR.OK`. + try { + let ret - this._readableState.dataEmitted = false + try { + currentBufferRef = data + currentParser = this + ret = llhttp.llhttp_execute(this.ptr, currentBufferPtr, data.length) + /* eslint-disable-next-line no-useless-catch */ + } catch (err) { + /* istanbul ignore next: difficult to make a test case for */ + throw err + } finally { + currentParser = null + currentBufferRef = null + } - this[kAbort] = abort - this[kConsume] = null - this[kBody] = null - this[kContentType] = contentType + const offset = llhttp.llhttp_get_error_pos(this.ptr) - currentBufferPtr - // Is stream being consumed through Readable API? - // This is an optimization so that we avoid checking - // for 'data' and 'readable' listeners in the hot path - // inside push(). - this[kReading] = false + if (ret === constants.ERROR.PAUSED_UPGRADE) { + this.onUpgrade(data.slice(offset)) + } else if (ret === constants.ERROR.PAUSED) { + this.paused = true + socket.unshift(data.slice(offset)) + } else if (ret !== constants.ERROR.OK) { + const ptr = llhttp.llhttp_get_error_reason(this.ptr) + let message = '' + /* istanbul ignore else: difficult to make a test case for */ + if (ptr) { + const len = new Uint8Array(llhttp.memory.buffer, ptr).indexOf(0) + message = + 'Response does not match the HTTP/1.1 protocol (' + + Buffer.from(llhttp.memory.buffer, ptr, len).toString() + + ')' + } + throw new HTTPParserError(message, constants.ERROR[ret], data.slice(offset)) + } + } catch (err) { + util.destroy(socket, err) + } } - destroy (err) { - if (this.destroyed) { - // Node < 16 - return this - } + destroy () { + assert(this.ptr != null) + assert(currentParser == null) - if (!err && !this._readableState.endEmitted) { - err = new RequestAbortedError() - } + this.llhttp.llhttp_free(this.ptr) + this.ptr = null - if (err) { - this[kAbort]() - } + this.timeout && timers.clearTimeout(this.timeout) + this.timeout = null + this.timeoutValue = null + this.timeoutType = null - return super.destroy(err) + this.paused = false } - emit (ev, ...args) { - if (ev === 'data') { - // Node < 16.7 - this._readableState.dataEmitted = true - } else if (ev === 'error') { - // Node < 16 - this._readableState.errorEmitted = true - } - return super.emit(ev, ...args) + onStatus (buf) { + this.statusText = buf.toString() } - on (ev, ...args) { - if (ev === 'data' || ev === 'readable') { - this[kReading] = true + onMessageBegin () { + const { socket, client } = this + + /* istanbul ignore next: difficult to make a test case for */ + if (socket.destroyed) { + return -1 } - return super.on(ev, ...args) - } - addListener (ev, ...args) { - return this.on(ev, ...args) + const request = client[kQueue][client[kRunningIdx]] + if (!request) { + return -1 + } + request.onResponseStarted() } - off (ev, ...args) { - const ret = super.off(ev, ...args) - if (ev === 'data' || ev === 'readable') { - this[kReading] = ( - this.listenerCount('data') > 0 || - this.listenerCount('readable') > 0 - ) + onHeaderField (buf) { + const len = this.headers.length + + if ((len & 1) === 0) { + this.headers.push(buf) + } else { + this.headers[len - 1] = Buffer.concat([this.headers[len - 1], buf]) } - return ret - } - removeListener (ev, ...args) { - return this.off(ev, ...args) + this.trackHeader(buf.length) } - push (chunk) { - if (this[kConsume] && chunk !== null && this.readableLength === 0) { - consumePush(this[kConsume], chunk) - return this[kReading] ? super.push(chunk) : true + onHeaderValue (buf) { + let len = this.headers.length + + if ((len & 1) === 1) { + this.headers.push(buf) + len += 1 + } else { + this.headers[len - 1] = Buffer.concat([this.headers[len - 1], buf]) } - return super.push(chunk) - } - // https://fetch.spec.whatwg.org/#dom-body-text - async text () { - return consume(this, 'text') - } + const key = this.headers[len - 2] + if (key.length === 10) { + const headerName = util.bufferToLowerCasedHeaderName(key) + if (headerName === 'keep-alive') { + this.keepAlive += buf.toString() + } else if (headerName === 'connection') { + this.connection += buf.toString() + } + } else if (key.length === 14 && util.bufferToLowerCasedHeaderName(key) === 'content-length') { + this.contentLength += buf.toString() + } - // https://fetch.spec.whatwg.org/#dom-body-json - async json () { - return consume(this, 'json') + this.trackHeader(buf.length) } - // https://fetch.spec.whatwg.org/#dom-body-blob - async blob () { - return consume(this, 'blob') + trackHeader (len) { + this.headersSize += len + if (this.headersSize >= this.headersMaxSize) { + util.destroy(this.socket, new HeadersOverflowError()) + } } - // https://fetch.spec.whatwg.org/#dom-body-arraybuffer - async arrayBuffer () { - return consume(this, 'arrayBuffer') - } + onUpgrade (head) { + const { upgrade, client, socket, headers, statusCode } = this - // https://fetch.spec.whatwg.org/#dom-body-formdata - async formData () { - // TODO: Implement. - throw new NotSupportedError() - } + assert(upgrade) + assert(client[kSocket] === socket) + assert(!socket.destroyed) + assert(!this.paused) + assert((headers.length & 1) === 0) - // https://fetch.spec.whatwg.org/#dom-body-bodyused - get bodyUsed () { - return util.isDisturbed(this) - } + const request = client[kQueue][client[kRunningIdx]] + assert(request) + assert(request.upgrade || request.method === 'CONNECT') - // https://fetch.spec.whatwg.org/#dom-body-body - get body () { - if (!this[kBody]) { - this[kBody] = ReadableStreamFrom(this) - if (this[kConsume]) { - // TODO: Is this the best way to force a lock? - this[kBody].getReader() // Ensure stream is locked. - assert(this[kBody].locked) - } - } - return this[kBody] - } + this.statusCode = null + this.statusText = '' + this.shouldKeepAlive = null - dump (opts) { - let limit = opts && Number.isFinite(opts.limit) ? opts.limit : 262144 - const signal = opts && opts.signal + this.headers = [] + this.headersSize = 0 - if (signal) { - try { - if (typeof signal !== 'object' || !('aborted' in signal)) { - throw new InvalidArgumentError('signal must be an AbortSignal') - } - util.throwIfAborted(signal) - } catch (err) { - return Promise.reject(err) - } - } + socket.unshift(head) - if (this.closed) { - return Promise.resolve(null) - } + socket[kParser].destroy() + socket[kParser] = null - return new Promise((resolve, reject) => { - const signalListenerCleanup = signal - ? util.addAbortListener(signal, () => { - this.destroy() - }) - : noop + socket[kClient] = null + socket[kError] = null - this - .on('close', function () { - signalListenerCleanup() - if (signal && signal.aborted) { - reject(signal.reason || Object.assign(new Error('The operation was aborted'), { name: 'AbortError' })) - } else { - resolve(null) - } - }) - .on('error', noop) - .on('data', function (chunk) { - limit -= chunk.length - if (limit <= 0) { - this.destroy() - } - }) - .resume() - }) - } -} + removeAllListeners(socket) -// https://streams.spec.whatwg.org/#readablestream-locked -function isLocked (self) { - // Consume is an implicit lock. - return (self[kBody] && self[kBody].locked === true) || self[kConsume] -} + client[kSocket] = null + client[kHTTPContext] = null // TODO (fix): This is hacky... + client[kQueue][client[kRunningIdx]++] = null + client.emit('disconnect', client[kUrl], [client], new InformationalError('upgrade')) -// https://fetch.spec.whatwg.org/#body-unusable -function isUnusable (self) { - return util.isDisturbed(self) || isLocked(self) -} + try { + request.onUpgrade(statusCode, headers, socket) + } catch (err) { + util.destroy(socket, err) + } -async function consume (stream, type) { - if (isUnusable(stream)) { - throw new TypeError('unusable') + client[kResume]() } - assert(!stream[kConsume]) + onHeadersComplete (statusCode, upgrade, shouldKeepAlive) { + const { client, socket, headers, statusText } = this - return new Promise((resolve, reject) => { - stream[kConsume] = { - type, - stream, - resolve, - reject, - length: 0, - body: [] + /* istanbul ignore next: difficult to make a test case for */ + if (socket.destroyed) { + return -1 } - stream - .on('error', function (err) { - consumeFinish(this[kConsume], err) - }) - .on('close', function () { - if (this[kConsume].body !== null) { - consumeFinish(this[kConsume], new RequestAbortedError()) - } - }) + const request = client[kQueue][client[kRunningIdx]] - process.nextTick(consumeStart, stream[kConsume]) - }) -} + /* istanbul ignore next: difficult to make a test case for */ + if (!request) { + return -1 + } -function consumeStart (consume) { - if (consume.body === null) { - return - } + assert(!this.upgrade) + assert(this.statusCode < 200) - const { _readableState: state } = consume.stream + if (statusCode === 100) { + util.destroy(socket, new SocketError('bad response', util.getSocketInfo(socket))) + return -1 + } - for (const chunk of state.buffer) { - consumePush(consume, chunk) - } + /* this can only happen if server is misbehaving */ + if (upgrade && !request.upgrade) { + util.destroy(socket, new SocketError('bad upgrade', util.getSocketInfo(socket))) + return -1 + } - if (state.endEmitted) { - consumeEnd(this[kConsume]) - } else { - consume.stream.on('end', function () { - consumeEnd(this[kConsume]) - }) - } + assert(this.timeoutType === TIMEOUT_HEADERS) - consume.stream.resume() + this.statusCode = statusCode + this.shouldKeepAlive = ( + shouldKeepAlive || + // Override llhttp value which does not allow keepAlive for HEAD. + (request.method === 'HEAD' && !socket[kReset] && this.connection.toLowerCase() === 'keep-alive') + ) - while (consume.stream.read() != null) { - // Loop - } -} + if (this.statusCode >= 200) { + const bodyTimeout = request.bodyTimeout != null + ? request.bodyTimeout + : client[kBodyTimeout] + this.setTimeout(bodyTimeout, TIMEOUT_BODY) + } else if (this.timeout) { + // istanbul ignore else: only for jest + if (this.timeout.refresh) { + this.timeout.refresh() + } + } -function consumeEnd (consume) { - const { type, body, resolve, stream, length } = consume + if (request.method === 'CONNECT') { + assert(client[kRunning] === 1) + this.upgrade = true + return 2 + } - try { - if (type === 'text') { - resolve(toUSVString(Buffer.concat(body))) - } else if (type === 'json') { - resolve(JSON.parse(Buffer.concat(body))) - } else if (type === 'arrayBuffer') { - const dst = new Uint8Array(length) + if (upgrade) { + assert(client[kRunning] === 1) + this.upgrade = true + return 2 + } - let pos = 0 - for (const buf of body) { - dst.set(buf, pos) - pos += buf.byteLength - } + assert((this.headers.length & 1) === 0) + this.headers = [] + this.headersSize = 0 - resolve(dst.buffer) - } else if (type === 'blob') { - if (!Blob) { - Blob = (__nccwpck_require__(181).Blob) + if (this.shouldKeepAlive && client[kPipelining]) { + const keepAliveTimeout = this.keepAlive ? util.parseKeepAliveTimeout(this.keepAlive) : null + + if (keepAliveTimeout != null) { + const timeout = Math.min( + keepAliveTimeout - client[kKeepAliveTimeoutThreshold], + client[kKeepAliveMaxTimeout] + ) + if (timeout <= 0) { + socket[kReset] = true + } else { + client[kKeepAliveTimeoutValue] = timeout + } + } else { + client[kKeepAliveTimeoutValue] = client[kKeepAliveDefaultTimeout] } - resolve(new Blob(body, { type: stream[kContentType] })) + } else { + // Stop more requests from being dispatched. + socket[kReset] = true } - consumeFinish(consume) - } catch (err) { - stream.destroy(err) - } -} + const pause = request.onHeaders(statusCode, headers, this.resume, statusText) === false -function consumePush (consume, chunk) { - consume.length += chunk.length - consume.body.push(chunk) -} + if (request.aborted) { + return -1 + } -function consumeFinish (consume, err) { - if (consume.body === null) { - return - } + if (request.method === 'HEAD') { + return 1 + } - if (err) { - consume.reject(err) - } else { - consume.resolve() + if (statusCode < 200) { + return 1 + } + + if (socket[kBlocking]) { + socket[kBlocking] = false + client[kResume]() + } + + return pause ? constants.ERROR.PAUSED : 0 } - consume.type = null - consume.stream = null - consume.resolve = null - consume.reject = null - consume.length = 0 - consume.body = null -} + onBody (buf) { + const { client, socket, statusCode, maxResponseSize } = this + if (socket.destroyed) { + return -1 + } -/***/ }), + const request = client[kQueue][client[kRunningIdx]] + assert(request) -/***/ 9252: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + assert(this.timeoutType === TIMEOUT_BODY) + if (this.timeout) { + // istanbul ignore else: only for jest + if (this.timeout.refresh) { + this.timeout.refresh() + } + } -const assert = __nccwpck_require__(2613) -const { - ResponseStatusCodeError -} = __nccwpck_require__(6738) -const { toUSVString } = __nccwpck_require__(5069) + assert(statusCode >= 200) -async function getResolveErrorBodyCallback ({ callback, body, contentType, statusCode, statusMessage, headers }) { - assert(body) + if (maxResponseSize > -1 && this.bytesRead + buf.length > maxResponseSize) { + util.destroy(socket, new ResponseExceededMaxSizeError()) + return -1 + } - let chunks = [] - let limit = 0 + this.bytesRead += buf.length - for await (const chunk of body) { - chunks.push(chunk) - limit += chunk.length - if (limit > 128 * 1024) { - chunks = null - break + if (request.onData(buf) === false) { + return constants.ERROR.PAUSED } } - if (statusCode === 204 || !contentType || !chunks) { - process.nextTick(callback, new ResponseStatusCodeError(`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`, statusCode, headers)) - return - } + onMessageComplete () { + const { client, socket, statusCode, upgrade, headers, contentLength, bytesRead, shouldKeepAlive } = this - try { - if (contentType.startsWith('application/json')) { - const payload = JSON.parse(toUSVString(Buffer.concat(chunks))) - process.nextTick(callback, new ResponseStatusCodeError(`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`, statusCode, headers, payload)) - return + if (socket.destroyed && (!statusCode || shouldKeepAlive)) { + return -1 } - if (contentType.startsWith('text/')) { - const payload = toUSVString(Buffer.concat(chunks)) - process.nextTick(callback, new ResponseStatusCodeError(`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`, statusCode, headers, payload)) + if (upgrade) { return } - } catch (err) { - // Process in a fallback if error - } - process.nextTick(callback, new ResponseStatusCodeError(`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`, statusCode, headers)) -} + assert(statusCode >= 100) + assert((this.headers.length & 1) === 0) -module.exports = { getResolveErrorBodyCallback } + const request = client[kQueue][client[kRunningIdx]] + assert(request) + this.statusCode = null + this.statusText = '' + this.bytesRead = 0 + this.contentLength = '' + this.keepAlive = '' + this.connection = '' -/***/ }), + this.headers = [] + this.headersSize = 0 -/***/ 3700: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + if (statusCode < 200) { + return + } -"use strict"; + /* istanbul ignore next: should be handled by llhttp? */ + if (request.method !== 'HEAD' && contentLength && bytesRead !== parseInt(contentLength, 10)) { + util.destroy(socket, new ResponseContentLengthMismatchError()) + return -1 + } + request.onComplete(headers) -const { - BalancedPoolMissingUpstreamError, - InvalidArgumentError -} = __nccwpck_require__(6738) -const { - PoolBase, - kClients, - kNeedDrain, - kAddClient, - kRemoveClient, - kGetDispatcher -} = __nccwpck_require__(9237) -const Pool = __nccwpck_require__(7279) -const { kUrl, kInterceptors } = __nccwpck_require__(1028) -const { parseOrigin } = __nccwpck_require__(5069) -const kFactory = Symbol('factory') + client[kQueue][client[kRunningIdx]++] = null -const kOptions = Symbol('options') -const kGreatestCommonDivisor = Symbol('kGreatestCommonDivisor') -const kCurrentWeight = Symbol('kCurrentWeight') -const kIndex = Symbol('kIndex') -const kWeight = Symbol('kWeight') -const kMaxWeightPerServer = Symbol('kMaxWeightPerServer') -const kErrorPenalty = Symbol('kErrorPenalty') - -function getGreatestCommonDivisor (a, b) { - if (b === 0) return a - return getGreatestCommonDivisor(b, a % b) -} - -function defaultFactory (origin, opts) { - return new Pool(origin, opts) + if (socket[kWriting]) { + assert(client[kRunning] === 0) + // Response completed before request. + util.destroy(socket, new InformationalError('reset')) + return constants.ERROR.PAUSED + } else if (!shouldKeepAlive) { + util.destroy(socket, new InformationalError('reset')) + return constants.ERROR.PAUSED + } else if (socket[kReset] && client[kRunning] === 0) { + // Destroy socket once all requests have completed. + // The request at the tail of the pipeline is the one + // that requested reset and no further requests should + // have been queued since then. + util.destroy(socket, new InformationalError('reset')) + return constants.ERROR.PAUSED + } else if (client[kPipelining] == null || client[kPipelining] === 1) { + // We must wait a full event loop cycle to reuse this socket to make sure + // that non-spec compliant servers are not closing the connection even if they + // said they won't. + setImmediate(() => client[kResume]()) + } else { + client[kResume]() + } + } } -class BalancedPool extends PoolBase { - constructor (upstreams = [], { factory = defaultFactory, ...opts } = {}) { - super() - - this[kOptions] = opts - this[kIndex] = -1 - this[kCurrentWeight] = 0 - - this[kMaxWeightPerServer] = this[kOptions].maxWeightPerServer || 100 - this[kErrorPenalty] = this[kOptions].errorPenalty || 15 - - if (!Array.isArray(upstreams)) { - upstreams = [upstreams] - } +function onParserTimeout (parser) { + const { socket, timeoutType, client, paused } = parser.deref() - if (typeof factory !== 'function') { - throw new InvalidArgumentError('factory must be a function.') + /* istanbul ignore else */ + if (timeoutType === TIMEOUT_HEADERS) { + if (!socket[kWriting] || socket.writableNeedDrain || client[kRunning] > 1) { + assert(!paused, 'cannot be paused while waiting for headers') + util.destroy(socket, new HeadersTimeoutError()) } - - this[kInterceptors] = opts.interceptors && opts.interceptors.BalancedPool && Array.isArray(opts.interceptors.BalancedPool) - ? opts.interceptors.BalancedPool - : [] - this[kFactory] = factory - - for (const upstream of upstreams) { - this.addUpstream(upstream) + } else if (timeoutType === TIMEOUT_BODY) { + if (!paused) { + util.destroy(socket, new BodyTimeoutError()) } - this._updateBalancedPoolStats() + } else if (timeoutType === TIMEOUT_KEEP_ALIVE) { + assert(client[kRunning] === 0 && client[kKeepAliveTimeoutValue]) + util.destroy(socket, new InformationalError('socket idle timeout')) } +} - addUpstream (upstream) { - const upstreamOrigin = parseOrigin(upstream).origin +async function connectH1 (client, socket) { + client[kSocket] = socket - if (this[kClients].find((pool) => ( - pool[kUrl].origin === upstreamOrigin && - pool.closed !== true && - pool.destroyed !== true - ))) { - return this - } - const pool = this[kFactory](upstreamOrigin, Object.assign({}, this[kOptions])) + if (!llhttpInstance) { + llhttpInstance = await llhttpPromise + llhttpPromise = null + } - this[kAddClient](pool) - pool.on('connect', () => { - pool[kWeight] = Math.min(this[kMaxWeightPerServer], pool[kWeight] + this[kErrorPenalty]) - }) + socket[kNoRef] = false + socket[kWriting] = false + socket[kReset] = false + socket[kBlocking] = false + socket[kParser] = new Parser(client, socket, llhttpInstance) - pool.on('connectionError', () => { - pool[kWeight] = Math.max(1, pool[kWeight] - this[kErrorPenalty]) - this._updateBalancedPoolStats() - }) + addListener(socket, 'error', function (err) { + assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID') - pool.on('disconnect', (...args) => { - const err = args[2] - if (err && err.code === 'UND_ERR_SOCKET') { - // decrease the weight of the pool. - pool[kWeight] = Math.max(1, pool[kWeight] - this[kErrorPenalty]) - this._updateBalancedPoolStats() - } - }) + const parser = this[kParser] - for (const client of this[kClients]) { - client[kWeight] = this[kMaxWeightPerServer] + // On Mac OS, we get an ECONNRESET even if there is a full body to be forwarded + // to the user. + if (err.code === 'ECONNRESET' && parser.statusCode && !parser.shouldKeepAlive) { + // We treat all incoming data so for as a valid response. + parser.onMessageComplete() + return } - this._updateBalancedPoolStats() + this[kError] = err - return this - } + this[kClient][kOnError](err) + }) + addListener(socket, 'readable', function () { + const parser = this[kParser] - _updateBalancedPoolStats () { - this[kGreatestCommonDivisor] = this[kClients].map(p => p[kWeight]).reduce(getGreatestCommonDivisor, 0) - } + if (parser) { + parser.readMore() + } + }) + addListener(socket, 'end', function () { + const parser = this[kParser] - removeUpstream (upstream) { - const upstreamOrigin = parseOrigin(upstream).origin + if (parser.statusCode && !parser.shouldKeepAlive) { + // We treat all incoming data so far as a valid response. + parser.onMessageComplete() + return + } - const pool = this[kClients].find((pool) => ( - pool[kUrl].origin === upstreamOrigin && - pool.closed !== true && - pool.destroyed !== true - )) + util.destroy(this, new SocketError('other side closed', util.getSocketInfo(this))) + }) + addListener(socket, 'close', function () { + const client = this[kClient] + const parser = this[kParser] - if (pool) { - this[kRemoveClient](pool) + if (parser) { + if (!this[kError] && parser.statusCode && !parser.shouldKeepAlive) { + // We treat all incoming data so far as a valid response. + parser.onMessageComplete() + } + + this[kParser].destroy() + this[kParser] = null } - return this - } + const err = this[kError] || new SocketError('closed', util.getSocketInfo(this)) - get upstreams () { - return this[kClients] - .filter(dispatcher => dispatcher.closed !== true && dispatcher.destroyed !== true) - .map((p) => p[kUrl].origin) - } + client[kSocket] = null + client[kHTTPContext] = null // TODO (fix): This is hacky... - [kGetDispatcher] () { - // We validate that pools is greater than 0, - // otherwise we would have to wait until an upstream - // is added, which might never happen. - if (this[kClients].length === 0) { - throw new BalancedPoolMissingUpstreamError() - } + if (client.destroyed) { + assert(client[kPending] === 0) - const dispatcher = this[kClients].find(dispatcher => ( - !dispatcher[kNeedDrain] && - dispatcher.closed !== true && - dispatcher.destroyed !== true - )) + // Fail entire queue. + const requests = client[kQueue].splice(client[kRunningIdx]) + for (let i = 0; i < requests.length; i++) { + const request = requests[i] + util.errorRequest(client, request, err) + } + } else if (client[kRunning] > 0 && err.code !== 'UND_ERR_INFO') { + // Fail head of pipeline. + const request = client[kQueue][client[kRunningIdx]] + client[kQueue][client[kRunningIdx]++] = null - if (!dispatcher) { - return + util.errorRequest(client, request, err) } - const allClientsBusy = this[kClients].map(pool => pool[kNeedDrain]).reduce((a, b) => a && b, true) + client[kPendingIdx] = client[kRunningIdx] - if (allClientsBusy) { - return - } + assert(client[kRunning] === 0) - let counter = 0 + client.emit('disconnect', client[kUrl], [client], err) - let maxWeightIndex = this[kClients].findIndex(pool => !pool[kNeedDrain]) + client[kResume]() + }) - while (counter++ < this[kClients].length) { - this[kIndex] = (this[kIndex] + 1) % this[kClients].length - const pool = this[kClients][this[kIndex]] + let closed = false + socket.on('close', () => { + closed = true + }) - // find pool index with the largest weight - if (pool[kWeight] > this[kClients][maxWeightIndex][kWeight] && !pool[kNeedDrain]) { - maxWeightIndex = this[kIndex] + return { + version: 'h1', + defaultPipelining: 1, + write (...args) { + return writeH1(client, ...args) + }, + resume () { + resumeH1(client) + }, + destroy (err, callback) { + if (closed) { + queueMicrotask(callback) + } else { + socket.destroy(err).on('close', callback) + } + }, + get destroyed () { + return socket.destroyed + }, + busy (request) { + if (socket[kWriting] || socket[kReset] || socket[kBlocking]) { + return true } - // decrease the current weight every `this[kClients].length`. - if (this[kIndex] === 0) { - // Set the current weight to the next lower weight. - this[kCurrentWeight] = this[kCurrentWeight] - this[kGreatestCommonDivisor] + if (request) { + if (client[kRunning] > 0 && !request.idempotent) { + // Non-idempotent request cannot be retried. + // Ensure that no other requests are inflight and + // could cause failure. + return true + } - if (this[kCurrentWeight] <= 0) { - this[kCurrentWeight] = this[kMaxWeightPerServer] + if (client[kRunning] > 0 && (request.upgrade || request.method === 'CONNECT')) { + // Don't dispatch an upgrade until all preceding requests have completed. + // A misbehaving server might upgrade the connection before all pipelined + // request has completed. + return true + } + + if (client[kRunning] > 0 && util.bodyLength(request.body) !== 0 && + (util.isStream(request.body) || util.isAsyncIterable(request.body) || util.isFormDataLike(request.body))) { + // Request with stream or iterator body can error while other requests + // are inflight and indirectly error those as well. + // Ensure this doesn't happen by waiting for inflight + // to complete before dispatching. + + // Request with stream or iterator body cannot be retried. + // Ensure that no other requests are inflight and + // could cause failure. + return true } } - if (pool[kWeight] >= this[kCurrentWeight] && (!pool[kNeedDrain])) { - return pool - } - } - this[kCurrentWeight] = this[kClients][maxWeightIndex][kWeight] - this[kIndex] = maxWeightIndex - return this[kClients][maxWeightIndex] + return false + } } } -module.exports = BalancedPool - +function resumeH1 (client) { + const socket = client[kSocket] -/***/ }), + if (socket && !socket.destroyed) { + if (client[kSize] === 0) { + if (!socket[kNoRef] && socket.unref) { + socket.unref() + socket[kNoRef] = true + } + } else if (socket[kNoRef] && socket.ref) { + socket.ref() + socket[kNoRef] = false + } -/***/ 7673: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + if (client[kSize] === 0) { + if (socket[kParser].timeoutType !== TIMEOUT_KEEP_ALIVE) { + socket[kParser].setTimeout(client[kKeepAliveTimeoutValue], TIMEOUT_KEEP_ALIVE) + } + } else if (client[kRunning] > 0 && socket[kParser].statusCode < 200) { + if (socket[kParser].timeoutType !== TIMEOUT_HEADERS) { + const request = client[kQueue][client[kRunningIdx]] + const headersTimeout = request.headersTimeout != null + ? request.headersTimeout + : client[kHeadersTimeout] + socket[kParser].setTimeout(headersTimeout, TIMEOUT_HEADERS) + } + } + } +} -"use strict"; +// https://www.rfc-editor.org/rfc/rfc7230#section-3.3.2 +function shouldSendContentLength (method) { + return method !== 'GET' && method !== 'HEAD' && method !== 'OPTIONS' && method !== 'TRACE' && method !== 'CONNECT' +} +function writeH1 (client, request) { + const { method, path, host, upgrade, blocking, reset } = request -const { kConstruct } = __nccwpck_require__(4193) -const { urlEquals, fieldValues: getFieldValues } = __nccwpck_require__(1066) -const { kEnumerableProperty, isDisturbed } = __nccwpck_require__(5069) -const { kHeadersList } = __nccwpck_require__(1028) -const { webidl } = __nccwpck_require__(8201) -const { Response, cloneResponse } = __nccwpck_require__(5743) -const { Request } = __nccwpck_require__(4555) -const { kState, kHeaders, kGuard, kRealm } = __nccwpck_require__(2895) -const { fetching } = __nccwpck_require__(8130) -const { urlIsHttpHttpsScheme, createDeferredPromise, readAllBytes } = __nccwpck_require__(1612) -const assert = __nccwpck_require__(2613) -const { getGlobalDispatcher } = __nccwpck_require__(5334) + let { body, headers, contentLength } = request -/** - * @see https://w3c.github.io/ServiceWorker/#dfn-cache-batch-operation - * @typedef {Object} CacheBatchOperation - * @property {'delete' | 'put'} type - * @property {any} request - * @property {any} response - * @property {import('../../types/cache').CacheQueryOptions} options - */ + // https://tools.ietf.org/html/rfc7231#section-4.3.1 + // https://tools.ietf.org/html/rfc7231#section-4.3.2 + // https://tools.ietf.org/html/rfc7231#section-4.3.5 -/** - * @see https://w3c.github.io/ServiceWorker/#dfn-request-response-list - * @typedef {[any, any][]} requestResponseList - */ + // Sending a payload body on a request that does not + // expect it can cause undefined behavior on some + // servers and corrupt connection state. Do not + // re-use the connection for further requests. -class Cache { - /** - * @see https://w3c.github.io/ServiceWorker/#dfn-relevant-request-response-list - * @type {requestResponseList} - */ - #relevantRequestResponseList + const expectsPayload = ( + method === 'PUT' || + method === 'POST' || + method === 'PATCH' || + method === 'QUERY' || + method === 'PROPFIND' || + method === 'PROPPATCH' + ) - constructor () { - if (arguments[0] !== kConstruct) { - webidl.illegalConstructor() + if (util.isFormDataLike(body)) { + if (!extractBody) { + extractBody = (__nccwpck_require__(8106).extractBody) } - this.#relevantRequestResponseList = arguments[1] + const [bodyStream, contentType] = extractBody(body) + if (request.contentType == null) { + headers.push('content-type', contentType) + } + body = bodyStream.stream + contentLength = bodyStream.length + } else if (util.isBlobLike(body) && request.contentType == null && body.type) { + headers.push('content-type', body.type) } - async match (request, options = {}) { - webidl.brandCheck(this, Cache) - webidl.argumentLengthCheck(arguments, 1, { header: 'Cache.match' }) - - request = webidl.converters.RequestInfo(request) - options = webidl.converters.CacheQueryOptions(options) + if (body && typeof body.read === 'function') { + // Try to read EOF in order to get length. + body.read(0) + } - const p = await this.matchAll(request, options) + const bodyLength = util.bodyLength(body) - if (p.length === 0) { - return - } + contentLength = bodyLength ?? contentLength - return p[0] + if (contentLength === null) { + contentLength = request.contentLength } - async matchAll (request = undefined, options = {}) { - webidl.brandCheck(this, Cache) - - if (request !== undefined) request = webidl.converters.RequestInfo(request) - options = webidl.converters.CacheQueryOptions(options) - - // 1. - let r = null + if (contentLength === 0 && !expectsPayload) { + // https://tools.ietf.org/html/rfc7230#section-3.3.2 + // A user agent SHOULD NOT send a Content-Length header field when + // the request message does not contain a payload body and the method + // semantics do not anticipate such a body. - // 2. - if (request !== undefined) { - if (request instanceof Request) { - // 2.1.1 - r = request[kState] + contentLength = null + } - // 2.1.2 - if (r.method !== 'GET' && !options.ignoreMethod) { - return [] - } - } else if (typeof request === 'string') { - // 2.2.1 - r = new Request(request)[kState] - } + // https://github.com/nodejs/undici/issues/2046 + // A user agent may send a Content-Length header with 0 value, this should be allowed. + if (shouldSendContentLength(method) && contentLength > 0 && request.contentLength !== null && request.contentLength !== contentLength) { + if (client[kStrictContentLength]) { + util.errorRequest(client, request, new RequestContentLengthMismatchError()) + return false } - // 5. - // 5.1 - const responses = [] + process.emitWarning(new RequestContentLengthMismatchError()) + } - // 5.2 - if (request === undefined) { - // 5.2.1 - for (const requestResponse of this.#relevantRequestResponseList) { - responses.push(requestResponse[1]) - } - } else { // 5.3 - // 5.3.1 - const requestResponses = this.#queryCache(r, options) + const socket = client[kSocket] - // 5.3.2 - for (const requestResponse of requestResponses) { - responses.push(requestResponse[1]) - } + const abort = (err) => { + if (request.aborted || request.completed) { + return } - // 5.4 - // We don't implement CORs so we don't need to loop over the responses, yay! - - // 5.5.1 - const responseList = [] + util.errorRequest(client, request, err || new RequestAbortedError()) - // 5.5.2 - for (const response of responses) { - // 5.5.2.1 - const responseObject = new Response(response.body?.source ?? null) - const body = responseObject[kState].body - responseObject[kState] = response - responseObject[kState].body = body - responseObject[kHeaders][kHeadersList] = response.headersList - responseObject[kHeaders][kGuard] = 'immutable' + util.destroy(body) + util.destroy(socket, new InformationalError('aborted')) + } - responseList.push(responseObject) - } + try { + request.onConnect(abort) + } catch (err) { + util.errorRequest(client, request, err) + } - // 6. - return Object.freeze(responseList) + if (request.aborted) { + return false } - async add (request) { - webidl.brandCheck(this, Cache) - webidl.argumentLengthCheck(arguments, 1, { header: 'Cache.add' }) + if (method === 'HEAD') { + // https://github.com/mcollina/undici/issues/258 + // Close after a HEAD request to interop with misbehaving servers + // that may send a body in the response. - request = webidl.converters.RequestInfo(request) + socket[kReset] = true + } - // 1. - const requests = [request] + if (upgrade || method === 'CONNECT') { + // On CONNECT or upgrade, block pipeline from dispatching further + // requests on this connection. - // 2. - const responseArrayPromise = this.addAll(requests) + socket[kReset] = true + } - // 3. - return await responseArrayPromise + if (reset != null) { + socket[kReset] = reset } - async addAll (requests) { - webidl.brandCheck(this, Cache) - webidl.argumentLengthCheck(arguments, 1, { header: 'Cache.addAll' }) + if (client[kMaxRequests] && socket[kCounter]++ >= client[kMaxRequests]) { + socket[kReset] = true + } - requests = webidl.converters['sequence'](requests) + if (blocking) { + socket[kBlocking] = true + } - // 1. - const responsePromises = [] + let header = `${method} ${path} HTTP/1.1\r\n` - // 2. - const requestList = [] + if (typeof host === 'string') { + header += `host: ${host}\r\n` + } else { + header += client[kHostHeader] + } - // 3. - for (const request of requests) { - if (typeof request === 'string') { - continue - } + if (upgrade) { + header += `connection: upgrade\r\nupgrade: ${upgrade}\r\n` + } else if (client[kPipelining] && !socket[kReset]) { + header += 'connection: keep-alive\r\n' + } else { + header += 'connection: close\r\n' + } - // 3.1 - const r = request[kState] + if (Array.isArray(headers)) { + for (let n = 0; n < headers.length; n += 2) { + const key = headers[n + 0] + const val = headers[n + 1] - // 3.2 - if (!urlIsHttpHttpsScheme(r.url) || r.method !== 'GET') { - throw webidl.errors.exception({ - header: 'Cache.addAll', - message: 'Expected http/s scheme when method is not GET.' - }) + if (Array.isArray(val)) { + for (let i = 0; i < val.length; i++) { + header += `${key}: ${val[i]}\r\n` + } + } else { + header += `${key}: ${val}\r\n` } } + } - // 4. - /** @type {ReturnType[]} */ - const fetchControllers = [] - - // 5. - for (const request of requests) { - // 5.1 - const r = new Request(request)[kState] - - // 5.2 - if (!urlIsHttpHttpsScheme(r.url)) { - throw webidl.errors.exception({ - header: 'Cache.addAll', - message: 'Expected http/s scheme.' - }) - } + if (channels.sendHeaders.hasSubscribers) { + channels.sendHeaders.publish({ request, headers: header, socket }) + } - // 5.4 - r.initiator = 'fetch' - r.destination = 'subresource' + /* istanbul ignore else: assertion */ + if (!body || bodyLength === 0) { + writeBuffer(abort, null, client, request, socket, contentLength, header, expectsPayload) + } else if (util.isBuffer(body)) { + writeBuffer(abort, body, client, request, socket, contentLength, header, expectsPayload) + } else if (util.isBlobLike(body)) { + if (typeof body.stream === 'function') { + writeIterable(abort, body.stream(), client, request, socket, contentLength, header, expectsPayload) + } else { + writeBlob(abort, body, client, request, socket, contentLength, header, expectsPayload) + } + } else if (util.isStream(body)) { + writeStream(abort, body, client, request, socket, contentLength, header, expectsPayload) + } else if (util.isIterable(body)) { + writeIterable(abort, body, client, request, socket, contentLength, header, expectsPayload) + } else { + assert(false) + } - // 5.5 - requestList.push(r) + return true +} - // 5.6 - const responsePromise = createDeferredPromise() +function writeStream (abort, body, client, request, socket, contentLength, header, expectsPayload) { + assert(contentLength !== 0 || client[kRunning] === 0, 'stream body cannot be pipelined') - // 5.7 - fetchControllers.push(fetching({ - request: r, - dispatcher: getGlobalDispatcher(), - processResponse (response) { - // 1. - if (response.type === 'error' || response.status === 206 || response.status < 200 || response.status > 299) { - responsePromise.reject(webidl.errors.exception({ - header: 'Cache.addAll', - message: 'Received an invalid status code or the request failed.' - })) - } else if (response.headersList.contains('vary')) { // 2. - // 2.1 - const fieldValues = getFieldValues(response.headersList.get('vary')) + let finished = false - // 2.2 - for (const fieldValue of fieldValues) { - // 2.2.1 - if (fieldValue === '*') { - responsePromise.reject(webidl.errors.exception({ - header: 'Cache.addAll', - message: 'invalid vary field value' - })) + const writer = new AsyncWriter({ abort, socket, request, contentLength, client, expectsPayload, header }) - for (const controller of fetchControllers) { - controller.abort() - } + const onData = function (chunk) { + if (finished) { + return + } - return - } - } - } - }, - processResponseEndOfBody (response) { - // 1. - if (response.aborted) { - responsePromise.reject(new DOMException('aborted', 'AbortError')) - return - } + try { + if (!writer.write(chunk) && this.pause) { + this.pause() + } + } catch (err) { + util.destroy(this, err) + } + } + const onDrain = function () { + if (finished) { + return + } - // 2. - responsePromise.resolve(response) - } - })) + if (body.resume) { + body.resume() + } + } + const onClose = function () { + // 'close' might be emitted *before* 'error' for + // broken streams. Wait a tick to avoid this case. + queueMicrotask(() => { + // It's only safe to remove 'error' listener after + // 'close'. + body.removeListener('error', onFinished) + }) - // 5.8 - responsePromises.push(responsePromise.promise) + if (!finished) { + const err = new RequestAbortedError() + queueMicrotask(() => onFinished(err)) + } + } + const onFinished = function (err) { + if (finished) { + return } - // 6. - const p = Promise.all(responsePromises) + finished = true - // 7. - const responses = await p + assert(socket.destroyed || (socket[kWriting] && client[kRunning] <= 1)) - // 7.1 - const operations = [] + socket + .off('drain', onDrain) + .off('error', onFinished) - // 7.2 - let index = 0 + body + .removeListener('data', onData) + .removeListener('end', onFinished) + .removeListener('close', onClose) - // 7.3 - for (const response of responses) { - // 7.3.1 - /** @type {CacheBatchOperation} */ - const operation = { - type: 'put', // 7.3.2 - request: requestList[index], // 7.3.3 - response // 7.3.4 + if (!err) { + try { + writer.end() + } catch (er) { + err = er } - - operations.push(operation) // 7.3.5 - - index++ // 7.3.6 } - // 7.5 - const cacheJobPromise = createDeferredPromise() - - // 7.6.1 - let errorData = null + writer.destroy(err) - // 7.6.2 - try { - this.#batchCacheOperations(operations) - } catch (e) { - errorData = e + if (err && (err.code !== 'UND_ERR_INFO' || err.message !== 'reset')) { + util.destroy(body, err) + } else { + util.destroy(body) } + } - // 7.6.3 - queueMicrotask(() => { - // 7.6.3.1 - if (errorData === null) { - cacheJobPromise.resolve(undefined) - } else { - // 7.6.3.2 - cacheJobPromise.reject(errorData) - } - }) + body + .on('data', onData) + .on('end', onFinished) + .on('error', onFinished) + .on('close', onClose) - // 7.7 - return cacheJobPromise.promise + if (body.resume) { + body.resume() } - async put (request, response) { - webidl.brandCheck(this, Cache) - webidl.argumentLengthCheck(arguments, 2, { header: 'Cache.put' }) - - request = webidl.converters.RequestInfo(request) - response = webidl.converters.Response(response) + socket + .on('drain', onDrain) + .on('error', onFinished) - // 1. - let innerRequest = null + if (body.errorEmitted ?? body.errored) { + setImmediate(() => onFinished(body.errored)) + } else if (body.endEmitted ?? body.readableEnded) { + setImmediate(() => onFinished(null)) + } - // 2. - if (request instanceof Request) { - innerRequest = request[kState] - } else { // 3. - innerRequest = new Request(request)[kState] - } + if (body.closeEmitted ?? body.closed) { + setImmediate(onClose) + } +} - // 4. - if (!urlIsHttpHttpsScheme(innerRequest.url) || innerRequest.method !== 'GET') { - throw webidl.errors.exception({ - header: 'Cache.put', - message: 'Expected an http/s scheme when method is not GET' - }) - } +function writeBuffer (abort, body, client, request, socket, contentLength, header, expectsPayload) { + try { + if (!body) { + if (contentLength === 0) { + socket.write(`${header}content-length: 0\r\n\r\n`, 'latin1') + } else { + assert(contentLength === null, 'no body must not have content length') + socket.write(`${header}\r\n`, 'latin1') + } + } else if (util.isBuffer(body)) { + assert(contentLength === body.byteLength, 'buffer body must have content length') - // 5. - const innerResponse = response[kState] + socket.cork() + socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'latin1') + socket.write(body) + socket.uncork() + request.onBodySent(body) - // 6. - if (innerResponse.status === 206) { - throw webidl.errors.exception({ - header: 'Cache.put', - message: 'Got 206 status' - }) + if (!expectsPayload && request.reset !== false) { + socket[kReset] = true + } } + request.onRequestSent() - // 7. - if (innerResponse.headersList.contains('vary')) { - // 7.1. - const fieldValues = getFieldValues(innerResponse.headersList.get('vary')) + client[kResume]() + } catch (err) { + abort(err) + } +} - // 7.2. - for (const fieldValue of fieldValues) { - // 7.2.1 - if (fieldValue === '*') { - throw webidl.errors.exception({ - header: 'Cache.put', - message: 'Got * vary field value' - }) - } - } - } +async function writeBlob (abort, body, client, request, socket, contentLength, header, expectsPayload) { + assert(contentLength === body.size, 'blob body must have content length') - // 8. - if (innerResponse.body && (isDisturbed(innerResponse.body.stream) || innerResponse.body.stream.locked)) { - throw webidl.errors.exception({ - header: 'Cache.put', - message: 'Response body is locked or disturbed' - }) + try { + if (contentLength != null && contentLength !== body.size) { + throw new RequestContentLengthMismatchError() } - // 9. - const clonedResponse = cloneResponse(innerResponse) - - // 10. - const bodyReadPromise = createDeferredPromise() + const buffer = Buffer.from(await body.arrayBuffer()) - // 11. - if (innerResponse.body != null) { - // 11.1 - const stream = innerResponse.body.stream + socket.cork() + socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'latin1') + socket.write(buffer) + socket.uncork() - // 11.2 - const reader = stream.getReader() + request.onBodySent(buffer) + request.onRequestSent() - // 11.3 - readAllBytes(reader).then(bodyReadPromise.resolve, bodyReadPromise.reject) - } else { - bodyReadPromise.resolve(undefined) + if (!expectsPayload && request.reset !== false) { + socket[kReset] = true } - // 12. - /** @type {CacheBatchOperation[]} */ - const operations = [] + client[kResume]() + } catch (err) { + abort(err) + } +} - // 13. - /** @type {CacheBatchOperation} */ - const operation = { - type: 'put', // 14. - request: innerRequest, // 15. - response: clonedResponse // 16. - } +async function writeIterable (abort, body, client, request, socket, contentLength, header, expectsPayload) { + assert(contentLength !== 0 || client[kRunning] === 0, 'iterator body cannot be pipelined') - // 17. - operations.push(operation) + let callback = null + function onDrain () { + if (callback) { + const cb = callback + callback = null + cb() + } + } - // 19. - const bytes = await bodyReadPromise.promise + const waitForDrain = () => new Promise((resolve, reject) => { + assert(callback === null) - if (clonedResponse.body != null) { - clonedResponse.body.source = bytes + if (socket[kError]) { + reject(socket[kError]) + } else { + callback = resolve } + }) - // 19.1 - const cacheJobPromise = createDeferredPromise() - - // 19.2.1 - let errorData = null + socket + .on('close', onDrain) + .on('drain', onDrain) - // 19.2.2 - try { - this.#batchCacheOperations(operations) - } catch (e) { - errorData = e - } + const writer = new AsyncWriter({ abort, socket, request, contentLength, client, expectsPayload, header }) + try { + // It's up to the user to somehow abort the async iterable. + for await (const chunk of body) { + if (socket[kError]) { + throw socket[kError] + } - // 19.2.3 - queueMicrotask(() => { - // 19.2.3.1 - if (errorData === null) { - cacheJobPromise.resolve() - } else { // 19.2.3.2 - cacheJobPromise.reject(errorData) + if (!writer.write(chunk)) { + await waitForDrain() } - }) + } - return cacheJobPromise.promise + writer.end() + } catch (err) { + writer.destroy(err) + } finally { + socket + .off('close', onDrain) + .off('drain', onDrain) } +} - async delete (request, options = {}) { - webidl.brandCheck(this, Cache) - webidl.argumentLengthCheck(arguments, 1, { header: 'Cache.delete' }) - - request = webidl.converters.RequestInfo(request) - options = webidl.converters.CacheQueryOptions(options) - - /** - * @type {Request} - */ - let r = null +class AsyncWriter { + constructor ({ abort, socket, request, contentLength, client, expectsPayload, header }) { + this.socket = socket + this.request = request + this.contentLength = contentLength + this.client = client + this.bytesWritten = 0 + this.expectsPayload = expectsPayload + this.header = header + this.abort = abort - if (request instanceof Request) { - r = request[kState] + socket[kWriting] = true + } - if (r.method !== 'GET' && !options.ignoreMethod) { - return false - } - } else { - assert(typeof request === 'string') + write (chunk) { + const { socket, request, contentLength, client, bytesWritten, expectsPayload, header } = this - r = new Request(request)[kState] + if (socket[kError]) { + throw socket[kError] } - /** @type {CacheBatchOperation[]} */ - const operations = [] + if (socket.destroyed) { + return false + } - /** @type {CacheBatchOperation} */ - const operation = { - type: 'delete', - request: r, - options + const len = Buffer.byteLength(chunk) + if (!len) { + return true } - operations.push(operation) + // We should defer writing chunks. + if (contentLength !== null && bytesWritten + len > contentLength) { + if (client[kStrictContentLength]) { + throw new RequestContentLengthMismatchError() + } - const cacheJobPromise = createDeferredPromise() + process.emitWarning(new RequestContentLengthMismatchError()) + } - let errorData = null - let requestResponses + socket.cork() - try { - requestResponses = this.#batchCacheOperations(operations) - } catch (e) { - errorData = e - } + if (bytesWritten === 0) { + if (!expectsPayload && request.reset !== false) { + socket[kReset] = true + } - queueMicrotask(() => { - if (errorData === null) { - cacheJobPromise.resolve(!!requestResponses?.length) + if (contentLength === null) { + socket.write(`${header}transfer-encoding: chunked\r\n`, 'latin1') } else { - cacheJobPromise.reject(errorData) + socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'latin1') } - }) + } - return cacheJobPromise.promise - } + if (contentLength === null) { + socket.write(`\r\n${len.toString(16)}\r\n`, 'latin1') + } - /** - * @see https://w3c.github.io/ServiceWorker/#dom-cache-keys - * @param {any} request - * @param {import('../../types/cache').CacheQueryOptions} options - * @returns {readonly Request[]} - */ - async keys (request = undefined, options = {}) { - webidl.brandCheck(this, Cache) + this.bytesWritten += len - if (request !== undefined) request = webidl.converters.RequestInfo(request) - options = webidl.converters.CacheQueryOptions(options) + const ret = socket.write(chunk) - // 1. - let r = null + socket.uncork() - // 2. - if (request !== undefined) { - // 2.1 - if (request instanceof Request) { - // 2.1.1 - r = request[kState] + request.onBodySent(chunk) - // 2.1.2 - if (r.method !== 'GET' && !options.ignoreMethod) { - return [] + if (!ret) { + if (socket[kParser].timeout && socket[kParser].timeoutType === TIMEOUT_HEADERS) { + // istanbul ignore else: only for jest + if (socket[kParser].timeout.refresh) { + socket[kParser].timeout.refresh() } - } else if (typeof request === 'string') { // 2.2 - r = new Request(request)[kState] } } - // 4. - const promise = createDeferredPromise() + return ret + } - // 5. - // 5.1 - const requests = [] + end () { + const { socket, contentLength, client, bytesWritten, expectsPayload, header, request } = this + request.onRequestSent() - // 5.2 - if (request === undefined) { - // 5.2.1 - for (const requestResponse of this.#relevantRequestResponseList) { - // 5.2.1.1 - requests.push(requestResponse[0]) - } - } else { // 5.3 - // 5.3.1 - const requestResponses = this.#queryCache(r, options) + socket[kWriting] = false - // 5.3.2 - for (const requestResponse of requestResponses) { - // 5.3.2.1 - requests.push(requestResponse[0]) - } + if (socket[kError]) { + throw socket[kError] } - // 5.4 - queueMicrotask(() => { - // 5.4.1 - const requestList = [] + if (socket.destroyed) { + return + } - // 5.4.2 - for (const request of requests) { - const requestObject = new Request('https://a') - requestObject[kState] = request - requestObject[kHeaders][kHeadersList] = request.headersList - requestObject[kHeaders][kGuard] = 'immutable' - requestObject[kRealm] = request.client + if (bytesWritten === 0) { + if (expectsPayload) { + // https://tools.ietf.org/html/rfc7230#section-3.3.2 + // A user agent SHOULD send a Content-Length in a request message when + // no Transfer-Encoding is sent and the request method defines a meaning + // for an enclosed payload body. - // 5.4.2.1 - requestList.push(requestObject) + socket.write(`${header}content-length: 0\r\n\r\n`, 'latin1') + } else { + socket.write(`${header}\r\n`, 'latin1') } + } else if (contentLength === null) { + socket.write('\r\n0\r\n\r\n', 'latin1') + } - // 5.4.3 - promise.resolve(Object.freeze(requestList)) - }) + if (contentLength !== null && bytesWritten !== contentLength) { + if (client[kStrictContentLength]) { + throw new RequestContentLengthMismatchError() + } else { + process.emitWarning(new RequestContentLengthMismatchError()) + } + } - return promise.promise - } + if (socket[kParser].timeout && socket[kParser].timeoutType === TIMEOUT_HEADERS) { + // istanbul ignore else: only for jest + if (socket[kParser].timeout.refresh) { + socket[kParser].timeout.refresh() + } + } - /** - * @see https://w3c.github.io/ServiceWorker/#batch-cache-operations-algorithm - * @param {CacheBatchOperation[]} operations - * @returns {requestResponseList} - */ - #batchCacheOperations (operations) { - // 1. - const cache = this.#relevantRequestResponseList + client[kResume]() + } - // 2. - const backupCache = [...cache] + destroy (err) { + const { socket, client, abort } = this - // 3. - const addedItems = [] + socket[kWriting] = false - // 4.1 - const resultList = [] + if (err) { + assert(client[kRunning] <= 1, 'pipeline should only contain this request') + abort(err) + } + } +} - try { - // 4.2 - for (const operation of operations) { - // 4.2.1 - if (operation.type !== 'delete' && operation.type !== 'put') { - throw webidl.errors.exception({ - header: 'Cache.#batchCacheOperations', - message: 'operation type does not match "delete" or "put"' - }) - } +module.exports = connectH1 - // 4.2.2 - if (operation.type === 'delete' && operation.response != null) { - throw webidl.errors.exception({ - header: 'Cache.#batchCacheOperations', - message: 'delete operation should not have an associated response' - }) - } - // 4.2.3 - if (this.#queryCache(operation.request, operation.options, addedItems).length) { - throw new DOMException('???', 'InvalidStateError') - } +/***/ }), - // 4.2.4 - let requestResponses +/***/ 2854: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - // 4.2.5 - if (operation.type === 'delete') { - // 4.2.5.1 - requestResponses = this.#queryCache(operation.request, operation.options) - // TODO: the spec is wrong, this is needed to pass WPTs - if (requestResponses.length === 0) { - return [] - } - // 4.2.5.2 - for (const requestResponse of requestResponses) { - const idx = cache.indexOf(requestResponse) - assert(idx !== -1) +const assert = __nccwpck_require__(4589) +const { pipeline } = __nccwpck_require__(7075) +const util = __nccwpck_require__(7234) +const { + RequestContentLengthMismatchError, + RequestAbortedError, + SocketError, + InformationalError +} = __nccwpck_require__(329) +const { + kUrl, + kReset, + kClient, + kRunning, + kPending, + kQueue, + kPendingIdx, + kRunningIdx, + kError, + kSocket, + kStrictContentLength, + kOnError, + kMaxConcurrentStreams, + kHTTP2Session, + kResume, + kSize, + kHTTPContext +} = __nccwpck_require__(7417) - // 4.2.5.2.1 - cache.splice(idx, 1) - } - } else if (operation.type === 'put') { // 4.2.6 - // 4.2.6.1 - if (operation.response == null) { - throw webidl.errors.exception({ - header: 'Cache.#batchCacheOperations', - message: 'put operation should have an associated response' - }) - } +const kOpenStreams = Symbol('open streams') - // 4.2.6.2 - const r = operation.request +let extractBody - // 4.2.6.3 - if (!urlIsHttpHttpsScheme(r.url)) { - throw webidl.errors.exception({ - header: 'Cache.#batchCacheOperations', - message: 'expected http or https scheme' - }) - } +// Experimental +let h2ExperimentalWarned = false - // 4.2.6.4 - if (r.method !== 'GET') { - throw webidl.errors.exception({ - header: 'Cache.#batchCacheOperations', - message: 'not get method' - }) - } +/** @type {import('http2')} */ +let http2 +try { + http2 = __nccwpck_require__(2467) +} catch { + // @ts-ignore + http2 = { constants: {} } +} - // 4.2.6.5 - if (operation.options != null) { - throw webidl.errors.exception({ - header: 'Cache.#batchCacheOperations', - message: 'options must not be defined' - }) - } +const { + constants: { + HTTP2_HEADER_AUTHORITY, + HTTP2_HEADER_METHOD, + HTTP2_HEADER_PATH, + HTTP2_HEADER_SCHEME, + HTTP2_HEADER_CONTENT_LENGTH, + HTTP2_HEADER_EXPECT, + HTTP2_HEADER_STATUS + } +} = http2 - // 4.2.6.6 - requestResponses = this.#queryCache(operation.request) +function parseH2Headers (headers) { + const result = [] - // 4.2.6.7 - for (const requestResponse of requestResponses) { - const idx = cache.indexOf(requestResponse) - assert(idx !== -1) + for (const [name, value] of Object.entries(headers)) { + // h2 may concat the header value by array + // e.g. Set-Cookie + if (Array.isArray(value)) { + for (const subvalue of value) { + // we need to provide each header value of header name + // because the headers handler expect name-value pair + result.push(Buffer.from(name), Buffer.from(subvalue)) + } + } else { + result.push(Buffer.from(name), Buffer.from(value)) + } + } - // 4.2.6.7.1 - cache.splice(idx, 1) - } + return result +} - // 4.2.6.8 - cache.push([operation.request, operation.response]) +async function connectH2 (client, socket) { + client[kSocket] = socket - // 4.2.6.10 - addedItems.push([operation.request, operation.response]) - } + if (!h2ExperimentalWarned) { + h2ExperimentalWarned = true + process.emitWarning('H2 support is experimental, expect them to change at any time.', { + code: 'UNDICI-H2' + }) + } - // 4.2.7 - resultList.push([operation.request, operation.response]) - } + const session = http2.connect(client[kUrl], { + createConnection: () => socket, + peerMaxConcurrentStreams: client[kMaxConcurrentStreams] + }) - // 4.3 - return resultList - } catch (e) { // 5. - // 5.1 - this.#relevantRequestResponseList.length = 0 + session[kOpenStreams] = 0 + session[kClient] = client + session[kSocket] = socket - // 5.2 - this.#relevantRequestResponseList = backupCache + util.addListener(session, 'error', onHttp2SessionError) + util.addListener(session, 'frameError', onHttp2FrameError) + util.addListener(session, 'end', onHttp2SessionEnd) + util.addListener(session, 'goaway', onHTTP2GoAway) + util.addListener(session, 'close', function () { + const { [kClient]: client } = this + const { [kSocket]: socket } = client - // 5.3 - throw e - } - } + const err = this[kSocket][kError] || this[kError] || new SocketError('closed', util.getSocketInfo(socket)) - /** - * @see https://w3c.github.io/ServiceWorker/#query-cache - * @param {any} requestQuery - * @param {import('../../types/cache').CacheQueryOptions} options - * @param {requestResponseList} targetStorage - * @returns {requestResponseList} - */ - #queryCache (requestQuery, options, targetStorage) { - /** @type {requestResponseList} */ - const resultList = [] + client[kHTTP2Session] = null - const storage = targetStorage ?? this.#relevantRequestResponseList + if (client.destroyed) { + assert(client[kPending] === 0) - for (const requestResponse of storage) { - const [cachedRequest, cachedResponse] = requestResponse - if (this.#requestMatchesCachedItem(requestQuery, cachedRequest, cachedResponse, options)) { - resultList.push(requestResponse) + // Fail entire queue. + const requests = client[kQueue].splice(client[kRunningIdx]) + for (let i = 0; i < requests.length; i++) { + const request = requests[i] + util.errorRequest(client, request, err) } } + }) - return resultList - } + session.unref() - /** - * @see https://w3c.github.io/ServiceWorker/#request-matches-cached-item-algorithm - * @param {any} requestQuery - * @param {any} request - * @param {any | null} response - * @param {import('../../types/cache').CacheQueryOptions | undefined} options - * @returns {boolean} - */ - #requestMatchesCachedItem (requestQuery, request, response = null, options) { - // if (options?.ignoreMethod === false && request.method === 'GET') { - // return false - // } + client[kHTTP2Session] = session + socket[kHTTP2Session] = session - const queryURL = new URL(requestQuery.url) + util.addListener(socket, 'error', function (err) { + assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID') - const cachedURL = new URL(request.url) + this[kError] = err - if (options?.ignoreSearch) { - cachedURL.search = '' + this[kClient][kOnError](err) + }) - queryURL.search = '' - } + util.addListener(socket, 'end', function () { + util.destroy(this, new SocketError('other side closed', util.getSocketInfo(this))) + }) - if (!urlEquals(queryURL, cachedURL, true)) { - return false - } + util.addListener(socket, 'close', function () { + const err = this[kError] || new SocketError('closed', util.getSocketInfo(this)) - if ( - response == null || - options?.ignoreVary || - !response.headersList.contains('vary') - ) { - return true + client[kSocket] = null + + if (this[kHTTP2Session] != null) { + this[kHTTP2Session].destroy(err) } - const fieldValues = getFieldValues(response.headersList.get('vary')) + client[kPendingIdx] = client[kRunningIdx] - for (const fieldValue of fieldValues) { - if (fieldValue === '*') { - return false - } + assert(client[kRunning] === 0) - const requestValue = request.headersList.get(fieldValue) - const queryValue = requestQuery.headersList.get(fieldValue) + client.emit('disconnect', client[kUrl], [client], err) - // If one has the header and the other doesn't, or one has - // a different value than the other, return false - if (requestValue !== queryValue) { - return false + client[kResume]() + }) + + let closed = false + socket.on('close', () => { + closed = true + }) + + return { + version: 'h2', + defaultPipelining: Infinity, + write (...args) { + return writeH2(client, ...args) + }, + resume () { + resumeH2(client) + }, + destroy (err, callback) { + if (closed) { + queueMicrotask(callback) + } else { + // Destroying the socket will trigger the session close + socket.destroy(err).on('close', callback) } + }, + get destroyed () { + return socket.destroyed + }, + busy () { + return false } - - return true } } -Object.defineProperties(Cache.prototype, { - [Symbol.toStringTag]: { - value: 'Cache', - configurable: true - }, - match: kEnumerableProperty, - matchAll: kEnumerableProperty, - add: kEnumerableProperty, - addAll: kEnumerableProperty, - put: kEnumerableProperty, - delete: kEnumerableProperty, - keys: kEnumerableProperty -}) - -const cacheQueryOptionConverters = [ - { - key: 'ignoreSearch', - converter: webidl.converters.boolean, - defaultValue: false - }, - { - key: 'ignoreMethod', - converter: webidl.converters.boolean, - defaultValue: false - }, - { - key: 'ignoreVary', - converter: webidl.converters.boolean, - defaultValue: false - } -] - -webidl.converters.CacheQueryOptions = webidl.dictionaryConverter(cacheQueryOptionConverters) +function resumeH2 (client) { + const socket = client[kSocket] -webidl.converters.MultiCacheQueryOptions = webidl.dictionaryConverter([ - ...cacheQueryOptionConverters, - { - key: 'cacheName', - converter: webidl.converters.DOMString + if (socket?.destroyed === false) { + if (client[kSize] === 0 && client[kMaxConcurrentStreams] === 0) { + socket.unref() + client[kHTTP2Session].unref() + } else { + socket.ref() + client[kHTTP2Session].ref() + } } -]) +} -webidl.converters.Response = webidl.interfaceConverter(Response) +function onHttp2SessionError (err) { + assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID') -webidl.converters['sequence'] = webidl.sequenceConverter( - webidl.converters.RequestInfo -) + this[kSocket][kError] = err + this[kClient][kOnError](err) +} -module.exports = { - Cache +function onHttp2FrameError (type, code, id) { + if (id === 0) { + const err = new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`) + this[kSocket][kError] = err + this[kClient][kOnError](err) + } } +function onHttp2SessionEnd () { + const err = new SocketError('other side closed', util.getSocketInfo(this[kSocket])) + this.destroy(err) + util.destroy(this[kSocket], err) +} -/***/ }), +/** + * This is the root cause of #3011 + * We need to handle GOAWAY frames properly, and trigger the session close + * along with the socket right away + */ +function onHTTP2GoAway (code) { + // We cannot recover, so best to close the session and the socket + const err = this[kError] || new SocketError(`HTTP/2: "GOAWAY" frame received with code ${code}`, util.getSocketInfo(this)) + const client = this[kClient] -/***/ 265: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + client[kSocket] = null + client[kHTTPContext] = null -"use strict"; + if (this[kHTTP2Session] != null) { + this[kHTTP2Session].destroy(err) + this[kHTTP2Session] = null + } + util.destroy(this[kSocket], err) -const { kConstruct } = __nccwpck_require__(4193) -const { Cache } = __nccwpck_require__(7673) -const { webidl } = __nccwpck_require__(8201) -const { kEnumerableProperty } = __nccwpck_require__(5069) + // Fail head of pipeline. + if (client[kRunningIdx] < client[kQueue].length) { + const request = client[kQueue][client[kRunningIdx]] + client[kQueue][client[kRunningIdx]++] = null + util.errorRequest(client, request, err) + client[kPendingIdx] = client[kRunningIdx] + } -class CacheStorage { - /** - * @see https://w3c.github.io/ServiceWorker/#dfn-relevant-name-to-cache-map - * @type {Map} - */ - async has (cacheName) { - webidl.brandCheck(this, CacheStorage) - webidl.argumentLengthCheck(arguments, 1, { header: 'CacheStorage.has' }) - - cacheName = webidl.converters.DOMString(cacheName) + /** @type {import('node:http2').ClientHttp2Stream} */ + let stream - // 2.1.1 - // 2.2 - return this.#caches.has(cacheName) - } + const { hostname, port } = client[kUrl] - /** - * @see https://w3c.github.io/ServiceWorker/#dom-cachestorage-open - * @param {string} cacheName - * @returns {Promise} - */ - async open (cacheName) { - webidl.brandCheck(this, CacheStorage) - webidl.argumentLengthCheck(arguments, 1, { header: 'CacheStorage.open' }) + headers[HTTP2_HEADER_AUTHORITY] = host || `${hostname}${port ? `:${port}` : ''}` + headers[HTTP2_HEADER_METHOD] = method - cacheName = webidl.converters.DOMString(cacheName) + const abort = (err) => { + if (request.aborted || request.completed) { + return + } - // 2.1 - if (this.#caches.has(cacheName)) { - // await caches.open('v1') !== await caches.open('v1') + err = err || new RequestAbortedError() - // 2.1.1 - const cache = this.#caches.get(cacheName) + util.errorRequest(client, request, err) - // 2.1.1.1 - return new Cache(kConstruct, cache) + if (stream != null) { + util.destroy(stream, err) } - // 2.2 - const cache = [] + // We do not destroy the socket as we can continue using the session + // the stream get's destroyed and the session remains to create new streams + util.destroy(body, err) + client[kQueue][client[kRunningIdx]++] = null + client[kResume]() + } - // 2.3 - this.#caches.set(cacheName, cache) + try { + // We are already connected, streams are pending. + // We can call on connect, and wait for abort + request.onConnect(abort) + } catch (err) { + util.errorRequest(client, request, err) + } - // 2.4 - return new Cache(kConstruct, cache) + if (request.aborted) { + return false } - /** - * @see https://w3c.github.io/ServiceWorker/#cache-storage-delete - * @param {string} cacheName - * @returns {Promise} - */ - async delete (cacheName) { - webidl.brandCheck(this, CacheStorage) - webidl.argumentLengthCheck(arguments, 1, { header: 'CacheStorage.delete' }) + if (method === 'CONNECT') { + session.ref() + // We are already connected, streams are pending, first request + // will create a new stream. We trigger a request to create the stream and wait until + // `ready` event is triggered + // We disabled endStream to allow the user to write to the stream + stream = session.request(headers, { endStream: false, signal }) - cacheName = webidl.converters.DOMString(cacheName) + if (stream.id && !stream.pending) { + request.onUpgrade(null, null, stream) + ++session[kOpenStreams] + client[kQueue][client[kRunningIdx]++] = null + } else { + stream.once('ready', () => { + request.onUpgrade(null, null, stream) + ++session[kOpenStreams] + client[kQueue][client[kRunningIdx]++] = null + }) + } - return this.#caches.delete(cacheName) + stream.once('close', () => { + session[kOpenStreams] -= 1 + if (session[kOpenStreams] === 0) session.unref() + }) + + return true } - /** - * @see https://w3c.github.io/ServiceWorker/#cache-storage-keys - * @returns {string[]} - */ - async keys () { - webidl.brandCheck(this, CacheStorage) + // https://tools.ietf.org/html/rfc7540#section-8.3 + // :path and :scheme headers must be omitted when sending CONNECT - // 2.1 - const keys = this.#caches.keys() + headers[HTTP2_HEADER_PATH] = path + headers[HTTP2_HEADER_SCHEME] = 'https' - // 2.2 - return [...keys] + // https://tools.ietf.org/html/rfc7231#section-4.3.1 + // https://tools.ietf.org/html/rfc7231#section-4.3.2 + // https://tools.ietf.org/html/rfc7231#section-4.3.5 + + // Sending a payload body on a request that does not + // expect it can cause undefined behavior on some + // servers and corrupt connection state. Do not + // re-use the connection for further requests. + + const expectsPayload = ( + method === 'PUT' || + method === 'POST' || + method === 'PATCH' + ) + + if (body && typeof body.read === 'function') { + // Try to read EOF in order to get length. + body.read(0) } -} -Object.defineProperties(CacheStorage.prototype, { - [Symbol.toStringTag]: { - value: 'CacheStorage', - configurable: true - }, - match: kEnumerableProperty, - has: kEnumerableProperty, - open: kEnumerableProperty, - delete: kEnumerableProperty, - keys: kEnumerableProperty -}) + let contentLength = util.bodyLength(body) -module.exports = { - CacheStorage -} + if (util.isFormDataLike(body)) { + extractBody ??= (__nccwpck_require__(8106).extractBody) + const [bodyStream, contentType] = extractBody(body) + headers['content-type'] = contentType -/***/ }), + body = bodyStream.stream + contentLength = bodyStream.length + } -/***/ 4193: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + if (contentLength == null) { + contentLength = request.contentLength + } -"use strict"; + if (contentLength === 0 || !expectsPayload) { + // https://tools.ietf.org/html/rfc7230#section-3.3.2 + // A user agent SHOULD NOT send a Content-Length header field when + // the request message does not contain a payload body and the method + // semantics do not anticipate such a body. + contentLength = null + } -module.exports = { - kConstruct: (__nccwpck_require__(1028).kConstruct) -} + // https://github.com/nodejs/undici/issues/2046 + // A user agent may send a Content-Length header with 0 value, this should be allowed. + if (shouldSendContentLength(method) && contentLength > 0 && request.contentLength != null && request.contentLength !== contentLength) { + if (client[kStrictContentLength]) { + util.errorRequest(client, request, new RequestContentLengthMismatchError()) + return false + } + process.emitWarning(new RequestContentLengthMismatchError()) + } -/***/ }), + if (contentLength != null) { + assert(body, 'no body must not have content length') + headers[HTTP2_HEADER_CONTENT_LENGTH] = `${contentLength}` + } -/***/ 1066: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + session.ref() -"use strict"; + const shouldEndStream = method === 'GET' || method === 'HEAD' || body === null + if (expectContinue) { + headers[HTTP2_HEADER_EXPECT] = '100-continue' + stream = session.request(headers, { endStream: shouldEndStream, signal }) + stream.once('continue', writeBodyH2) + } else { + stream = session.request(headers, { + endStream: shouldEndStream, + signal + }) + writeBodyH2() + } -const assert = __nccwpck_require__(2613) -const { URLSerializer } = __nccwpck_require__(4955) -const { isValidHeaderName } = __nccwpck_require__(1612) + // Increment counter as we have new streams open + ++session[kOpenStreams] -/** - * @see https://url.spec.whatwg.org/#concept-url-equals - * @param {URL} A - * @param {URL} B - * @param {boolean | undefined} excludeFragment - * @returns {boolean} - */ -function urlEquals (A, B, excludeFragment = false) { - const serializedA = URLSerializer(A, excludeFragment) + stream.once('response', headers => { + const { [HTTP2_HEADER_STATUS]: statusCode, ...realHeaders } = headers + request.onResponseStarted() - const serializedB = URLSerializer(B, excludeFragment) + // Due to the stream nature, it is possible we face a race condition + // where the stream has been assigned, but the request has been aborted + // the request remains in-flight and headers hasn't been received yet + // for those scenarios, best effort is to destroy the stream immediately + // as there's no value to keep it open. + if (request.aborted) { + const err = new RequestAbortedError() + util.errorRequest(client, request, err) + util.destroy(stream, err) + return + } - return serializedA === serializedB + if (request.onHeaders(Number(statusCode), parseH2Headers(realHeaders), stream.resume.bind(stream), '') === false) { + stream.pause() + } + + stream.on('data', (chunk) => { + if (request.onData(chunk) === false) { + stream.pause() + } + }) + }) + + stream.once('end', () => { + // When state is null, it means we haven't consumed body and the stream still do not have + // a state. + // Present specially when using pipeline or stream + if (stream.state?.state == null || stream.state.state < 6) { + request.onComplete([]) + } + + if (session[kOpenStreams] === 0) { + // Stream is closed or half-closed-remote (6), decrement counter and cleanup + // It does not have sense to continue working with the stream as we do not + // have yet RST_STREAM support on client-side + + session.unref() + } + + abort(new InformationalError('HTTP/2: stream half-closed (remote)')) + client[kQueue][client[kRunningIdx]++] = null + client[kPendingIdx] = client[kRunningIdx] + client[kResume]() + }) + + stream.once('close', () => { + session[kOpenStreams] -= 1 + if (session[kOpenStreams] === 0) { + session.unref() + } + }) + + stream.once('error', function (err) { + abort(err) + }) + + stream.once('frameError', (type, code) => { + abort(new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`)) + }) + + // stream.on('aborted', () => { + // // TODO(HTTP/2): Support aborted + // }) + + // stream.on('timeout', () => { + // // TODO(HTTP/2): Support timeout + // }) + + // stream.on('push', headers => { + // // TODO(HTTP/2): Support push + // }) + + // stream.on('trailers', headers => { + // // TODO(HTTP/2): Support trailers + // }) + + return true + + function writeBodyH2 () { + /* istanbul ignore else: assertion */ + if (!body || contentLength === 0) { + writeBuffer( + abort, + stream, + null, + client, + request, + client[kSocket], + contentLength, + expectsPayload + ) + } else if (util.isBuffer(body)) { + writeBuffer( + abort, + stream, + body, + client, + request, + client[kSocket], + contentLength, + expectsPayload + ) + } else if (util.isBlobLike(body)) { + if (typeof body.stream === 'function') { + writeIterable( + abort, + stream, + body.stream(), + client, + request, + client[kSocket], + contentLength, + expectsPayload + ) + } else { + writeBlob( + abort, + stream, + body, + client, + request, + client[kSocket], + contentLength, + expectsPayload + ) + } + } else if (util.isStream(body)) { + writeStream( + abort, + client[kSocket], + expectsPayload, + stream, + body, + client, + request, + contentLength + ) + } else if (util.isIterable(body)) { + writeIterable( + abort, + stream, + body, + client, + request, + client[kSocket], + contentLength, + expectsPayload + ) + } else { + assert(false) + } + } } -/** - * @see https://github.com/chromium/chromium/blob/694d20d134cb553d8d89e5500b9148012b1ba299/content/browser/cache_storage/cache_storage_cache.cc#L260-L262 - * @param {string} header - */ -function fieldValues (header) { - assert(header !== null) +function writeBuffer (abort, h2stream, body, client, request, socket, contentLength, expectsPayload) { + try { + if (body != null && util.isBuffer(body)) { + assert(contentLength === body.byteLength, 'buffer body must have content length') + h2stream.cork() + h2stream.write(body) + h2stream.uncork() + h2stream.end() - const values = [] + request.onBodySent(body) + } - for (let value of header.split(',')) { - value = value.trim() + if (!expectsPayload) { + socket[kReset] = true + } - if (!value.length) { - continue - } else if (!isValidHeaderName(value)) { - continue + request.onRequestSent() + client[kResume]() + } catch (error) { + abort(error) + } +} + +function writeStream (abort, socket, expectsPayload, h2stream, body, client, request, contentLength) { + assert(contentLength !== 0 || client[kRunning] === 0, 'stream body cannot be pipelined') + + // For HTTP/2, is enough to pipe the stream + const pipe = pipeline( + body, + h2stream, + (err) => { + if (err) { + util.destroy(pipe, err) + abort(err) + } else { + util.removeAllListeners(pipe) + request.onRequestSent() + + if (!expectsPayload) { + socket[kReset] = true + } + + client[kResume]() + } } + ) + + util.addListener(pipe, 'data', onPipeData) - values.push(value) + function onPipeData (chunk) { + request.onBodySent(chunk) } +} - return values +async function writeBlob (abort, h2stream, body, client, request, socket, contentLength, expectsPayload) { + assert(contentLength === body.size, 'blob body must have content length') + + try { + if (contentLength != null && contentLength !== body.size) { + throw new RequestContentLengthMismatchError() + } + + const buffer = Buffer.from(await body.arrayBuffer()) + + h2stream.cork() + h2stream.write(buffer) + h2stream.uncork() + h2stream.end() + + request.onBodySent(buffer) + request.onRequestSent() + + if (!expectsPayload) { + socket[kReset] = true + } + + client[kResume]() + } catch (err) { + abort(err) + } } -module.exports = { - urlEquals, - fieldValues +async function writeIterable (abort, h2stream, body, client, request, socket, contentLength, expectsPayload) { + assert(contentLength !== 0 || client[kRunning] === 0, 'iterator body cannot be pipelined') + + let callback = null + function onDrain () { + if (callback) { + const cb = callback + callback = null + cb() + } + } + + const waitForDrain = () => new Promise((resolve, reject) => { + assert(callback === null) + + if (socket[kError]) { + reject(socket[kError]) + } else { + callback = resolve + } + }) + + h2stream + .on('close', onDrain) + .on('drain', onDrain) + + try { + // It's up to the user to somehow abort the async iterable. + for await (const chunk of body) { + if (socket[kError]) { + throw socket[kError] + } + + const res = h2stream.write(chunk) + request.onBodySent(chunk) + if (!res) { + await waitForDrain() + } + } + + h2stream.end() + + request.onRequestSent() + + if (!expectsPayload) { + socket[kReset] = true + } + + client[kResume]() + } catch (err) { + abort(err) + } finally { + h2stream + .off('close', onDrain) + .off('drain', onDrain) + } } +module.exports = connectH2 + /***/ }), -/***/ 6466: +/***/ 9143: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; // @ts-check -/* global WebAssembly */ - -const assert = __nccwpck_require__(2613) -const net = __nccwpck_require__(9278) -const http = __nccwpck_require__(8611) -const { pipeline } = __nccwpck_require__(2203) -const util = __nccwpck_require__(5069) -const timers = __nccwpck_require__(1775) -const Request = __nccwpck_require__(2635) -const DispatcherBase = __nccwpck_require__(7172) +const assert = __nccwpck_require__(4589) +const net = __nccwpck_require__(7030) +const http = __nccwpck_require__(7067) +const util = __nccwpck_require__(7234) +const { channels } = __nccwpck_require__(7820) +const Request = __nccwpck_require__(4053) +const DispatcherBase = __nccwpck_require__(555) const { - RequestContentLengthMismatchError, - ResponseContentLengthMismatchError, InvalidArgumentError, - RequestAbortedError, - HeadersTimeoutError, - HeadersOverflowError, - SocketError, InformationalError, - BodyTimeoutError, - HTTPParserError, - ResponseExceededMaxSizeError, ClientDestroyedError -} = __nccwpck_require__(6738) -const buildConnector = __nccwpck_require__(9323) +} = __nccwpck_require__(329) +const buildConnector = __nccwpck_require__(3242) const { kUrl, - kReset, kServerName, kClient, kBusy, - kParser, kConnect, - kBlocking, kResuming, kRunning, kPending, kSize, - kWriting, kQueue, kConnected, kConnecting, kNeedDrain, - kNoRef, kKeepAliveDefaultTimeout, kHostHeader, kPendingIdx, kRunningIdx, kError, kPipelining, - kSocket, kKeepAliveTimeoutValue, kMaxHeadersSize, kKeepAliveMaxTimeout, @@ -26881,67 +23359,31 @@ const { kInterceptors, kLocalAddress, kMaxResponseSize, - kHTTPConnVersion, - // HTTP2 - kHost, - kHTTP2Session, - kHTTP2SessionState, - kHTTP2BuildRequest, - kHTTP2CopyHeaders, - kHTTP1BuildRequest -} = __nccwpck_require__(1028) - -/** @type {import('http2')} */ -let http2 -try { - http2 = __nccwpck_require__(5675) -} catch { - // @ts-ignore - http2 = { constants: {} } -} - -const { - constants: { - HTTP2_HEADER_AUTHORITY, - HTTP2_HEADER_METHOD, - HTTP2_HEADER_PATH, - HTTP2_HEADER_SCHEME, - HTTP2_HEADER_CONTENT_LENGTH, - HTTP2_HEADER_EXPECT, - HTTP2_HEADER_STATUS - } -} = http2 - -// Experimental -let h2ExperimentalWarned = false - -const FastBuffer = Buffer[Symbol.species] + kOnError, + kHTTPContext, + kMaxConcurrentStreams, + kResume +} = __nccwpck_require__(7417) +const connectH1 = __nccwpck_require__(6323) +const connectH2 = __nccwpck_require__(2854) +let deprecatedInterceptorWarned = false const kClosedResolve = Symbol('kClosedResolve') -const channels = {} +const noop = () => {} -try { - const diagnosticsChannel = __nccwpck_require__(1637) - channels.sendHeaders = diagnosticsChannel.channel('undici:client:sendHeaders') - channels.beforeConnect = diagnosticsChannel.channel('undici:client:beforeConnect') - channels.connectError = diagnosticsChannel.channel('undici:client:connectError') - channels.connected = diagnosticsChannel.channel('undici:client:connected') -} catch { - channels.sendHeaders = { hasSubscribers: false } - channels.beforeConnect = { hasSubscribers: false } - channels.connectError = { hasSubscribers: false } - channels.connected = { hasSubscribers: false } +function getPipelining (client) { + return client[kPipelining] ?? client[kHTTPContext]?.defaultPipelining ?? 1 } /** - * @type {import('../types/client').default} + * @type {import('../../types/client.js').default} */ class Client extends DispatcherBase { /** * * @param {string|URL} url - * @param {import('../types/client').Client.Options} options + * @param {import('../../types/client.js').Client.Options} options */ constructor (url, { interceptors, @@ -26970,8 +23412,8 @@ class Client extends DispatcherBase { autoSelectFamily, autoSelectFamilyAttemptTimeout, // h2 - allowH2, - maxConcurrentStreams + maxConcurrentStreams, + allowH2 } = {}) { super() @@ -27060,7 +23502,7 @@ class Client extends DispatcherBase { } if (maxConcurrentStreams != null && (typeof maxConcurrentStreams !== 'number' || maxConcurrentStreams < 1)) { - throw new InvalidArgumentError('maxConcurrentStreams must be a possitive integer, greater than 0') + throw new InvalidArgumentError('maxConcurrentStreams must be a positive integer, greater than 0') } if (typeof connect !== 'function') { @@ -27070,22 +23512,30 @@ class Client extends DispatcherBase { allowH2, socketPath, timeout: connectTimeout, - ...(util.nodeHasAutoSelectFamily && autoSelectFamily ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : undefined), + ...(autoSelectFamily ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : undefined), ...connect }) } - this[kInterceptors] = interceptors && interceptors.Client && Array.isArray(interceptors.Client) - ? interceptors.Client - : [createRedirectInterceptor({ maxRedirections })] + if (interceptors?.Client && Array.isArray(interceptors.Client)) { + this[kInterceptors] = interceptors.Client + if (!deprecatedInterceptorWarned) { + deprecatedInterceptorWarned = true + process.emitWarning('Client.Options#interceptor is deprecated. Use Dispatcher#compose instead.', { + code: 'UNDICI-CLIENT-INTERCEPTOR-DEPRECATED' + }) + } + } else { + this[kInterceptors] = [createRedirectInterceptor({ maxRedirections })] + } + this[kUrl] = util.parseOrigin(url) this[kConnector] = connect - this[kSocket] = null this[kPipelining] = pipelining != null ? pipelining : 1 this[kMaxHeadersSize] = maxHeaderSize || http.maxHeaderSize this[kKeepAliveDefaultTimeout] = keepAliveTimeout == null ? 4e3 : keepAliveTimeout this[kKeepAliveMaxTimeout] = keepAliveMaxTimeout == null ? 600e3 : keepAliveMaxTimeout - this[kKeepAliveTimeoutThreshold] = keepAliveTimeoutThreshold == null ? 1e3 : keepAliveTimeoutThreshold + this[kKeepAliveTimeoutThreshold] = keepAliveTimeoutThreshold == null ? 2e3 : keepAliveTimeoutThreshold this[kKeepAliveTimeoutValue] = this[kKeepAliveDefaultTimeout] this[kServerName] = null this[kLocalAddress] = localAddress != null ? localAddress : null @@ -27099,18 +23549,8 @@ class Client extends DispatcherBase { this[kMaxRequests] = maxRequestsPerClient this[kClosedResolve] = null this[kMaxResponseSize] = maxResponseSize > -1 ? maxResponseSize : -1 - this[kHTTPConnVersion] = 'h1' - - // HTTP/2 - this[kHTTP2Session] = null - this[kHTTP2SessionState] = !allowH2 - ? null - : { - // streams: null, // Fixed queue of streams - For future support of `push` - openStreams: 0, // Keep track of them to decide wether or not unref the session - maxConcurrentStreams: maxConcurrentStreams != null ? maxConcurrentStreams : 100 // Max peerConcurrentStreams for a Node h2 server - } - this[kHost] = `${this[kUrl].hostname}${this[kUrl].port ? `:${this[kUrl].port}` : ''}` + this[kMaxConcurrentStreams] = maxConcurrentStreams != null ? maxConcurrentStreams : 100 // Max peerConcurrentStreams for a Node h2 server + this[kHTTPContext] = null // kQueue is built up of 3 sections separated by // the kRunningIdx and kPendingIdx indices. @@ -27124,6 +23564,9 @@ class Client extends DispatcherBase { this[kQueue] = [] this[kRunningIdx] = 0 this[kPendingIdx] = 0 + + this[kResume] = (sync) => resume(this, sync) + this[kOnError] = (err) => onError(this, err) } get pipelining () { @@ -27132,7 +23575,7 @@ class Client extends DispatcherBase { set pipelining (value) { this[kPipelining] = value - resume(this, true) + this[kResume](true) } get [kPending] () { @@ -27148,14 +23591,13 @@ class Client extends DispatcherBase { } get [kConnected] () { - return !!this[kSocket] && !this[kConnecting] && !this[kSocket].destroyed + return !!this[kHTTPContext] && !this[kConnecting] && !this[kHTTPContext].destroyed } get [kBusy] () { - const socket = this[kSocket] - return ( - (socket && (socket[kReset] || socket[kWriting] || socket[kBlocking])) || - (this[kSize] >= (this[kPipelining] || 1)) || + return Boolean( + this[kHTTPContext]?.busy(null) || + (this[kSize] >= (getPipelining(this) || 1)) || this[kPending] > 0 ) } @@ -27168,10 +23610,7 @@ class Client extends DispatcherBase { [kDispatch] (opts, handler) { const origin = opts.origin || this[kUrl].origin - - const request = this[kHTTPConnVersion] === 'h2' - ? Request[kHTTP2BuildRequest](origin, opts, handler) - : Request[kHTTP1BuildRequest](origin, opts, handler) + const request = new Request(origin, opts, handler) this[kQueue].push(request) if (this[kResuming]) { @@ -27179,9 +23618,9 @@ class Client extends DispatcherBase { } else if (util.bodyLength(request.body) == null && util.isIterable(request.body)) { // Wait a tick in case stream/iterator is ended in the same tick. this[kResuming] = 1 - process.nextTick(resume, this) + queueMicrotask(() => resume(this)) } else { - resume(this, true) + this[kResume](true) } if (this[kResuming] && this[kNeedDrain] !== 2 && this[kBusy]) { @@ -27195,10 +23634,10 @@ class Client extends DispatcherBase { // TODO: for H2 we need to gracefully flush the remaining enqueued // request and close each stream. return new Promise((resolve) => { - if (!this[kSize]) { - resolve(null) - } else { + if (this[kSize]) { this[kClosedResolve] = resolve + } else { + resolve(null) } }) } @@ -27208,7 +23647,7 @@ class Client extends DispatcherBase { const requests = this[kQueue].splice(this[kPendingIdx]) for (let i = 0; i < requests.length; i++) { const request = requests[i] - errorRequest(this, request, err) + util.errorRequest(this, request, err) } const callback = () => { @@ -27217,62167 +23656,66495 @@ class Client extends DispatcherBase { this[kClosedResolve]() this[kClosedResolve] = null } - resolve() - } - - if (this[kHTTP2Session] != null) { - util.destroy(this[kHTTP2Session], err) - this[kHTTP2Session] = null - this[kHTTP2SessionState] = null + resolve(null) } - if (!this[kSocket]) { - queueMicrotask(callback) + if (this[kHTTPContext]) { + this[kHTTPContext].destroy(err, callback) + this[kHTTPContext] = null } else { - util.destroy(this[kSocket].on('close', callback), err) + queueMicrotask(callback) } - resume(this) + this[kResume]() }) } } -function onHttp2SessionError (err) { - assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID') +const createRedirectInterceptor = __nccwpck_require__(2642) - this[kSocket][kError] = err +function onError (client, err) { + if ( + client[kRunning] === 0 && + err.code !== 'UND_ERR_INFO' && + err.code !== 'UND_ERR_SOCKET' + ) { + // Error is not caused by running request and not a recoverable + // socket error. - onError(this[kClient], err) -} + assert(client[kPendingIdx] === client[kRunningIdx]) -function onHttp2FrameError (type, code, id) { - const err = new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`) + const requests = client[kQueue].splice(client[kRunningIdx]) - if (id === 0) { - this[kSocket][kError] = err - onError(this[kClient], err) + for (let i = 0; i < requests.length; i++) { + const request = requests[i] + util.errorRequest(client, request, err) + } + assert(client[kSize] === 0) } } -function onHttp2SessionEnd () { - util.destroy(this, new SocketError('other side closed')) - util.destroy(this[kSocket], new SocketError('other side closed')) -} +/** + * @param {Client} client + * @returns + */ +async function connect (client) { + assert(!client[kConnecting]) + assert(!client[kHTTPContext]) -function onHTTP2GoAway (code) { - const client = this[kClient] - const err = new InformationalError(`HTTP/2: "GOAWAY" frame received with code ${code}`) - client[kSocket] = null - client[kHTTP2Session] = null + let { host, hostname, protocol, port } = client[kUrl] - if (client.destroyed) { - assert(this[kPending] === 0) + // Resolve ipv6 + if (hostname[0] === '[') { + const idx = hostname.indexOf(']') - // Fail entire queue. - const requests = client[kQueue].splice(client[kRunningIdx]) - for (let i = 0; i < requests.length; i++) { - const request = requests[i] - errorRequest(this, request, err) - } - } else if (client[kRunning] > 0) { - // Fail head of pipeline. - const request = client[kQueue][client[kRunningIdx]] - client[kQueue][client[kRunningIdx]++] = null + assert(idx !== -1) + const ip = hostname.substring(1, idx) - errorRequest(client, request, err) + assert(net.isIP(ip)) + hostname = ip } - client[kPendingIdx] = client[kRunningIdx] + client[kConnecting] = true - assert(client[kRunning] === 0) + if (channels.beforeConnect.hasSubscribers) { + channels.beforeConnect.publish({ + connectParams: { + host, + hostname, + protocol, + port, + version: client[kHTTPContext]?.version, + servername: client[kServerName], + localAddress: client[kLocalAddress] + }, + connector: client[kConnector] + }) + } - client.emit('disconnect', - client[kUrl], - [client], - err - ) + try { + const socket = await new Promise((resolve, reject) => { + client[kConnector]({ + host, + hostname, + protocol, + port, + servername: client[kServerName], + localAddress: client[kLocalAddress] + }, (err, socket) => { + if (err) { + reject(err) + } else { + resolve(socket) + } + }) + }) - resume(client) -} + if (client.destroyed) { + util.destroy(socket.on('error', noop), new ClientDestroyedError()) + return + } -const constants = __nccwpck_require__(4319) -const createRedirectInterceptor = __nccwpck_require__(7646) -const EMPTY_BUF = Buffer.alloc(0) + assert(socket) -async function lazyllhttp () { - const llhttpWasmData = process.env.JEST_WORKER_ID ? __nccwpck_require__(9753) : undefined + try { + client[kHTTPContext] = socket.alpnProtocol === 'h2' + ? await connectH2(client, socket) + : await connectH1(client, socket) + } catch (err) { + socket.destroy().on('error', noop) + throw err + } - let mod - try { - mod = await WebAssembly.compile(Buffer.from(__nccwpck_require__(3387), 'base64')) - } catch (e) { - /* istanbul ignore next */ + client[kConnecting] = false - // We could check if the error was caused by the simd option not - // being enabled, but the occurring of this other error - // * https://github.com/emscripten-core/emscripten/issues/11495 - // got me to remove that check to avoid breaking Node 12. - mod = await WebAssembly.compile(Buffer.from(llhttpWasmData || __nccwpck_require__(9753), 'base64')) - } + socket[kCounter] = 0 + socket[kMaxRequests] = client[kMaxRequests] + socket[kClient] = client + socket[kError] = null - return await WebAssembly.instantiate(mod, { - env: { - /* eslint-disable camelcase */ + if (channels.connected.hasSubscribers) { + channels.connected.publish({ + connectParams: { + host, + hostname, + protocol, + port, + version: client[kHTTPContext]?.version, + servername: client[kServerName], + localAddress: client[kLocalAddress] + }, + connector: client[kConnector], + socket + }) + } + client.emit('connect', client[kUrl], [client]) + } catch (err) { + if (client.destroyed) { + return + } - wasm_on_url: (p, at, len) => { - /* istanbul ignore next */ - return 0 - }, - wasm_on_status: (p, at, len) => { - assert.strictEqual(currentParser.ptr, p) - const start = at - currentBufferPtr + currentBufferRef.byteOffset - return currentParser.onStatus(new FastBuffer(currentBufferRef.buffer, start, len)) || 0 - }, - wasm_on_message_begin: (p) => { - assert.strictEqual(currentParser.ptr, p) - return currentParser.onMessageBegin() || 0 - }, - wasm_on_header_field: (p, at, len) => { - assert.strictEqual(currentParser.ptr, p) - const start = at - currentBufferPtr + currentBufferRef.byteOffset - return currentParser.onHeaderField(new FastBuffer(currentBufferRef.buffer, start, len)) || 0 - }, - wasm_on_header_value: (p, at, len) => { - assert.strictEqual(currentParser.ptr, p) - const start = at - currentBufferPtr + currentBufferRef.byteOffset - return currentParser.onHeaderValue(new FastBuffer(currentBufferRef.buffer, start, len)) || 0 - }, - wasm_on_headers_complete: (p, statusCode, upgrade, shouldKeepAlive) => { - assert.strictEqual(currentParser.ptr, p) - return currentParser.onHeadersComplete(statusCode, Boolean(upgrade), Boolean(shouldKeepAlive)) || 0 - }, - wasm_on_body: (p, at, len) => { - assert.strictEqual(currentParser.ptr, p) - const start = at - currentBufferPtr + currentBufferRef.byteOffset - return currentParser.onBody(new FastBuffer(currentBufferRef.buffer, start, len)) || 0 - }, - wasm_on_message_complete: (p) => { - assert.strictEqual(currentParser.ptr, p) - return currentParser.onMessageComplete() || 0 - } + client[kConnecting] = false - /* eslint-enable camelcase */ + if (channels.connectError.hasSubscribers) { + channels.connectError.publish({ + connectParams: { + host, + hostname, + protocol, + port, + version: client[kHTTPContext]?.version, + servername: client[kServerName], + localAddress: client[kLocalAddress] + }, + connector: client[kConnector], + error: err + }) } - }) -} -let llhttpInstance = null -let llhttpPromise = lazyllhttp() -llhttpPromise.catch() + if (err.code === 'ERR_TLS_CERT_ALTNAME_INVALID') { + assert(client[kRunning] === 0) + while (client[kPending] > 0 && client[kQueue][client[kPendingIdx]].servername === client[kServerName]) { + const request = client[kQueue][client[kPendingIdx]++] + util.errorRequest(client, request, err) + } + } else { + onError(client, err) + } -let currentParser = null -let currentBufferRef = null -let currentBufferSize = 0 -let currentBufferPtr = null + client.emit('connectionError', client[kUrl], [client], err) + } -const TIMEOUT_HEADERS = 1 -const TIMEOUT_BODY = 2 -const TIMEOUT_IDLE = 3 + client[kResume]() +} -class Parser { - constructor (client, socket, { exports }) { - assert(Number.isFinite(client[kMaxHeadersSize]) && client[kMaxHeadersSize] > 0) +function emitDrain (client) { + client[kNeedDrain] = 0 + client.emit('drain', client[kUrl], [client]) +} - this.llhttp = exports - this.ptr = this.llhttp.llhttp_alloc(constants.TYPE.RESPONSE) - this.client = client - this.socket = socket - this.timeout = null - this.timeoutValue = null - this.timeoutType = null - this.statusCode = null - this.statusText = '' - this.upgrade = false - this.headers = [] - this.headersSize = 0 - this.headersMaxSize = client[kMaxHeadersSize] - this.shouldKeepAlive = false - this.paused = false - this.resume = this.resume.bind(this) +function resume (client, sync) { + if (client[kResuming] === 2) { + return + } - this.bytesRead = 0 + client[kResuming] = 2 - this.keepAlive = '' - this.contentLength = '' - this.connection = '' - this.maxResponseSize = client[kMaxResponseSize] + _resume(client, sync) + client[kResuming] = 0 + + if (client[kRunningIdx] > 256) { + client[kQueue].splice(0, client[kRunningIdx]) + client[kPendingIdx] -= client[kRunningIdx] + client[kRunningIdx] = 0 } +} - setTimeout (value, type) { - this.timeoutType = type - if (value !== this.timeoutValue) { - timers.clearTimeout(this.timeout) - if (value) { - this.timeout = timers.setTimeout(onParserTimeout, value, this) - // istanbul ignore else: only for jest - if (this.timeout.unref) { - this.timeout.unref() - } +function _resume (client, sync) { + while (true) { + if (client.destroyed) { + assert(client[kPending] === 0) + return + } + + if (client[kClosedResolve] && !client[kSize]) { + client[kClosedResolve]() + client[kClosedResolve] = null + return + } + + if (client[kHTTPContext]) { + client[kHTTPContext].resume() + } + + if (client[kBusy]) { + client[kNeedDrain] = 2 + } else if (client[kNeedDrain] === 2) { + if (sync) { + client[kNeedDrain] = 1 + queueMicrotask(() => emitDrain(client)) } else { - this.timeout = null - } - this.timeoutValue = value - } else if (this.timeout) { - // istanbul ignore else: only for jest - if (this.timeout.refresh) { - this.timeout.refresh() + emitDrain(client) } + continue } - } - resume () { - if (this.socket.destroyed || !this.paused) { + if (client[kPending] === 0) { return } - assert(this.ptr != null) - assert(currentParser == null) + if (client[kRunning] >= (getPipelining(client) || 1)) { + return + } - this.llhttp.llhttp_resume(this.ptr) + const request = client[kQueue][client[kPendingIdx]] - assert(this.timeoutType === TIMEOUT_BODY) - if (this.timeout) { - // istanbul ignore else: only for jest - if (this.timeout.refresh) { - this.timeout.refresh() + if (client[kUrl].protocol === 'https:' && client[kServerName] !== request.servername) { + if (client[kRunning] > 0) { + return } + + client[kServerName] = request.servername + client[kHTTPContext]?.destroy(new InformationalError('servername changed'), () => { + client[kHTTPContext] = null + resume(client) + }) } - this.paused = false - this.execute(this.socket.read() || EMPTY_BUF) // Flush parser. - this.readMore() - } + if (client[kConnecting]) { + return + } - readMore () { - while (!this.paused && this.ptr) { - const chunk = this.socket.read() - if (chunk === null) { - break - } - this.execute(chunk) + if (!client[kHTTPContext]) { + connect(client) + return } - } - execute (data) { - assert(this.ptr != null) - assert(currentParser == null) - assert(!this.paused) + if (client[kHTTPContext].destroyed) { + return + } - const { socket, llhttp } = this + if (client[kHTTPContext].busy(request)) { + return + } - if (data.length > currentBufferSize) { - if (currentBufferPtr) { - llhttp.free(currentBufferPtr) - } - currentBufferSize = Math.ceil(data.length / 4096) * 4096 - currentBufferPtr = llhttp.malloc(currentBufferSize) + if (!request.aborted && client[kHTTPContext].write(request)) { + client[kPendingIdx]++ + } else { + client[kQueue].splice(client[kPendingIdx], 1) } + } +} - new Uint8Array(llhttp.memory.buffer, currentBufferPtr, currentBufferSize).set(data) +module.exports = Client - // Call `execute` on the wasm parser. - // We pass the `llhttp_parser` pointer address, the pointer address of buffer view data, - // and finally the length of bytes to parse. - // The return value is an error code or `constants.ERROR.OK`. - try { - let ret - try { - currentBufferRef = data - currentParser = this - ret = llhttp.llhttp_execute(this.ptr, currentBufferPtr, data.length) - /* eslint-disable-next-line no-useless-catch */ - } catch (err) { - /* istanbul ignore next: difficult to make a test case for */ - throw err - } finally { - currentParser = null - currentBufferRef = null - } +/***/ }), - const offset = llhttp.llhttp_get_error_pos(this.ptr) - currentBufferPtr +/***/ 555: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - if (ret === constants.ERROR.PAUSED_UPGRADE) { - this.onUpgrade(data.slice(offset)) - } else if (ret === constants.ERROR.PAUSED) { - this.paused = true - socket.unshift(data.slice(offset)) - } else if (ret !== constants.ERROR.OK) { - const ptr = llhttp.llhttp_get_error_reason(this.ptr) - let message = '' - /* istanbul ignore else: difficult to make a test case for */ - if (ptr) { - const len = new Uint8Array(llhttp.memory.buffer, ptr).indexOf(0) - message = - 'Response does not match the HTTP/1.1 protocol (' + - Buffer.from(llhttp.memory.buffer, ptr, len).toString() + - ')' - } - throw new HTTPParserError(message, constants.ERROR[ret], data.slice(offset)) - } - } catch (err) { - util.destroy(socket, err) - } - } - destroy () { - assert(this.ptr != null) - assert(currentParser == null) - this.llhttp.llhttp_free(this.ptr) - this.ptr = null +const Dispatcher = __nccwpck_require__(5137) +const { + ClientDestroyedError, + ClientClosedError, + InvalidArgumentError +} = __nccwpck_require__(329) +const { kDestroy, kClose, kClosed, kDestroyed, kDispatch, kInterceptors } = __nccwpck_require__(7417) - timers.clearTimeout(this.timeout) - this.timeout = null - this.timeoutValue = null - this.timeoutType = null +const kOnDestroyed = Symbol('onDestroyed') +const kOnClosed = Symbol('onClosed') +const kInterceptedDispatch = Symbol('Intercepted Dispatch') - this.paused = false - } +class DispatcherBase extends Dispatcher { + constructor () { + super() - onStatus (buf) { - this.statusText = buf.toString() + this[kDestroyed] = false + this[kOnDestroyed] = null + this[kClosed] = false + this[kOnClosed] = [] } - onMessageBegin () { - const { socket, client } = this - - /* istanbul ignore next: difficult to make a test case for */ - if (socket.destroyed) { - return -1 - } + get destroyed () { + return this[kDestroyed] + } - const request = client[kQueue][client[kRunningIdx]] - if (!request) { - return -1 - } + get closed () { + return this[kClosed] } - onHeaderField (buf) { - const len = this.headers.length + get interceptors () { + return this[kInterceptors] + } - if ((len & 1) === 0) { - this.headers.push(buf) - } else { - this.headers[len - 1] = Buffer.concat([this.headers[len - 1], buf]) + set interceptors (newInterceptors) { + if (newInterceptors) { + for (let i = newInterceptors.length - 1; i >= 0; i--) { + const interceptor = this[kInterceptors][i] + if (typeof interceptor !== 'function') { + throw new InvalidArgumentError('interceptor must be an function') + } + } } - this.trackHeader(buf.length) + this[kInterceptors] = newInterceptors } - onHeaderValue (buf) { - let len = this.headers.length - - if ((len & 1) === 1) { - this.headers.push(buf) - len += 1 - } else { - this.headers[len - 1] = Buffer.concat([this.headers[len - 1], buf]) + close (callback) { + if (callback === undefined) { + return new Promise((resolve, reject) => { + this.close((err, data) => { + return err ? reject(err) : resolve(data) + }) + }) } - const key = this.headers[len - 2] - if (key.length === 10 && key.toString().toLowerCase() === 'keep-alive') { - this.keepAlive += buf.toString() - } else if (key.length === 10 && key.toString().toLowerCase() === 'connection') { - this.connection += buf.toString() - } else if (key.length === 14 && key.toString().toLowerCase() === 'content-length') { - this.contentLength += buf.toString() + if (typeof callback !== 'function') { + throw new InvalidArgumentError('invalid callback') } - this.trackHeader(buf.length) - } - - trackHeader (len) { - this.headersSize += len - if (this.headersSize >= this.headersMaxSize) { - util.destroy(this.socket, new HeadersOverflowError()) + if (this[kDestroyed]) { + queueMicrotask(() => callback(new ClientDestroyedError(), null)) + return } - } - onUpgrade (head) { - const { upgrade, client, socket, headers, statusCode } = this + if (this[kClosed]) { + if (this[kOnClosed]) { + this[kOnClosed].push(callback) + } else { + queueMicrotask(() => callback(null, null)) + } + return + } - assert(upgrade) + this[kClosed] = true + this[kOnClosed].push(callback) - const request = client[kQueue][client[kRunningIdx]] - assert(request) + const onClosed = () => { + const callbacks = this[kOnClosed] + this[kOnClosed] = null + for (let i = 0; i < callbacks.length; i++) { + callbacks[i](null, null) + } + } - assert(!socket.destroyed) - assert(socket === client[kSocket]) - assert(!this.paused) - assert(request.upgrade || request.method === 'CONNECT') + // Should not error. + this[kClose]() + .then(() => this.destroy()) + .then(() => { + queueMicrotask(onClosed) + }) + } - this.statusCode = null - this.statusText = '' - this.shouldKeepAlive = null + destroy (err, callback) { + if (typeof err === 'function') { + callback = err + err = null + } - assert(this.headers.length % 2 === 0) - this.headers = [] - this.headersSize = 0 + if (callback === undefined) { + return new Promise((resolve, reject) => { + this.destroy(err, (err, data) => { + return err ? /* istanbul ignore next: should never error */ reject(err) : resolve(data) + }) + }) + } - socket.unshift(head) + if (typeof callback !== 'function') { + throw new InvalidArgumentError('invalid callback') + } - socket[kParser].destroy() - socket[kParser] = null + if (this[kDestroyed]) { + if (this[kOnDestroyed]) { + this[kOnDestroyed].push(callback) + } else { + queueMicrotask(() => callback(null, null)) + } + return + } - socket[kClient] = null - socket[kError] = null - socket - .removeListener('error', onSocketError) - .removeListener('readable', onSocketReadable) - .removeListener('end', onSocketEnd) - .removeListener('close', onSocketClose) + if (!err) { + err = new ClientDestroyedError() + } - client[kSocket] = null - client[kQueue][client[kRunningIdx]++] = null - client.emit('disconnect', client[kUrl], [client], new InformationalError('upgrade')) + this[kDestroyed] = true + this[kOnDestroyed] = this[kOnDestroyed] || [] + this[kOnDestroyed].push(callback) - try { - request.onUpgrade(statusCode, headers, socket) - } catch (err) { - util.destroy(socket, err) + const onDestroyed = () => { + const callbacks = this[kOnDestroyed] + this[kOnDestroyed] = null + for (let i = 0; i < callbacks.length; i++) { + callbacks[i](null, null) + } } - resume(client) + // Should not error. + this[kDestroy](err).then(() => { + queueMicrotask(onDestroyed) + }) } - onHeadersComplete (statusCode, upgrade, shouldKeepAlive) { - const { client, socket, headers, statusText } = this - - /* istanbul ignore next: difficult to make a test case for */ - if (socket.destroyed) { - return -1 + [kInterceptedDispatch] (opts, handler) { + if (!this[kInterceptors] || this[kInterceptors].length === 0) { + this[kInterceptedDispatch] = this[kDispatch] + return this[kDispatch](opts, handler) } - const request = client[kQueue][client[kRunningIdx]] - - /* istanbul ignore next: difficult to make a test case for */ - if (!request) { - return -1 + let dispatch = this[kDispatch].bind(this) + for (let i = this[kInterceptors].length - 1; i >= 0; i--) { + dispatch = this[kInterceptors][i](dispatch) } + this[kInterceptedDispatch] = dispatch + return dispatch(opts, handler) + } - assert(!this.upgrade) - assert(this.statusCode < 200) - - if (statusCode === 100) { - util.destroy(socket, new SocketError('bad response', util.getSocketInfo(socket))) - return -1 + dispatch (opts, handler) { + if (!handler || typeof handler !== 'object') { + throw new InvalidArgumentError('handler must be an object') } - /* this can only happen if server is misbehaving */ - if (upgrade && !request.upgrade) { - util.destroy(socket, new SocketError('bad upgrade', util.getSocketInfo(socket))) - return -1 - } + try { + if (!opts || typeof opts !== 'object') { + throw new InvalidArgumentError('opts must be an object.') + } - assert.strictEqual(this.timeoutType, TIMEOUT_HEADERS) + if (this[kDestroyed] || this[kOnDestroyed]) { + throw new ClientDestroyedError() + } - this.statusCode = statusCode - this.shouldKeepAlive = ( - shouldKeepAlive || - // Override llhttp value which does not allow keepAlive for HEAD. - (request.method === 'HEAD' && !socket[kReset] && this.connection.toLowerCase() === 'keep-alive') - ) + if (this[kClosed]) { + throw new ClientClosedError() + } - if (this.statusCode >= 200) { - const bodyTimeout = request.bodyTimeout != null - ? request.bodyTimeout - : client[kBodyTimeout] - this.setTimeout(bodyTimeout, TIMEOUT_BODY) - } else if (this.timeout) { - // istanbul ignore else: only for jest - if (this.timeout.refresh) { - this.timeout.refresh() + return this[kInterceptedDispatch](opts, handler) + } catch (err) { + if (typeof handler.onError !== 'function') { + throw new InvalidArgumentError('invalid onError method') } - } - if (request.method === 'CONNECT') { - assert(client[kRunning] === 1) - this.upgrade = true - return 2 - } + handler.onError(err) - if (upgrade) { - assert(client[kRunning] === 1) - this.upgrade = true - return 2 + return false } + } +} - assert(this.headers.length % 2 === 0) - this.headers = [] - this.headersSize = 0 +module.exports = DispatcherBase - if (this.shouldKeepAlive && client[kPipelining]) { - const keepAliveTimeout = this.keepAlive ? util.parseKeepAliveTimeout(this.keepAlive) : null - if (keepAliveTimeout != null) { - const timeout = Math.min( - keepAliveTimeout - client[kKeepAliveTimeoutThreshold], - client[kKeepAliveMaxTimeout] - ) - if (timeout <= 0) { - socket[kReset] = true - } else { - client[kKeepAliveTimeoutValue] = timeout - } - } else { - client[kKeepAliveTimeoutValue] = client[kKeepAliveDefaultTimeout] - } - } else { - // Stop more requests from being dispatched. - socket[kReset] = true - } +/***/ }), - const pause = request.onHeaders(statusCode, headers, this.resume, statusText) === false +/***/ 5137: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - if (request.aborted) { - return -1 - } - if (request.method === 'HEAD') { - return 1 - } +const EventEmitter = __nccwpck_require__(8474) - if (statusCode < 200) { - return 1 - } +class Dispatcher extends EventEmitter { + dispatch () { + throw new Error('not implemented') + } - if (socket[kBlocking]) { - socket[kBlocking] = false - resume(client) - } + close () { + throw new Error('not implemented') + } - return pause ? constants.ERROR.PAUSED : 0 + destroy () { + throw new Error('not implemented') } - onBody (buf) { - const { client, socket, statusCode, maxResponseSize } = this + compose (...args) { + // So we handle [interceptor1, interceptor2] or interceptor1, interceptor2, ... + const interceptors = Array.isArray(args[0]) ? args[0] : args + let dispatch = this.dispatch.bind(this) - if (socket.destroyed) { - return -1 - } + for (const interceptor of interceptors) { + if (interceptor == null) { + continue + } - const request = client[kQueue][client[kRunningIdx]] - assert(request) + if (typeof interceptor !== 'function') { + throw new TypeError(`invalid interceptor, expected function received ${typeof interceptor}`) + } - assert.strictEqual(this.timeoutType, TIMEOUT_BODY) - if (this.timeout) { - // istanbul ignore else: only for jest - if (this.timeout.refresh) { - this.timeout.refresh() + dispatch = interceptor(dispatch) + + if (dispatch == null || typeof dispatch !== 'function' || dispatch.length !== 2) { + throw new TypeError('invalid interceptor') } } - assert(statusCode >= 200) + return new ComposedDispatcher(this, dispatch) + } +} - if (maxResponseSize > -1 && this.bytesRead + buf.length > maxResponseSize) { - util.destroy(socket, new ResponseExceededMaxSizeError()) - return -1 - } +class ComposedDispatcher extends Dispatcher { + #dispatcher = null + #dispatch = null - this.bytesRead += buf.length + constructor (dispatcher, dispatch) { + super() + this.#dispatcher = dispatcher + this.#dispatch = dispatch + } - if (request.onData(buf) === false) { - return constants.ERROR.PAUSED - } + dispatch (...args) { + this.#dispatch(...args) } - onMessageComplete () { - const { client, socket, statusCode, upgrade, headers, contentLength, bytesRead, shouldKeepAlive } = this + close (...args) { + return this.#dispatcher.close(...args) + } - if (socket.destroyed && (!statusCode || shouldKeepAlive)) { - return -1 - } + destroy (...args) { + return this.#dispatcher.destroy(...args) + } +} - if (upgrade) { - return - } +module.exports = Dispatcher - const request = client[kQueue][client[kRunningIdx]] - assert(request) - assert(statusCode >= 100) +/***/ }), - this.statusCode = null - this.statusText = '' - this.bytesRead = 0 - this.contentLength = '' - this.keepAlive = '' - this.connection = '' +/***/ 8019: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - assert(this.headers.length % 2 === 0) - this.headers = [] - this.headersSize = 0 - if (statusCode < 200) { - return - } - /* istanbul ignore next: should be handled by llhttp? */ - if (request.method !== 'HEAD' && contentLength && bytesRead !== parseInt(contentLength, 10)) { - util.destroy(socket, new ResponseContentLengthMismatchError()) - return -1 - } +const DispatcherBase = __nccwpck_require__(555) +const { kClose, kDestroy, kClosed, kDestroyed, kDispatch, kNoProxyAgent, kHttpProxyAgent, kHttpsProxyAgent } = __nccwpck_require__(7417) +const ProxyAgent = __nccwpck_require__(6614) +const Agent = __nccwpck_require__(4779) - request.onComplete(headers) +const DEFAULT_PORTS = { + 'http:': 80, + 'https:': 443 +} - client[kQueue][client[kRunningIdx]++] = null +let experimentalWarned = false - if (socket[kWriting]) { - assert.strictEqual(client[kRunning], 0) - // Response completed before request. - util.destroy(socket, new InformationalError('reset')) - return constants.ERROR.PAUSED - } else if (!shouldKeepAlive) { - util.destroy(socket, new InformationalError('reset')) - return constants.ERROR.PAUSED - } else if (socket[kReset] && client[kRunning] === 0) { - // Destroy socket once all requests have completed. - // The request at the tail of the pipeline is the one - // that requested reset and no further requests should - // have been queued since then. - util.destroy(socket, new InformationalError('reset')) - return constants.ERROR.PAUSED - } else if (client[kPipelining] === 1) { - // We must wait a full event loop cycle to reuse this socket to make sure - // that non-spec compliant servers are not closing the connection even if they - // said they won't. - setImmediate(resume, client) - } else { - resume(client) - } - } -} +class EnvHttpProxyAgent extends DispatcherBase { + #noProxyValue = null + #noProxyEntries = null + #opts = null -function onParserTimeout (parser) { - const { socket, timeoutType, client } = parser + constructor (opts = {}) { + super() + this.#opts = opts - /* istanbul ignore else */ - if (timeoutType === TIMEOUT_HEADERS) { - if (!socket[kWriting] || socket.writableNeedDrain || client[kRunning] > 1) { - assert(!parser.paused, 'cannot be paused while waiting for headers') - util.destroy(socket, new HeadersTimeoutError()) - } - } else if (timeoutType === TIMEOUT_BODY) { - if (!parser.paused) { - util.destroy(socket, new BodyTimeoutError()) + if (!experimentalWarned) { + experimentalWarned = true + process.emitWarning('EnvHttpProxyAgent is experimental, expect them to change at any time.', { + code: 'UNDICI-EHPA' + }) } - } else if (timeoutType === TIMEOUT_IDLE) { - assert(client[kRunning] === 0 && client[kKeepAliveTimeoutValue]) - util.destroy(socket, new InformationalError('socket idle timeout')) - } -} - -function onSocketReadable () { - const { [kParser]: parser } = this - if (parser) { - parser.readMore() - } -} -function onSocketError (err) { - const { [kClient]: client, [kParser]: parser } = this + const { httpProxy, httpsProxy, noProxy, ...agentOpts } = opts - assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID') + this[kNoProxyAgent] = new Agent(agentOpts) - if (client[kHTTPConnVersion] !== 'h2') { - // On Mac OS, we get an ECONNRESET even if there is a full body to be forwarded - // to the user. - if (err.code === 'ECONNRESET' && parser.statusCode && !parser.shouldKeepAlive) { - // We treat all incoming data so for as a valid response. - parser.onMessageComplete() - return + const HTTP_PROXY = httpProxy ?? process.env.http_proxy ?? process.env.HTTP_PROXY + if (HTTP_PROXY) { + this[kHttpProxyAgent] = new ProxyAgent({ ...agentOpts, uri: HTTP_PROXY }) + } else { + this[kHttpProxyAgent] = this[kNoProxyAgent] } - } - this[kError] = err + const HTTPS_PROXY = httpsProxy ?? process.env.https_proxy ?? process.env.HTTPS_PROXY + if (HTTPS_PROXY) { + this[kHttpsProxyAgent] = new ProxyAgent({ ...agentOpts, uri: HTTPS_PROXY }) + } else { + this[kHttpsProxyAgent] = this[kHttpProxyAgent] + } - onError(this[kClient], err) -} + this.#parseNoProxy() + } -function onError (client, err) { - if ( - client[kRunning] === 0 && - err.code !== 'UND_ERR_INFO' && - err.code !== 'UND_ERR_SOCKET' - ) { - // Error is not caused by running request and not a recoverable - // socket error. + [kDispatch] (opts, handler) { + const url = new URL(opts.origin) + const agent = this.#getProxyAgentForUrl(url) + return agent.dispatch(opts, handler) + } - assert(client[kPendingIdx] === client[kRunningIdx]) + async [kClose] () { + await this[kNoProxyAgent].close() + if (!this[kHttpProxyAgent][kClosed]) { + await this[kHttpProxyAgent].close() + } + if (!this[kHttpsProxyAgent][kClosed]) { + await this[kHttpsProxyAgent].close() + } + } - const requests = client[kQueue].splice(client[kRunningIdx]) - for (let i = 0; i < requests.length; i++) { - const request = requests[i] - errorRequest(client, request, err) + async [kDestroy] (err) { + await this[kNoProxyAgent].destroy(err) + if (!this[kHttpProxyAgent][kDestroyed]) { + await this[kHttpProxyAgent].destroy(err) + } + if (!this[kHttpsProxyAgent][kDestroyed]) { + await this[kHttpsProxyAgent].destroy(err) } - assert(client[kSize] === 0) } -} -function onSocketEnd () { - const { [kParser]: parser, [kClient]: client } = this + #getProxyAgentForUrl (url) { + let { protocol, host: hostname, port } = url - if (client[kHTTPConnVersion] !== 'h2') { - if (parser.statusCode && !parser.shouldKeepAlive) { - // We treat all incoming data so far as a valid response. - parser.onMessageComplete() - return + // Stripping ports in this way instead of using parsedUrl.hostname to make + // sure that the brackets around IPv6 addresses are kept. + hostname = hostname.replace(/:\d*$/, '').toLowerCase() + port = Number.parseInt(port, 10) || DEFAULT_PORTS[protocol] || 0 + if (!this.#shouldProxy(hostname, port)) { + return this[kNoProxyAgent] + } + if (protocol === 'https:') { + return this[kHttpsProxyAgent] } + return this[kHttpProxyAgent] } - util.destroy(this, new SocketError('other side closed', util.getSocketInfo(this))) -} + #shouldProxy (hostname, port) { + if (this.#noProxyChanged) { + this.#parseNoProxy() + } -function onSocketClose () { - const { [kClient]: client, [kParser]: parser } = this + if (this.#noProxyEntries.length === 0) { + return true // Always proxy if NO_PROXY is not set or empty. + } + if (this.#noProxyValue === '*') { + return false // Never proxy if wildcard is set. + } - if (client[kHTTPConnVersion] === 'h1' && parser) { - if (!this[kError] && parser.statusCode && !parser.shouldKeepAlive) { - // We treat all incoming data so far as a valid response. - parser.onMessageComplete() + for (let i = 0; i < this.#noProxyEntries.length; i++) { + const entry = this.#noProxyEntries[i] + if (entry.port && entry.port !== port) { + continue // Skip if ports don't match. + } + if (!/^[.*]/.test(entry.hostname)) { + // No wildcards, so don't proxy only if there is not an exact match. + if (hostname === entry.hostname) { + return false + } + } else { + // Don't proxy if the hostname ends with the no_proxy host. + if (hostname.endsWith(entry.hostname.replace(/^\*/, ''))) { + return false + } + } } - this[kParser].destroy() - this[kParser] = null + return true } - const err = this[kError] || new SocketError('closed', util.getSocketInfo(this)) + #parseNoProxy () { + const noProxyValue = this.#opts.noProxy ?? this.#noProxyEnv + const noProxySplit = noProxyValue.split(/[,\s]/) + const noProxyEntries = [] - client[kSocket] = null + for (let i = 0; i < noProxySplit.length; i++) { + const entry = noProxySplit[i] + if (!entry) { + continue + } + const parsed = entry.match(/^(.+):(\d+)$/) + noProxyEntries.push({ + hostname: (parsed ? parsed[1] : entry).toLowerCase(), + port: parsed ? Number.parseInt(parsed[2], 10) : 0 + }) + } - if (client.destroyed) { - assert(client[kPending] === 0) + this.#noProxyValue = noProxyValue + this.#noProxyEntries = noProxyEntries + } - // Fail entire queue. - const requests = client[kQueue].splice(client[kRunningIdx]) - for (let i = 0; i < requests.length; i++) { - const request = requests[i] - errorRequest(client, request, err) + get #noProxyChanged () { + if (this.#opts.noProxy !== undefined) { + return false } - } else if (client[kRunning] > 0 && err.code !== 'UND_ERR_INFO') { - // Fail head of pipeline. - const request = client[kQueue][client[kRunningIdx]] - client[kQueue][client[kRunningIdx]++] = null + return this.#noProxyValue !== this.#noProxyEnv + } - errorRequest(client, request, err) + get #noProxyEnv () { + return process.env.no_proxy ?? process.env.NO_PROXY ?? '' } +} - client[kPendingIdx] = client[kRunningIdx] +module.exports = EnvHttpProxyAgent - assert(client[kRunning] === 0) - client.emit('disconnect', client[kUrl], [client], err) +/***/ }), - resume(client) -} +/***/ 3830: +/***/ ((module) => { -async function connect (client) { - assert(!client[kConnecting]) - assert(!client[kSocket]) +/* eslint-disable */ - let { host, hostname, protocol, port } = client[kUrl] - // Resolve ipv6 - if (hostname[0] === '[') { - const idx = hostname.indexOf(']') - assert(idx !== -1) - const ip = hostname.substring(1, idx) +// Extracted from node/lib/internal/fixed_queue.js - assert(net.isIP(ip)) - hostname = ip - } +// Currently optimal queue size, tested on V8 6.0 - 6.6. Must be power of two. +const kSize = 2048; +const kMask = kSize - 1; - client[kConnecting] = true +// The FixedQueue is implemented as a singly-linked list of fixed-size +// circular buffers. It looks something like this: +// +// head tail +// | | +// v v +// +-----------+ <-----\ +-----------+ <------\ +-----------+ +// | [null] | \----- | next | \------- | next | +// +-----------+ +-----------+ +-----------+ +// | item | <-- bottom | item | <-- bottom | [empty] | +// | item | | item | | [empty] | +// | item | | item | | [empty] | +// | item | | item | | [empty] | +// | item | | item | bottom --> | item | +// | item | | item | | item | +// | ... | | ... | | ... | +// | item | | item | | item | +// | item | | item | | item | +// | [empty] | <-- top | item | | item | +// | [empty] | | item | | item | +// | [empty] | | [empty] | <-- top top --> | [empty] | +// +-----------+ +-----------+ +-----------+ +// +// Or, if there is only one circular buffer, it looks something +// like either of these: +// +// head tail head tail +// | | | | +// v v v v +// +-----------+ +-----------+ +// | [null] | | [null] | +// +-----------+ +-----------+ +// | [empty] | | item | +// | [empty] | | item | +// | item | <-- bottom top --> | [empty] | +// | item | | [empty] | +// | [empty] | <-- top bottom --> | item | +// | [empty] | | item | +// +-----------+ +-----------+ +// +// Adding a value means moving `top` forward by one, removing means +// moving `bottom` forward by one. After reaching the end, the queue +// wraps around. +// +// When `top === bottom` the current queue is empty and when +// `top + 1 === bottom` it's full. This wastes a single space of storage +// but allows much quicker checks. - if (channels.beforeConnect.hasSubscribers) { - channels.beforeConnect.publish({ - connectParams: { - host, - hostname, - protocol, - port, - servername: client[kServerName], - localAddress: client[kLocalAddress] - }, - connector: client[kConnector] - }) +class FixedCircularBuffer { + constructor() { + this.bottom = 0; + this.top = 0; + this.list = new Array(kSize); + this.next = null; } - try { - const socket = await new Promise((resolve, reject) => { - client[kConnector]({ - host, - hostname, - protocol, - port, - servername: client[kServerName], - localAddress: client[kLocalAddress] - }, (err, socket) => { - if (err) { - reject(err) - } else { - resolve(socket) - } - }) - }) - - if (client.destroyed) { - util.destroy(socket.on('error', () => {}), new ClientDestroyedError()) - return - } - - client[kConnecting] = false + isEmpty() { + return this.top === this.bottom; + } - assert(socket) + isFull() { + return ((this.top + 1) & kMask) === this.bottom; + } - const isH2 = socket.alpnProtocol === 'h2' - if (isH2) { - if (!h2ExperimentalWarned) { - h2ExperimentalWarned = true - process.emitWarning('H2 support is experimental, expect them to change at any time.', { - code: 'UNDICI-H2' - }) - } + push(data) { + this.list[this.top] = data; + this.top = (this.top + 1) & kMask; + } - const session = http2.connect(client[kUrl], { - createConnection: () => socket, - peerMaxConcurrentStreams: client[kHTTP2SessionState].maxConcurrentStreams - }) + shift() { + const nextItem = this.list[this.bottom]; + if (nextItem === undefined) + return null; + this.list[this.bottom] = undefined; + this.bottom = (this.bottom + 1) & kMask; + return nextItem; + } +} - client[kHTTPConnVersion] = 'h2' - session[kClient] = client - session[kSocket] = socket - session.on('error', onHttp2SessionError) - session.on('frameError', onHttp2FrameError) - session.on('end', onHttp2SessionEnd) - session.on('goaway', onHTTP2GoAway) - session.on('close', onSocketClose) - session.unref() +module.exports = class FixedQueue { + constructor() { + this.head = this.tail = new FixedCircularBuffer(); + } - client[kHTTP2Session] = session - socket[kHTTP2Session] = session - } else { - if (!llhttpInstance) { - llhttpInstance = await llhttpPromise - llhttpPromise = null - } + isEmpty() { + return this.head.isEmpty(); + } - socket[kNoRef] = false - socket[kWriting] = false - socket[kReset] = false - socket[kBlocking] = false - socket[kParser] = new Parser(client, socket, llhttpInstance) + push(data) { + if (this.head.isFull()) { + // Head is full: Creates a new queue, sets the old queue's `.next` to it, + // and sets it as the new main queue. + this.head = this.head.next = new FixedCircularBuffer(); } + this.head.push(data); + } - socket[kCounter] = 0 - socket[kMaxRequests] = client[kMaxRequests] - socket[kClient] = client - socket[kError] = null - - socket - .on('error', onSocketError) - .on('readable', onSocketReadable) - .on('end', onSocketEnd) - .on('close', onSocketClose) - - client[kSocket] = socket - - if (channels.connected.hasSubscribers) { - channels.connected.publish({ - connectParams: { - host, - hostname, - protocol, - port, - servername: client[kServerName], - localAddress: client[kLocalAddress] - }, - connector: client[kConnector], - socket - }) - } - client.emit('connect', client[kUrl], [client]) - } catch (err) { - if (client.destroyed) { - return + shift() { + const tail = this.tail; + const next = tail.shift(); + if (tail.isEmpty() && tail.next !== null) { + // If there is another queue, it forms the new tail. + this.tail = tail.next; } + return next; + } +}; - client[kConnecting] = false - - if (channels.connectError.hasSubscribers) { - channels.connectError.publish({ - connectParams: { - host, - hostname, - protocol, - port, - servername: client[kServerName], - localAddress: client[kLocalAddress] - }, - connector: client[kConnector], - error: err - }) - } - if (err.code === 'ERR_TLS_CERT_ALTNAME_INVALID') { - assert(client[kRunning] === 0) - while (client[kPending] > 0 && client[kQueue][client[kPendingIdx]].servername === client[kServerName]) { - const request = client[kQueue][client[kPendingIdx]++] - errorRequest(client, request, err) - } - } else { - onError(client, err) - } +/***/ }), - client.emit('connectionError', client[kUrl], [client], err) - } +/***/ 5398: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - resume(client) -} -function emitDrain (client) { - client[kNeedDrain] = 0 - client.emit('drain', client[kUrl], [client]) -} -function resume (client, sync) { - if (client[kResuming] === 2) { - return - } +const DispatcherBase = __nccwpck_require__(555) +const FixedQueue = __nccwpck_require__(3830) +const { kConnected, kSize, kRunning, kPending, kQueued, kBusy, kFree, kUrl, kClose, kDestroy, kDispatch } = __nccwpck_require__(7417) +const PoolStats = __nccwpck_require__(8072) - client[kResuming] = 2 +const kClients = Symbol('clients') +const kNeedDrain = Symbol('needDrain') +const kQueue = Symbol('queue') +const kClosedResolve = Symbol('closed resolve') +const kOnDrain = Symbol('onDrain') +const kOnConnect = Symbol('onConnect') +const kOnDisconnect = Symbol('onDisconnect') +const kOnConnectionError = Symbol('onConnectionError') +const kGetDispatcher = Symbol('get dispatcher') +const kAddClient = Symbol('add client') +const kRemoveClient = Symbol('remove client') +const kStats = Symbol('stats') - _resume(client, sync) - client[kResuming] = 0 +class PoolBase extends DispatcherBase { + constructor () { + super() - if (client[kRunningIdx] > 256) { - client[kQueue].splice(0, client[kRunningIdx]) - client[kPendingIdx] -= client[kRunningIdx] - client[kRunningIdx] = 0 - } -} + this[kQueue] = new FixedQueue() + this[kClients] = [] + this[kQueued] = 0 -function _resume (client, sync) { - while (true) { - if (client.destroyed) { - assert(client[kPending] === 0) - return - } + const pool = this - if (client[kClosedResolve] && !client[kSize]) { - client[kClosedResolve]() - client[kClosedResolve] = null - return - } + this[kOnDrain] = function onDrain (origin, targets) { + const queue = pool[kQueue] - const socket = client[kSocket] + let needDrain = false - if (socket && !socket.destroyed && socket.alpnProtocol !== 'h2') { - if (client[kSize] === 0) { - if (!socket[kNoRef] && socket.unref) { - socket.unref() - socket[kNoRef] = true + while (!needDrain) { + const item = queue.shift() + if (!item) { + break } - } else if (socket[kNoRef] && socket.ref) { - socket.ref() - socket[kNoRef] = false + pool[kQueued]-- + needDrain = !this.dispatch(item.opts, item.handler) } - if (client[kSize] === 0) { - if (socket[kParser].timeoutType !== TIMEOUT_IDLE) { - socket[kParser].setTimeout(client[kKeepAliveTimeoutValue], TIMEOUT_IDLE) - } - } else if (client[kRunning] > 0 && socket[kParser].statusCode < 200) { - if (socket[kParser].timeoutType !== TIMEOUT_HEADERS) { - const request = client[kQueue][client[kRunningIdx]] - const headersTimeout = request.headersTimeout != null - ? request.headersTimeout - : client[kHeadersTimeout] - socket[kParser].setTimeout(headersTimeout, TIMEOUT_HEADERS) - } + this[kNeedDrain] = needDrain + + if (!this[kNeedDrain] && pool[kNeedDrain]) { + pool[kNeedDrain] = false + pool.emit('drain', origin, [pool, ...targets]) } - } - if (client[kBusy]) { - client[kNeedDrain] = 2 - } else if (client[kNeedDrain] === 2) { - if (sync) { - client[kNeedDrain] = 1 - process.nextTick(emitDrain, client) - } else { - emitDrain(client) + if (pool[kClosedResolve] && queue.isEmpty()) { + Promise + .all(pool[kClients].map(c => c.close())) + .then(pool[kClosedResolve]) } - continue } - if (client[kPending] === 0) { - return + this[kOnConnect] = (origin, targets) => { + pool.emit('connect', origin, [pool, ...targets]) } - if (client[kRunning] >= (client[kPipelining] || 1)) { - return + this[kOnDisconnect] = (origin, targets, err) => { + pool.emit('disconnect', origin, [pool, ...targets], err) } - const request = client[kQueue][client[kPendingIdx]] - - if (client[kUrl].protocol === 'https:' && client[kServerName] !== request.servername) { - if (client[kRunning] > 0) { - return - } + this[kOnConnectionError] = (origin, targets, err) => { + pool.emit('connectionError', origin, [pool, ...targets], err) + } - client[kServerName] = request.servername + this[kStats] = new PoolStats(this) + } - if (socket && socket.servername !== request.servername) { - util.destroy(socket, new InformationalError('servername changed')) - return - } - } + get [kBusy] () { + return this[kNeedDrain] + } - if (client[kConnecting]) { - return - } + get [kConnected] () { + return this[kClients].filter(client => client[kConnected]).length + } - if (!socket && !client[kHTTP2Session]) { - connect(client) - return - } + get [kFree] () { + return this[kClients].filter(client => client[kConnected] && !client[kNeedDrain]).length + } - if (socket.destroyed || socket[kWriting] || socket[kReset] || socket[kBlocking]) { - return + get [kPending] () { + let ret = this[kQueued] + for (const { [kPending]: pending } of this[kClients]) { + ret += pending } + return ret + } - if (client[kRunning] > 0 && !request.idempotent) { - // Non-idempotent request cannot be retried. - // Ensure that no other requests are inflight and - // could cause failure. - return + get [kRunning] () { + let ret = 0 + for (const { [kRunning]: running } of this[kClients]) { + ret += running } + return ret + } - if (client[kRunning] > 0 && (request.upgrade || request.method === 'CONNECT')) { - // Don't dispatch an upgrade until all preceding requests have completed. - // A misbehaving server might upgrade the connection before all pipelined - // request has completed. - return + get [kSize] () { + let ret = this[kQueued] + for (const { [kSize]: size } of this[kClients]) { + ret += size } + return ret + } - if (client[kRunning] > 0 && util.bodyLength(request.body) !== 0 && - (util.isStream(request.body) || util.isAsyncIterable(request.body))) { - // Request with stream or iterator body can error while other requests - // are inflight and indirectly error those as well. - // Ensure this doesn't happen by waiting for inflight - // to complete before dispatching. - - // Request with stream or iterator body cannot be retried. - // Ensure that no other requests are inflight and - // could cause failure. - return - } + get stats () { + return this[kStats] + } - if (!request.aborted && write(client, request)) { - client[kPendingIdx]++ + async [kClose] () { + if (this[kQueue].isEmpty()) { + await Promise.all(this[kClients].map(c => c.close())) } else { - client[kQueue].splice(client[kPendingIdx], 1) + await new Promise((resolve) => { + this[kClosedResolve] = resolve + }) } } -} -// https://www.rfc-editor.org/rfc/rfc7230#section-3.3.2 -function shouldSendContentLength (method) { - return method !== 'GET' && method !== 'HEAD' && method !== 'OPTIONS' && method !== 'TRACE' && method !== 'CONNECT' -} + async [kDestroy] (err) { + while (true) { + const item = this[kQueue].shift() + if (!item) { + break + } + item.handler.onError(err) + } -function write (client, request) { - if (client[kHTTPConnVersion] === 'h2') { - writeH2(client, client[kHTTP2Session], request) - return + await Promise.all(this[kClients].map(c => c.destroy(err))) } - const { body, method, path, host, upgrade, headers, blocking, reset } = request - - // https://tools.ietf.org/html/rfc7231#section-4.3.1 - // https://tools.ietf.org/html/rfc7231#section-4.3.2 - // https://tools.ietf.org/html/rfc7231#section-4.3.5 - - // Sending a payload body on a request that does not - // expect it can cause undefined behavior on some - // servers and corrupt connection state. Do not - // re-use the connection for further requests. + [kDispatch] (opts, handler) { + const dispatcher = this[kGetDispatcher]() - const expectsPayload = ( - method === 'PUT' || - method === 'POST' || - method === 'PATCH' - ) + if (!dispatcher) { + this[kNeedDrain] = true + this[kQueue].push({ opts, handler }) + this[kQueued]++ + } else if (!dispatcher.dispatch(opts, handler)) { + dispatcher[kNeedDrain] = true + this[kNeedDrain] = !this[kGetDispatcher]() + } - if (body && typeof body.read === 'function') { - // Try to read EOF in order to get length. - body.read(0) + return !this[kNeedDrain] } - const bodyLength = util.bodyLength(body) + [kAddClient] (client) { + client + .on('drain', this[kOnDrain]) + .on('connect', this[kOnConnect]) + .on('disconnect', this[kOnDisconnect]) + .on('connectionError', this[kOnConnectionError]) - let contentLength = bodyLength + this[kClients].push(client) - if (contentLength === null) { - contentLength = request.contentLength + if (this[kNeedDrain]) { + queueMicrotask(() => { + if (this[kNeedDrain]) { + this[kOnDrain](client[kUrl], [this, client]) + } + }) + } + + return this } - if (contentLength === 0 && !expectsPayload) { - // https://tools.ietf.org/html/rfc7230#section-3.3.2 - // A user agent SHOULD NOT send a Content-Length header field when - // the request message does not contain a payload body and the method - // semantics do not anticipate such a body. + [kRemoveClient] (client) { + client.close(() => { + const idx = this[kClients].indexOf(client) + if (idx !== -1) { + this[kClients].splice(idx, 1) + } + }) - contentLength = null + this[kNeedDrain] = this[kClients].some(dispatcher => ( + !dispatcher[kNeedDrain] && + dispatcher.closed !== true && + dispatcher.destroyed !== true + )) } +} - // https://github.com/nodejs/undici/issues/2046 - // A user agent may send a Content-Length header with 0 value, this should be allowed. - if (shouldSendContentLength(method) && contentLength > 0 && request.contentLength !== null && request.contentLength !== contentLength) { - if (client[kStrictContentLength]) { - errorRequest(client, request, new RequestContentLengthMismatchError()) - return false - } +module.exports = { + PoolBase, + kClients, + kNeedDrain, + kAddClient, + kRemoveClient, + kGetDispatcher +} - process.emitWarning(new RequestContentLengthMismatchError()) - } - const socket = client[kSocket] +/***/ }), - try { - request.onConnect((err) => { - if (request.aborted || request.completed) { - return - } +/***/ 8072: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - errorRequest(client, request, err || new RequestAbortedError()) +const { kFree, kConnected, kPending, kQueued, kRunning, kSize } = __nccwpck_require__(7417) +const kPool = Symbol('pool') - util.destroy(socket, new InformationalError('aborted')) - }) - } catch (err) { - errorRequest(client, request, err) +class PoolStats { + constructor (pool) { + this[kPool] = pool } - if (request.aborted) { - return false + get connected () { + return this[kPool][kConnected] } - if (method === 'HEAD') { - // https://github.com/mcollina/undici/issues/258 - // Close after a HEAD request to interop with misbehaving servers - // that may send a body in the response. - - socket[kReset] = true + get free () { + return this[kPool][kFree] } - if (upgrade || method === 'CONNECT') { - // On CONNECT or upgrade, block pipeline from dispatching further - // requests on this connection. - - socket[kReset] = true + get pending () { + return this[kPool][kPending] } - if (reset != null) { - socket[kReset] = reset + get queued () { + return this[kPool][kQueued] } - if (client[kMaxRequests] && socket[kCounter]++ >= client[kMaxRequests]) { - socket[kReset] = true + get running () { + return this[kPool][kRunning] } - if (blocking) { - socket[kBlocking] = true + get size () { + return this[kPool][kSize] } +} - let header = `${method} ${path} HTTP/1.1\r\n` +module.exports = PoolStats - if (typeof host === 'string') { - header += `host: ${host}\r\n` - } else { - header += client[kHostHeader] - } - if (upgrade) { - header += `connection: upgrade\r\nupgrade: ${upgrade}\r\n` - } else if (client[kPipelining] && !socket[kReset]) { - header += 'connection: keep-alive\r\n' - } else { - header += 'connection: close\r\n' - } +/***/ }), - if (headers) { - header += headers - } +/***/ 4105: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - if (channels.sendHeaders.hasSubscribers) { - channels.sendHeaders.publish({ request, headers: header, socket }) - } - /* istanbul ignore else: assertion */ - if (!body || bodyLength === 0) { - if (contentLength === 0) { - socket.write(`${header}content-length: 0\r\n\r\n`, 'latin1') - } else { - assert(contentLength === null, 'no body must not have content length') - socket.write(`${header}\r\n`, 'latin1') - } - request.onRequestSent() - } else if (util.isBuffer(body)) { - assert(contentLength === body.byteLength, 'buffer body must have content length') - socket.cork() - socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'latin1') - socket.write(body) - socket.uncork() - request.onBodySent(body) - request.onRequestSent() - if (!expectsPayload) { - socket[kReset] = true - } - } else if (util.isBlobLike(body)) { - if (typeof body.stream === 'function') { - writeIterable({ body: body.stream(), client, request, socket, contentLength, header, expectsPayload }) - } else { - writeBlob({ body, client, request, socket, contentLength, header, expectsPayload }) - } - } else if (util.isStream(body)) { - writeStream({ body, client, request, socket, contentLength, header, expectsPayload }) - } else if (util.isIterable(body)) { - writeIterable({ body, client, request, socket, contentLength, header, expectsPayload }) - } else { - assert(false) - } +const { + PoolBase, + kClients, + kNeedDrain, + kAddClient, + kGetDispatcher +} = __nccwpck_require__(5398) +const Client = __nccwpck_require__(9143) +const { + InvalidArgumentError +} = __nccwpck_require__(329) +const util = __nccwpck_require__(7234) +const { kUrl, kInterceptors } = __nccwpck_require__(7417) +const buildConnector = __nccwpck_require__(3242) - return true +const kOptions = Symbol('options') +const kConnections = Symbol('connections') +const kFactory = Symbol('factory') + +function defaultFactory (origin, opts) { + return new Client(origin, opts) } -function writeH2 (client, session, request) { - const { body, method, path, host, upgrade, expectContinue, signal, headers: reqHeaders } = request +class Pool extends PoolBase { + constructor (origin, { + connections, + factory = defaultFactory, + connect, + connectTimeout, + tls, + maxCachedSessions, + socketPath, + autoSelectFamily, + autoSelectFamilyAttemptTimeout, + allowH2, + ...options + } = {}) { + super() + + if (connections != null && (!Number.isFinite(connections) || connections < 0)) { + throw new InvalidArgumentError('invalid connections') + } - let headers - if (typeof reqHeaders === 'string') headers = Request[kHTTP2CopyHeaders](reqHeaders.trim()) - else headers = reqHeaders + if (typeof factory !== 'function') { + throw new InvalidArgumentError('factory must be a function.') + } - if (upgrade) { - errorRequest(client, request, new Error('Upgrade not supported for H2')) - return false - } + if (connect != null && typeof connect !== 'function' && typeof connect !== 'object') { + throw new InvalidArgumentError('connect must be a function or an object') + } - try { - // TODO(HTTP/2): Should we call onConnect immediately or on stream ready event? - request.onConnect((err) => { - if (request.aborted || request.completed) { - return - } + if (typeof connect !== 'function') { + connect = buildConnector({ + ...tls, + maxCachedSessions, + allowH2, + socketPath, + timeout: connectTimeout, + ...(autoSelectFamily ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : undefined), + ...connect + }) + } + + this[kInterceptors] = options.interceptors?.Pool && Array.isArray(options.interceptors.Pool) + ? options.interceptors.Pool + : [] + this[kConnections] = connections || null + this[kUrl] = util.parseOrigin(origin) + this[kOptions] = { ...util.deepClone(options), connect, allowH2 } + this[kOptions].interceptors = options.interceptors + ? { ...options.interceptors } + : undefined + this[kFactory] = factory - errorRequest(client, request, err || new RequestAbortedError()) + this.on('connectionError', (origin, targets, error) => { + // If a connection error occurs, we remove the client from the pool, + // and emit a connectionError event. They will not be re-used. + // Fixes https://github.com/nodejs/undici/issues/3895 + for (const target of targets) { + // Do not use kRemoveClient here, as it will close the client, + // but the client cannot be closed in this state. + const idx = this[kClients].indexOf(target) + if (idx !== -1) { + this[kClients].splice(idx, 1) + } + } }) - } catch (err) { - errorRequest(client, request, err) } - if (request.aborted) { - return false + [kGetDispatcher] () { + for (const client of this[kClients]) { + if (!client[kNeedDrain]) { + return client + } + } + + if (!this[kConnections] || this[kClients].length < this[kConnections]) { + const dispatcher = this[kFactory](this[kUrl], this[kOptions]) + this[kAddClient](dispatcher) + return dispatcher + } } +} - /** @type {import('node:http2').ClientHttp2Stream} */ - let stream - const h2State = client[kHTTP2SessionState] +module.exports = Pool - headers[HTTP2_HEADER_AUTHORITY] = host || client[kHost] - headers[HTTP2_HEADER_METHOD] = method - if (method === 'CONNECT') { - session.ref() - // we are already connected, streams are pending, first request - // will create a new stream. We trigger a request to create the stream and wait until - // `ready` event is triggered - // We disabled endStream to allow the user to write to the stream - stream = session.request(headers, { endStream: false, signal }) +/***/ }), - if (stream.id && !stream.pending) { - request.onUpgrade(null, null, stream) - ++h2State.openStreams - } else { - stream.once('ready', () => { - request.onUpgrade(null, null, stream) - ++h2State.openStreams - }) - } +/***/ 6614: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - stream.once('close', () => { - h2State.openStreams -= 1 - // TODO(HTTP/2): unref only if current streams count is 0 - if (h2State.openStreams === 0) session.unref() - }) - return true - } - // https://tools.ietf.org/html/rfc7540#section-8.3 - // :path and :scheme headers must be omited when sending CONNECT +const { kProxy, kClose, kDestroy, kDispatch, kInterceptors } = __nccwpck_require__(7417) +const { URL } = __nccwpck_require__(3136) +const Agent = __nccwpck_require__(4779) +const Pool = __nccwpck_require__(4105) +const DispatcherBase = __nccwpck_require__(555) +const { InvalidArgumentError, RequestAbortedError, SecureProxyConnectionError } = __nccwpck_require__(329) +const buildConnector = __nccwpck_require__(3242) +const Client = __nccwpck_require__(9143) - headers[HTTP2_HEADER_PATH] = path - headers[HTTP2_HEADER_SCHEME] = 'https' +const kAgent = Symbol('proxy agent') +const kClient = Symbol('proxy client') +const kProxyHeaders = Symbol('proxy headers') +const kRequestTls = Symbol('request tls settings') +const kProxyTls = Symbol('proxy tls settings') +const kConnectEndpoint = Symbol('connect endpoint function') +const kTunnelProxy = Symbol('tunnel proxy') - // https://tools.ietf.org/html/rfc7231#section-4.3.1 - // https://tools.ietf.org/html/rfc7231#section-4.3.2 - // https://tools.ietf.org/html/rfc7231#section-4.3.5 +function defaultProtocolPort (protocol) { + return protocol === 'https:' ? 443 : 80 +} - // Sending a payload body on a request that does not - // expect it can cause undefined behavior on some - // servers and corrupt connection state. Do not - // re-use the connection for further requests. +function defaultFactory (origin, opts) { + return new Pool(origin, opts) +} - const expectsPayload = ( - method === 'PUT' || - method === 'POST' || - method === 'PATCH' - ) +const noop = () => {} - if (body && typeof body.read === 'function') { - // Try to read EOF in order to get length. - body.read(0) +function defaultAgentFactory (origin, opts) { + if (opts.connections === 1) { + return new Client(origin, opts) } + return new Pool(origin, opts) +} - let contentLength = util.bodyLength(body) - - if (contentLength == null) { - contentLength = request.contentLength - } +class Http1ProxyWrapper extends DispatcherBase { + #client - if (contentLength === 0 || !expectsPayload) { - // https://tools.ietf.org/html/rfc7230#section-3.3.2 - // A user agent SHOULD NOT send a Content-Length header field when - // the request message does not contain a payload body and the method - // semantics do not anticipate such a body. + constructor (proxyUrl, { headers = {}, connect, factory }) { + super() + if (!proxyUrl) { + throw new InvalidArgumentError('Proxy URL is mandatory') + } - contentLength = null + this[kProxyHeaders] = headers + if (factory) { + this.#client = factory(proxyUrl, { connect }) + } else { + this.#client = new Client(proxyUrl, { connect }) + } } - // https://github.com/nodejs/undici/issues/2046 - // A user agent may send a Content-Length header with 0 value, this should be allowed. - if (shouldSendContentLength(method) && contentLength > 0 && request.contentLength != null && request.contentLength !== contentLength) { - if (client[kStrictContentLength]) { - errorRequest(client, request, new RequestContentLengthMismatchError()) - return false + [kDispatch] (opts, handler) { + const onHeaders = handler.onHeaders + handler.onHeaders = function (statusCode, data, resume) { + if (statusCode === 407) { + if (typeof handler.onError === 'function') { + handler.onError(new InvalidArgumentError('Proxy Authentication Required (407)')) + } + return + } + if (onHeaders) onHeaders.call(this, statusCode, data, resume) } - process.emitWarning(new RequestContentLengthMismatchError()) - } + // Rewrite request as an HTTP1 Proxy request, without tunneling. + const { + origin, + path = '/', + headers = {} + } = opts - if (contentLength != null) { - assert(body, 'no body must not have content length') - headers[HTTP2_HEADER_CONTENT_LENGTH] = `${contentLength}` - } + opts.path = origin + path - session.ref() + if (!('host' in headers) && !('Host' in headers)) { + const { host } = new URL(origin) + headers.host = host + } + opts.headers = { ...this[kProxyHeaders], ...headers } - const shouldEndStream = method === 'GET' || method === 'HEAD' - if (expectContinue) { - headers[HTTP2_HEADER_EXPECT] = '100-continue' - stream = session.request(headers, { endStream: shouldEndStream, signal }) + return this.#client[kDispatch](opts, handler) + } - stream.once('continue', writeBodyH2) - } else { - stream = session.request(headers, { - endStream: shouldEndStream, - signal - }) - writeBodyH2() + async [kClose] () { + return this.#client.close() } - // Increment counter as we have new several streams open - ++h2State.openStreams + async [kDestroy] (err) { + return this.#client.destroy(err) + } +} - stream.once('response', headers => { - const { [HTTP2_HEADER_STATUS]: statusCode, ...realHeaders } = headers +class ProxyAgent extends DispatcherBase { + constructor (opts) { + super() - if (request.onHeaders(Number(statusCode), realHeaders, stream.resume.bind(stream), '') === false) { - stream.pause() + if (!opts || (typeof opts === 'object' && !(opts instanceof URL) && !opts.uri)) { + throw new InvalidArgumentError('Proxy uri is mandatory') } - }) - - stream.once('end', () => { - request.onComplete([]) - }) - stream.on('data', (chunk) => { - if (request.onData(chunk) === false) { - stream.pause() + const { clientFactory = defaultFactory } = opts + if (typeof clientFactory !== 'function') { + throw new InvalidArgumentError('Proxy opts.clientFactory must be a function.') } - }) - stream.once('close', () => { - h2State.openStreams -= 1 - // TODO(HTTP/2): unref only if current streams count is 0 - if (h2State.openStreams === 0) { - session.unref() - } - }) + const { proxyTunnel = true } = opts - stream.once('error', function (err) { - if (client[kHTTP2Session] && !client[kHTTP2Session].destroyed && !this.closed && !this.destroyed) { - h2State.streams -= 1 - util.destroy(stream, err) - } - }) + const url = this.#getUrl(opts) + const { href, origin, port, protocol, username, password, hostname: proxyHostname } = url - stream.once('frameError', (type, code) => { - const err = new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`) - errorRequest(client, request, err) + this[kProxy] = { uri: href, protocol } + this[kInterceptors] = opts.interceptors?.ProxyAgent && Array.isArray(opts.interceptors.ProxyAgent) + ? opts.interceptors.ProxyAgent + : [] + this[kRequestTls] = opts.requestTls + this[kProxyTls] = opts.proxyTls + this[kProxyHeaders] = opts.headers || {} + this[kTunnelProxy] = proxyTunnel - if (client[kHTTP2Session] && !client[kHTTP2Session].destroyed && !this.closed && !this.destroyed) { - h2State.streams -= 1 - util.destroy(stream, err) + if (opts.auth && opts.token) { + throw new InvalidArgumentError('opts.auth cannot be used in combination with opts.token') + } else if (opts.auth) { + /* @deprecated in favour of opts.token */ + this[kProxyHeaders]['proxy-authorization'] = `Basic ${opts.auth}` + } else if (opts.token) { + this[kProxyHeaders]['proxy-authorization'] = opts.token + } else if (username && password) { + this[kProxyHeaders]['proxy-authorization'] = `Basic ${Buffer.from(`${decodeURIComponent(username)}:${decodeURIComponent(password)}`).toString('base64')}` } - }) - - // stream.on('aborted', () => { - // // TODO(HTTP/2): Support aborted - // }) - - // stream.on('timeout', () => { - // // TODO(HTTP/2): Support timeout - // }) - - // stream.on('push', headers => { - // // TODO(HTTP/2): Suppor push - // }) - - // stream.on('trailers', headers => { - // // TODO(HTTP/2): Support trailers - // }) - return true + const connect = buildConnector({ ...opts.proxyTls }) + this[kConnectEndpoint] = buildConnector({ ...opts.requestTls }) - function writeBodyH2 () { - /* istanbul ignore else: assertion */ - if (!body) { - request.onRequestSent() - } else if (util.isBuffer(body)) { - assert(contentLength === body.byteLength, 'buffer body must have content length') - stream.cork() - stream.write(body) - stream.uncork() - stream.end() - request.onBodySent(body) - request.onRequestSent() - } else if (util.isBlobLike(body)) { - if (typeof body.stream === 'function') { - writeIterable({ - client, - request, - contentLength, - h2stream: stream, - expectsPayload, - body: body.stream(), - socket: client[kSocket], - header: '' - }) - } else { - writeBlob({ - body, - client, - request, - contentLength, - expectsPayload, - h2stream: stream, - header: '', - socket: client[kSocket] + const agentFactory = opts.factory || defaultAgentFactory + const factory = (origin, options) => { + const { protocol } = new URL(origin) + if (!this[kTunnelProxy] && protocol === 'http:' && this[kProxy].protocol === 'http:') { + return new Http1ProxyWrapper(this[kProxy].uri, { + headers: this[kProxyHeaders], + connect, + factory: agentFactory }) } - } else if (util.isStream(body)) { - writeStream({ - body, - client, - request, - contentLength, - expectsPayload, - socket: client[kSocket], - h2stream: stream, - header: '' - }) - } else if (util.isIterable(body)) { - writeIterable({ - body, - client, - request, - contentLength, - expectsPayload, - header: '', - h2stream: stream, - socket: client[kSocket] - }) - } else { - assert(false) + return agentFactory(origin, options) } - } -} - -function writeStream ({ h2stream, body, client, request, socket, contentLength, header, expectsPayload }) { - assert(contentLength !== 0 || client[kRunning] === 0, 'stream body cannot be pipelined') - - if (client[kHTTPConnVersion] === 'h2') { - // For HTTP/2, is enough to pipe the stream - const pipe = pipeline( - body, - h2stream, - (err) => { - if (err) { - util.destroy(body, err) - util.destroy(h2stream, err) - } else { - request.onRequestSent() + this[kClient] = clientFactory(url, { connect }) + this[kAgent] = new Agent({ + ...opts, + factory, + connect: async (opts, callback) => { + let requestedPath = opts.host + if (!opts.port) { + requestedPath += `:${defaultProtocolPort(opts.protocol)}` + } + try { + const { socket, statusCode } = await this[kClient].connect({ + origin, + port, + path: requestedPath, + signal: opts.signal, + headers: { + ...this[kProxyHeaders], + host: opts.host + }, + servername: this[kProxyTls]?.servername || proxyHostname + }) + if (statusCode !== 200) { + socket.on('error', noop).destroy() + callback(new RequestAbortedError(`Proxy response (${statusCode}) !== 200 when HTTP Tunneling`)) + } + if (opts.protocol !== 'https:') { + callback(null, socket) + return + } + let servername + if (this[kRequestTls]) { + servername = this[kRequestTls].servername + } else { + servername = opts.servername + } + this[kConnectEndpoint]({ ...opts, servername, httpSocket: socket }, callback) + } catch (err) { + if (err.code === 'ERR_TLS_CERT_ALTNAME_INVALID') { + // Throw a custom error to avoid loop in client.js#connect + callback(new SecureProxyConnectionError(err)) + } else { + callback(err) + } } } - ) - - pipe.on('data', onPipeData) - pipe.once('end', () => { - pipe.removeListener('data', onPipeData) - util.destroy(pipe) }) - - function onPipeData (chunk) { - request.onBodySent(chunk) - } - - return } - let finished = false - - const writer = new AsyncWriter({ socket, request, contentLength, client, expectsPayload, header }) + dispatch (opts, handler) { + const headers = buildHeaders(opts.headers) + throwIfProxyAuthIsSent(headers) - const onData = function (chunk) { - if (finished) { - return + if (headers && !('host' in headers) && !('Host' in headers)) { + const { host } = new URL(opts.origin) + headers.host = host } - try { - if (!writer.write(chunk) && this.pause) { - this.pause() - } - } catch (err) { - util.destroy(this, err) - } + return this[kAgent].dispatch( + { + ...opts, + headers + }, + handler + ) } - const onDrain = function () { - if (finished) { - return - } - if (body.resume) { - body.resume() - } - } - const onAbort = function () { - if (finished) { - return + /** + * @param {import('../types/proxy-agent').ProxyAgent.Options | string | URL} opts + * @returns {URL} + */ + #getUrl (opts) { + if (typeof opts === 'string') { + return new URL(opts) + } else if (opts instanceof URL) { + return opts + } else { + return new URL(opts.uri) } - const err = new RequestAbortedError() - queueMicrotask(() => onFinished(err)) } - const onFinished = function (err) { - if (finished) { - return - } - - finished = true - assert(socket.destroyed || (socket[kWriting] && client[kRunning] <= 1)) + async [kClose] () { + await this[kAgent].close() + await this[kClient].close() + } - socket - .off('drain', onDrain) - .off('error', onFinished) + async [kDestroy] () { + await this[kAgent].destroy() + await this[kClient].destroy() + } +} - body - .removeListener('data', onData) - .removeListener('end', onFinished) - .removeListener('error', onFinished) - .removeListener('close', onAbort) +/** + * @param {string[] | Record} headers + * @returns {Record} + */ +function buildHeaders (headers) { + // When using undici.fetch, the headers list is stored + // as an array. + if (Array.isArray(headers)) { + /** @type {Record} */ + const headersPair = {} - if (!err) { - try { - writer.end() - } catch (er) { - err = er - } + for (let i = 0; i < headers.length; i += 2) { + headersPair[headers[i]] = headers[i + 1] } - writer.destroy(err) - - if (err && (err.code !== 'UND_ERR_INFO' || err.message !== 'reset')) { - util.destroy(body, err) - } else { - util.destroy(body) - } + return headersPair } - body - .on('data', onData) - .on('end', onFinished) - .on('error', onFinished) - .on('close', onAbort) + return headers +} - if (body.resume) { - body.resume() +/** + * @param {Record} headers + * + * Previous versions of ProxyAgent suggests the Proxy-Authorization in request headers + * Nevertheless, it was changed and to avoid a security vulnerability by end users + * this check was created. + * It should be removed in the next major version for performance reasons + */ +function throwIfProxyAuthIsSent (headers) { + const existProxyAuth = headers && Object.keys(headers) + .find((key) => key.toLowerCase() === 'proxy-authorization') + if (existProxyAuth) { + throw new InvalidArgumentError('Proxy-Authorization should be sent in ProxyAgent constructor') } - - socket - .on('drain', onDrain) - .on('error', onFinished) } -async function writeBlob ({ h2stream, body, client, request, socket, contentLength, header, expectsPayload }) { - assert(contentLength === body.size, 'blob body must have content length') +module.exports = ProxyAgent - const isH2 = client[kHTTPConnVersion] === 'h2' - try { - if (contentLength != null && contentLength !== body.size) { - throw new RequestContentLengthMismatchError() - } - const buffer = Buffer.from(await body.arrayBuffer()) +/***/ }), - if (isH2) { - h2stream.cork() - h2stream.write(buffer) - h2stream.uncork() - } else { - socket.cork() - socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'latin1') - socket.write(buffer) - socket.uncork() - } +/***/ 8800: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - request.onBodySent(buffer) - request.onRequestSent() - if (!expectsPayload) { - socket[kReset] = true - } - resume(client) - } catch (err) { - util.destroy(isH2 ? h2stream : socket, err) +const Dispatcher = __nccwpck_require__(5137) +const RetryHandler = __nccwpck_require__(1838) + +class RetryAgent extends Dispatcher { + #agent = null + #options = null + constructor (agent, options = {}) { + super(options) + this.#agent = agent + this.#options = options } -} -async function writeIterable ({ h2stream, body, client, request, socket, contentLength, header, expectsPayload }) { - assert(contentLength !== 0 || client[kRunning] === 0, 'iterator body cannot be pipelined') + dispatch (opts, handler) { + const retry = new RetryHandler({ + ...opts, + retryOptions: this.#options + }, { + dispatch: this.#agent.dispatch.bind(this.#agent), + handler + }) + return this.#agent.dispatch(opts, retry) + } - let callback = null - function onDrain () { - if (callback) { - const cb = callback - callback = null - cb() - } + close () { + return this.#agent.close() } - const waitForDrain = () => new Promise((resolve, reject) => { - assert(callback === null) + destroy () { + return this.#agent.destroy() + } +} - if (socket[kError]) { - reject(socket[kError]) - } else { - callback = resolve - } - }) +module.exports = RetryAgent - if (client[kHTTPConnVersion] === 'h2') { - h2stream - .on('close', onDrain) - .on('drain', onDrain) - try { - // It's up to the user to somehow abort the async iterable. - for await (const chunk of body) { - if (socket[kError]) { - throw socket[kError] - } +/***/ }), - const res = h2stream.write(chunk) - request.onBodySent(chunk) - if (!res) { - await waitForDrain() - } - } - } catch (err) { - h2stream.destroy(err) - } finally { - request.onRequestSent() - h2stream.end() - h2stream - .off('close', onDrain) - .off('drain', onDrain) - } +/***/ 1903: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - return - } - socket - .on('close', onDrain) - .on('drain', onDrain) - const writer = new AsyncWriter({ socket, request, contentLength, client, expectsPayload, header }) - try { - // It's up to the user to somehow abort the async iterable. - for await (const chunk of body) { - if (socket[kError]) { - throw socket[kError] - } +// We include a version number for the Dispatcher API. In case of breaking changes, +// this version number must be increased to avoid conflicts. +const globalDispatcher = Symbol.for('undici.globalDispatcher.1') +const { InvalidArgumentError } = __nccwpck_require__(329) +const Agent = __nccwpck_require__(4779) - if (!writer.write(chunk)) { - await waitForDrain() - } - } +if (getGlobalDispatcher() === undefined) { + setGlobalDispatcher(new Agent()) +} - writer.end() - } catch (err) { - writer.destroy(err) - } finally { - socket - .off('close', onDrain) - .off('drain', onDrain) +function setGlobalDispatcher (agent) { + if (!agent || typeof agent.dispatch !== 'function') { + throw new InvalidArgumentError('Argument agent must implement Agent') } + Object.defineProperty(globalThis, globalDispatcher, { + value: agent, + writable: true, + enumerable: false, + configurable: false + }) } -class AsyncWriter { - constructor ({ socket, request, contentLength, client, expectsPayload, header }) { - this.socket = socket - this.request = request - this.contentLength = contentLength - this.client = client - this.bytesWritten = 0 - this.expectsPayload = expectsPayload - this.header = header +function getGlobalDispatcher () { + return globalThis[globalDispatcher] +} - socket[kWriting] = true - } +module.exports = { + setGlobalDispatcher, + getGlobalDispatcher +} - write (chunk) { - const { socket, request, contentLength, client, bytesWritten, expectsPayload, header } = this - if (socket[kError]) { - throw socket[kError] - } +/***/ }), - if (socket.destroyed) { - return false - } +/***/ 6541: +/***/ ((module) => { - const len = Buffer.byteLength(chunk) - if (!len) { - return true - } - // We should defer writing chunks. - if (contentLength !== null && bytesWritten + len > contentLength) { - if (client[kStrictContentLength]) { - throw new RequestContentLengthMismatchError() - } - process.emitWarning(new RequestContentLengthMismatchError()) +module.exports = class DecoratorHandler { + #handler + + constructor (handler) { + if (typeof handler !== 'object' || handler === null) { + throw new TypeError('handler must be an object') } + this.#handler = handler + } - socket.cork() + onConnect (...args) { + return this.#handler.onConnect?.(...args) + } - if (bytesWritten === 0) { - if (!expectsPayload) { - socket[kReset] = true - } + onError (...args) { + return this.#handler.onError?.(...args) + } - if (contentLength === null) { - socket.write(`${header}transfer-encoding: chunked\r\n`, 'latin1') - } else { - socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'latin1') - } - } + onUpgrade (...args) { + return this.#handler.onUpgrade?.(...args) + } - if (contentLength === null) { - socket.write(`\r\n${len.toString(16)}\r\n`, 'latin1') - } + onResponseStarted (...args) { + return this.#handler.onResponseStarted?.(...args) + } - this.bytesWritten += len + onHeaders (...args) { + return this.#handler.onHeaders?.(...args) + } - const ret = socket.write(chunk) + onData (...args) { + return this.#handler.onData?.(...args) + } - socket.uncork() + onComplete (...args) { + return this.#handler.onComplete?.(...args) + } - request.onBodySent(chunk) + onBodySent (...args) { + return this.#handler.onBodySent?.(...args) + } +} - if (!ret) { - if (socket[kParser].timeout && socket[kParser].timeoutType === TIMEOUT_HEADERS) { - // istanbul ignore else: only for jest - if (socket[kParser].timeout.refresh) { - socket[kParser].timeout.refresh() - } - } - } - return ret - } +/***/ }), - end () { - const { socket, contentLength, client, bytesWritten, expectsPayload, header, request } = this - request.onRequestSent() +/***/ 7608: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - socket[kWriting] = false - if (socket[kError]) { - throw socket[kError] - } - if (socket.destroyed) { - return +const util = __nccwpck_require__(7234) +const { kBodyUsed } = __nccwpck_require__(7417) +const assert = __nccwpck_require__(4589) +const { InvalidArgumentError } = __nccwpck_require__(329) +const EE = __nccwpck_require__(8474) + +const redirectableStatusCodes = [300, 301, 302, 303, 307, 308] + +const kBody = Symbol('body') + +class BodyAsyncIterable { + constructor (body) { + this[kBody] = body + this[kBodyUsed] = false + } + + async * [Symbol.asyncIterator] () { + assert(!this[kBodyUsed], 'disturbed') + this[kBodyUsed] = true + yield * this[kBody] + } +} + +class RedirectHandler { + constructor (dispatch, maxRedirections, opts, handler) { + if (maxRedirections != null && (!Number.isInteger(maxRedirections) || maxRedirections < 0)) { + throw new InvalidArgumentError('maxRedirections must be a positive number') } - if (bytesWritten === 0) { - if (expectsPayload) { - // https://tools.ietf.org/html/rfc7230#section-3.3.2 - // A user agent SHOULD send a Content-Length in a request message when - // no Transfer-Encoding is sent and the request method defines a meaning - // for an enclosed payload body. + util.validateHandler(handler, opts.method, opts.upgrade) - socket.write(`${header}content-length: 0\r\n\r\n`, 'latin1') - } else { - socket.write(`${header}\r\n`, 'latin1') + this.dispatch = dispatch + this.location = null + this.abort = null + this.opts = { ...opts, maxRedirections: 0 } // opts must be a copy + this.maxRedirections = maxRedirections + this.handler = handler + this.history = [] + this.redirectionLimitReached = false + + if (util.isStream(this.opts.body)) { + // TODO (fix): Provide some way for the user to cache the file to e.g. /tmp + // so that it can be dispatched again? + // TODO (fix): Do we need 100-expect support to provide a way to do this properly? + if (util.bodyLength(this.opts.body) === 0) { + this.opts.body + .on('data', function () { + assert(false) + }) } - } else if (contentLength === null) { - socket.write('\r\n0\r\n\r\n', 'latin1') - } - if (contentLength !== null && bytesWritten !== contentLength) { - if (client[kStrictContentLength]) { - throw new RequestContentLengthMismatchError() - } else { - process.emitWarning(new RequestContentLengthMismatchError()) + if (typeof this.opts.body.readableDidRead !== 'boolean') { + this.opts.body[kBodyUsed] = false + EE.prototype.on.call(this.opts.body, 'data', function () { + this[kBodyUsed] = true + }) } + } else if (this.opts.body && typeof this.opts.body.pipeTo === 'function') { + // TODO (fix): We can't access ReadableStream internal state + // to determine whether or not it has been disturbed. This is just + // a workaround. + this.opts.body = new BodyAsyncIterable(this.opts.body) + } else if ( + this.opts.body && + typeof this.opts.body !== 'string' && + !ArrayBuffer.isView(this.opts.body) && + util.isIterable(this.opts.body) + ) { + // TODO: Should we allow re-using iterable if !this.opts.idempotent + // or through some other flag? + this.opts.body = new BodyAsyncIterable(this.opts.body) } + } - if (socket[kParser].timeout && socket[kParser].timeoutType === TIMEOUT_HEADERS) { - // istanbul ignore else: only for jest - if (socket[kParser].timeout.refresh) { - socket[kParser].timeout.refresh() + onConnect (abort) { + this.abort = abort + this.handler.onConnect(abort, { history: this.history }) + } + + onUpgrade (statusCode, headers, socket) { + this.handler.onUpgrade(statusCode, headers, socket) + } + + onError (error) { + this.handler.onError(error) + } + + onHeaders (statusCode, headers, resume, statusText) { + this.location = this.history.length >= this.maxRedirections || util.isDisturbed(this.opts.body) + ? null + : parseLocation(statusCode, headers) + + if (this.opts.throwOnMaxRedirect && this.history.length >= this.maxRedirections) { + if (this.request) { + this.request.abort(new Error('max redirects')) } + + this.redirectionLimitReached = true + this.abort(new Error('max redirects')) + return } - resume(client) - } + if (this.opts.origin) { + this.history.push(new URL(this.opts.path, this.opts.origin)) + } - destroy (err) { - const { socket, client } = this + if (!this.location) { + return this.handler.onHeaders(statusCode, headers, resume, statusText) + } - socket[kWriting] = false + const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin))) + const path = search ? `${pathname}${search}` : pathname - if (err) { - assert(client[kRunning] <= 1, 'pipeline should only contain this request') - util.destroy(socket, err) + // Remove headers referring to the original URL. + // By default it is Host only, unless it's a 303 (see below), which removes also all Content-* headers. + // https://tools.ietf.org/html/rfc7231#section-6.4 + this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin) + this.opts.path = path + this.opts.origin = origin + this.opts.maxRedirections = 0 + this.opts.query = null + + // https://tools.ietf.org/html/rfc7231#section-6.4.4 + // In case of HTTP 303, always replace method to be either HEAD or GET + if (statusCode === 303 && this.opts.method !== 'HEAD') { + this.opts.method = 'GET' + this.opts.body = null } } -} -function errorRequest (client, request, err) { - try { - request.onError(err) - assert(request.aborted) - } catch (err) { - client.emit('error', err) - } -} + onData (chunk) { + if (this.location) { + /* + https://tools.ietf.org/html/rfc7231#section-6.4 -module.exports = Client + TLDR: undici always ignores 3xx response bodies. + Redirection is used to serve the requested resource from another URL, so it is assumes that + no body is generated (and thus can be ignored). Even though generating a body is not prohibited. -/***/ }), + For status 301, 302, 303, 307 and 308 (the latter from RFC 7238), the specs mention that the body usually + (which means it's optional and not mandated) contain just an hyperlink to the value of + the Location response header, so the body can be ignored safely. -/***/ 199: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + For status 300, which is "Multiple Choices", the spec mentions both generating a Location + response header AND a response body with the other possible location to follow. + Since the spec explicitly chooses not to specify a format for such body and leave it to + servers and browsers implementors, we ignore the body as there is no specified way to eventually parse it. + */ + } else { + return this.handler.onData(chunk) + } + } -"use strict"; + onComplete (trailers) { + if (this.location) { + /* + https://tools.ietf.org/html/rfc7231#section-6.4 + TLDR: undici always ignores 3xx response trailers as they are not expected in case of redirections + and neither are useful if present. -/* istanbul ignore file: only for Node 12 */ + See comment on onData method above for more detailed information. + */ -const { kConnected, kSize } = __nccwpck_require__(1028) + this.location = null + this.abort = null -class CompatWeakRef { - constructor (value) { - this.value = value + this.dispatch(this.opts, this) + } else { + this.handler.onComplete(trailers) + } } - deref () { - return this.value[kConnected] === 0 && this.value[kSize] === 0 - ? undefined - : this.value + onBodySent (chunk) { + if (this.handler.onBodySent) { + this.handler.onBodySent(chunk) + } } } -class CompatFinalizer { - constructor (finalizer) { - this.finalizer = finalizer +function parseLocation (statusCode, headers) { + if (redirectableStatusCodes.indexOf(statusCode) === -1) { + return null } - register (dispatcher, key) { - if (dispatcher.on) { - dispatcher.on('disconnect', () => { - if (dispatcher[kConnected] === 0 && dispatcher[kSize] === 0) { - this.finalizer(key) - } - }) + for (let i = 0; i < headers.length; i += 2) { + if (headers[i].length === 8 && util.headerNameToString(headers[i]) === 'location') { + return headers[i + 1] } } } -module.exports = function () { - // FIXME: remove workaround when the Node bug is fixed - // https://github.com/nodejs/node/issues/49344#issuecomment-1741776308 - if (process.env.NODE_V8_COVERAGE) { - return { - WeakRef: CompatWeakRef, - FinalizationRegistry: CompatFinalizer - } +// https://tools.ietf.org/html/rfc7231#section-6.4.4 +function shouldRemoveHeader (header, removeContent, unknownOrigin) { + if (header.length === 4) { + return util.headerNameToString(header) === 'host' } - return { - WeakRef: global.WeakRef || CompatWeakRef, - FinalizationRegistry: global.FinalizationRegistry || CompatFinalizer + if (removeContent && util.headerNameToString(header).startsWith('content-')) { + return true + } + if (unknownOrigin && (header.length === 13 || header.length === 6 || header.length === 19)) { + const name = util.headerNameToString(header) + return name === 'authorization' || name === 'cookie' || name === 'proxy-authorization' } + return false } - -/***/ }), - -/***/ 4240: -/***/ ((module) => { - -"use strict"; - - -// https://wicg.github.io/cookie-store/#cookie-maximum-attribute-value-size -const maxAttributeValueSize = 1024 - -// https://wicg.github.io/cookie-store/#cookie-maximum-name-value-pair-size -const maxNameValuePairSize = 4096 - -module.exports = { - maxAttributeValueSize, - maxNameValuePairSize +// https://tools.ietf.org/html/rfc7231#section-6.4 +function cleanRequestHeaders (headers, removeContent, unknownOrigin) { + const ret = [] + if (Array.isArray(headers)) { + for (let i = 0; i < headers.length; i += 2) { + if (!shouldRemoveHeader(headers[i], removeContent, unknownOrigin)) { + ret.push(headers[i], headers[i + 1]) + } + } + } else if (headers && typeof headers === 'object') { + for (const key of Object.keys(headers)) { + if (!shouldRemoveHeader(key, removeContent, unknownOrigin)) { + ret.push(key, headers[key]) + } + } + } else { + assert(headers == null, 'headers must be an object or an array') + } + return ret } +module.exports = RedirectHandler + /***/ }), -/***/ 1433: +/***/ 1838: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; +const assert = __nccwpck_require__(4589) -const { parseSetCookie } = __nccwpck_require__(7726) -const { stringify } = __nccwpck_require__(8033) -const { webidl } = __nccwpck_require__(8201) -const { Headers } = __nccwpck_require__(3640) +const { kRetryHandlerDefaultRetry } = __nccwpck_require__(7417) +const { RequestRetryError } = __nccwpck_require__(329) +const { + isDisturbed, + parseHeaders, + parseRangeHeader, + wrapRequestBody +} = __nccwpck_require__(7234) -/** - * @typedef {Object} Cookie - * @property {string} name - * @property {string} value - * @property {Date|number|undefined} expires - * @property {number|undefined} maxAge - * @property {string|undefined} domain - * @property {string|undefined} path - * @property {boolean|undefined} secure - * @property {boolean|undefined} httpOnly - * @property {'Strict'|'Lax'|'None'} sameSite - * @property {string[]} unparsed - */ +function calculateRetryAfterHeader (retryAfter) { + const current = Date.now() + return new Date(retryAfter).getTime() - current +} -/** - * @param {Headers} headers - * @returns {Record} - */ -function getCookies (headers) { - webidl.argumentLengthCheck(arguments, 1, { header: 'getCookies' }) +class RetryHandler { + constructor (opts, handlers) { + const { retryOptions, ...dispatchOpts } = opts + const { + // Retry scoped + retry: retryFn, + maxRetries, + maxTimeout, + minTimeout, + timeoutFactor, + // Response scoped + methods, + errorCodes, + retryAfter, + statusCodes + } = retryOptions ?? {} - webidl.brandCheck(headers, Headers, { strict: false }) + this.dispatch = handlers.dispatch + this.handler = handlers.handler + this.opts = { ...dispatchOpts, body: wrapRequestBody(opts.body) } + this.abort = null + this.aborted = false + this.retryOpts = { + retry: retryFn ?? RetryHandler[kRetryHandlerDefaultRetry], + retryAfter: retryAfter ?? true, + maxTimeout: maxTimeout ?? 30 * 1000, // 30s, + minTimeout: minTimeout ?? 500, // .5s + timeoutFactor: timeoutFactor ?? 2, + maxRetries: maxRetries ?? 5, + // What errors we should retry + methods: methods ?? ['GET', 'HEAD', 'OPTIONS', 'PUT', 'DELETE', 'TRACE'], + // Indicates which errors to retry + statusCodes: statusCodes ?? [500, 502, 503, 504, 429], + // List of errors to retry + errorCodes: errorCodes ?? [ + 'ECONNRESET', + 'ECONNREFUSED', + 'ENOTFOUND', + 'ENETDOWN', + 'ENETUNREACH', + 'EHOSTDOWN', + 'EHOSTUNREACH', + 'EPIPE', + 'UND_ERR_SOCKET' + ] + } - const cookie = headers.get('cookie') - const out = {} + this.retryCount = 0 + this.retryCountCheckpoint = 0 + this.start = 0 + this.end = null + this.etag = null + this.resume = null - if (!cookie) { - return out + // Handle possible onConnect duplication + this.handler.onConnect(reason => { + this.aborted = true + if (this.abort) { + this.abort(reason) + } else { + this.reason = reason + } + }) } - for (const piece of cookie.split(';')) { - const [name, ...value] = piece.split('=') - - out[name.trim()] = value.join('=') + onRequestSent () { + if (this.handler.onRequestSent) { + this.handler.onRequestSent() + } } - return out -} + onUpgrade (statusCode, headers, socket) { + if (this.handler.onUpgrade) { + this.handler.onUpgrade(statusCode, headers, socket) + } + } -/** - * @param {Headers} headers - * @param {string} name - * @param {{ path?: string, domain?: string }|undefined} attributes - * @returns {void} - */ -function deleteCookie (headers, name, attributes) { - webidl.argumentLengthCheck(arguments, 2, { header: 'deleteCookie' }) + onConnect (abort) { + if (this.aborted) { + abort(this.reason) + } else { + this.abort = abort + } + } - webidl.brandCheck(headers, Headers, { strict: false }) + onBodySent (chunk) { + if (this.handler.onBodySent) return this.handler.onBodySent(chunk) + } - name = webidl.converters.DOMString(name) - attributes = webidl.converters.DeleteCookieAttributes(attributes) + static [kRetryHandlerDefaultRetry] (err, { state, opts }, cb) { + const { statusCode, code, headers } = err + const { method, retryOptions } = opts + const { + maxRetries, + minTimeout, + maxTimeout, + timeoutFactor, + statusCodes, + errorCodes, + methods + } = retryOptions + const { counter } = state - // Matches behavior of - // https://github.com/denoland/deno_std/blob/63827b16330b82489a04614027c33b7904e08be5/http/cookie.ts#L278 - setCookie(headers, { - name, - value: '', - expires: new Date(0), - ...attributes - }) -} + // Any code that is not a Undici's originated and allowed to retry + if (code && code !== 'UND_ERR_REQ_RETRY' && !errorCodes.includes(code)) { + cb(err) + return + } -/** - * @param {Headers} headers - * @returns {Cookie[]} - */ -function getSetCookies (headers) { - webidl.argumentLengthCheck(arguments, 1, { header: 'getSetCookies' }) + // If a set of method are provided and the current method is not in the list + if (Array.isArray(methods) && !methods.includes(method)) { + cb(err) + return + } - webidl.brandCheck(headers, Headers, { strict: false }) + // If a set of status code are provided and the current status code is not in the list + if ( + statusCode != null && + Array.isArray(statusCodes) && + !statusCodes.includes(statusCode) + ) { + cb(err) + return + } - const cookies = headers.getSetCookie() + // If we reached the max number of retries + if (counter > maxRetries) { + cb(err) + return + } - if (!cookies) { - return [] - } + let retryAfterHeader = headers?.['retry-after'] + if (retryAfterHeader) { + retryAfterHeader = Number(retryAfterHeader) + retryAfterHeader = Number.isNaN(retryAfterHeader) + ? calculateRetryAfterHeader(retryAfterHeader) + : retryAfterHeader * 1e3 // Retry-After is in seconds + } - return cookies.map((pair) => parseSetCookie(pair)) -} + const retryTimeout = + retryAfterHeader > 0 + ? Math.min(retryAfterHeader, maxTimeout) + : Math.min(minTimeout * timeoutFactor ** (counter - 1), maxTimeout) -/** - * @param {Headers} headers - * @param {Cookie} cookie - * @returns {void} - */ -function setCookie (headers, cookie) { - webidl.argumentLengthCheck(arguments, 2, { header: 'setCookie' }) + setTimeout(() => cb(null), retryTimeout) + } - webidl.brandCheck(headers, Headers, { strict: false }) + onHeaders (statusCode, rawHeaders, resume, statusMessage) { + const headers = parseHeaders(rawHeaders) - cookie = webidl.converters.Cookie(cookie) + this.retryCount += 1 - const str = stringify(cookie) + if (statusCode >= 300) { + if (this.retryOpts.statusCodes.includes(statusCode) === false) { + return this.handler.onHeaders( + statusCode, + rawHeaders, + resume, + statusMessage + ) + } else { + this.abort( + new RequestRetryError('Request failed', statusCode, { + headers, + data: { + count: this.retryCount + } + }) + ) + return false + } + } - if (str) { - headers.append('Set-Cookie', stringify(cookie)) - } -} + // Checkpoint for resume from where we left it + if (this.resume != null) { + this.resume = null -webidl.converters.DeleteCookieAttributes = webidl.dictionaryConverter([ - { - converter: webidl.nullableConverter(webidl.converters.DOMString), - key: 'path', - defaultValue: null - }, - { - converter: webidl.nullableConverter(webidl.converters.DOMString), - key: 'domain', - defaultValue: null - } -]) + // Only Partial Content 206 supposed to provide Content-Range, + // any other status code that partially consumed the payload + // should not be retry because it would result in downstream + // wrongly concatanete multiple responses. + if (statusCode !== 206 && (this.start > 0 || statusCode !== 200)) { + this.abort( + new RequestRetryError('server does not support the range header and the payload was partially consumed', statusCode, { + headers, + data: { count: this.retryCount } + }) + ) + return false + } -webidl.converters.Cookie = webidl.dictionaryConverter([ - { - converter: webidl.converters.DOMString, - key: 'name' - }, - { - converter: webidl.converters.DOMString, - key: 'value' - }, - { - converter: webidl.nullableConverter((value) => { - if (typeof value === 'number') { - return webidl.converters['unsigned long long'](value) + const contentRange = parseRangeHeader(headers['content-range']) + // If no content range + if (!contentRange) { + this.abort( + new RequestRetryError('Content-Range mismatch', statusCode, { + headers, + data: { count: this.retryCount } + }) + ) + return false } - return new Date(value) - }), - key: 'expires', - defaultValue: null - }, - { - converter: webidl.nullableConverter(webidl.converters['long long']), - key: 'maxAge', - defaultValue: null - }, - { - converter: webidl.nullableConverter(webidl.converters.DOMString), - key: 'domain', - defaultValue: null - }, - { - converter: webidl.nullableConverter(webidl.converters.DOMString), - key: 'path', - defaultValue: null - }, - { - converter: webidl.nullableConverter(webidl.converters.boolean), - key: 'secure', - defaultValue: null - }, - { - converter: webidl.nullableConverter(webidl.converters.boolean), - key: 'httpOnly', - defaultValue: null - }, - { - converter: webidl.converters.USVString, - key: 'sameSite', - allowedValues: ['Strict', 'Lax', 'None'] - }, - { - converter: webidl.sequenceConverter(webidl.converters.DOMString), - key: 'unparsed', - defaultValue: [] - } -]) + // Let's start with a weak etag check + if (this.etag != null && this.etag !== headers.etag) { + this.abort( + new RequestRetryError('ETag mismatch', statusCode, { + headers, + data: { count: this.retryCount } + }) + ) + return false + } -module.exports = { - getCookies, - deleteCookie, - getSetCookies, - setCookie -} + const { start, size, end = size - 1 } = contentRange + assert(this.start === start, 'content-range mismatch') + assert(this.end == null || this.end === end, 'content-range mismatch') -/***/ }), + this.resume = resume + return true + } -/***/ 7726: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + if (this.end == null) { + if (statusCode === 206) { + // First time we receive 206 + const range = parseRangeHeader(headers['content-range']) -"use strict"; + if (range == null) { + return this.handler.onHeaders( + statusCode, + rawHeaders, + resume, + statusMessage + ) + } + const { start, size, end = size - 1 } = range + assert( + start != null && Number.isFinite(start), + 'content-range mismatch' + ) + assert(end != null && Number.isFinite(end), 'invalid content-length') -const { maxNameValuePairSize, maxAttributeValueSize } = __nccwpck_require__(4240) -const { isCTLExcludingHtab } = __nccwpck_require__(8033) -const { collectASequenceOfCodePointsFast } = __nccwpck_require__(4955) -const assert = __nccwpck_require__(2613) + this.start = start + this.end = end + } -/** - * @description Parses the field-value attributes of a set-cookie header string. - * @see https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4 - * @param {string} header - * @returns if the header is invalid, null will be returned - */ -function parseSetCookie (header) { - // 1. If the set-cookie-string contains a %x00-08 / %x0A-1F / %x7F - // character (CTL characters excluding HTAB): Abort these steps and - // ignore the set-cookie-string entirely. - if (isCTLExcludingHtab(header)) { - return null - } + // We make our best to checkpoint the body for further range headers + if (this.end == null) { + const contentLength = headers['content-length'] + this.end = contentLength != null ? Number(contentLength) - 1 : null + } - let nameValuePair = '' - let unparsedAttributes = '' - let name = '' - let value = '' + assert(Number.isFinite(this.start)) + assert( + this.end == null || Number.isFinite(this.end), + 'invalid content-length' + ) - // 2. If the set-cookie-string contains a %x3B (";") character: - if (header.includes(';')) { - // 1. The name-value-pair string consists of the characters up to, - // but not including, the first %x3B (";"), and the unparsed- - // attributes consist of the remainder of the set-cookie-string - // (including the %x3B (";") in question). - const position = { position: 0 } + this.resume = resume + this.etag = headers.etag != null ? headers.etag : null - nameValuePair = collectASequenceOfCodePointsFast(';', header, position) - unparsedAttributes = header.slice(position.position) - } else { - // Otherwise: + // Weak etags are not useful for comparison nor cache + // for instance not safe to assume if the response is byte-per-byte + // equal + if (this.etag != null && this.etag.startsWith('W/')) { + this.etag = null + } - // 1. The name-value-pair string consists of all the characters - // contained in the set-cookie-string, and the unparsed- - // attributes is the empty string. - nameValuePair = header - } + return this.handler.onHeaders( + statusCode, + rawHeaders, + resume, + statusMessage + ) + } - // 3. If the name-value-pair string lacks a %x3D ("=") character, then - // the name string is empty, and the value string is the value of - // name-value-pair. - if (!nameValuePair.includes('=')) { - value = nameValuePair - } else { - // Otherwise, the name string consists of the characters up to, but - // not including, the first %x3D ("=") character, and the (possibly - // empty) value string consists of the characters after the first - // %x3D ("=") character. - const position = { position: 0 } - name = collectASequenceOfCodePointsFast( - '=', - nameValuePair, - position - ) - value = nameValuePair.slice(position.position + 1) - } + const err = new RequestRetryError('Request failed', statusCode, { + headers, + data: { count: this.retryCount } + }) - // 4. Remove any leading or trailing WSP characters from the name - // string and the value string. - name = name.trim() - value = value.trim() + this.abort(err) - // 5. If the sum of the lengths of the name string and the value string - // is more than 4096 octets, abort these steps and ignore the set- - // cookie-string entirely. - if (name.length + value.length > maxNameValuePairSize) { - return null + return false } - // 6. The cookie-name is the name string, and the cookie-value is the - // value string. - return { - name, value, ...parseUnparsedAttributes(unparsedAttributes) + onData (chunk) { + this.start += chunk.length + + return this.handler.onData(chunk) } -} -/** - * Parses the remaining attributes of a set-cookie header - * @see https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4 - * @param {string} unparsedAttributes - * @param {[Object.]={}} cookieAttributeList - */ -function parseUnparsedAttributes (unparsedAttributes, cookieAttributeList = {}) { - // 1. If the unparsed-attributes string is empty, skip the rest of - // these steps. - if (unparsedAttributes.length === 0) { - return cookieAttributeList + onComplete (rawTrailers) { + this.retryCount = 0 + return this.handler.onComplete(rawTrailers) } - // 2. Discard the first character of the unparsed-attributes (which - // will be a %x3B (";") character). - assert(unparsedAttributes[0] === ';') - unparsedAttributes = unparsedAttributes.slice(1) + onError (err) { + if (this.aborted || isDisturbed(this.opts.body)) { + return this.handler.onError(err) + } - let cookieAv = '' + // We reconcile in case of a mix between network errors + // and server error response + if (this.retryCount - this.retryCountCheckpoint > 0) { + // We count the difference between the last checkpoint and the current retry count + this.retryCount = + this.retryCountCheckpoint + + (this.retryCount - this.retryCountCheckpoint) + } else { + this.retryCount += 1 + } - // 3. If the remaining unparsed-attributes contains a %x3B (";") - // character: - if (unparsedAttributes.includes(';')) { - // 1. Consume the characters of the unparsed-attributes up to, but - // not including, the first %x3B (";") character. - cookieAv = collectASequenceOfCodePointsFast( - ';', - unparsedAttributes, - { position: 0 } + this.retryOpts.retry( + err, + { + state: { counter: this.retryCount }, + opts: { retryOptions: this.retryOpts, ...this.opts } + }, + onRetry.bind(this) ) - unparsedAttributes = unparsedAttributes.slice(cookieAv.length) - } else { - // Otherwise: - // 1. Consume the remainder of the unparsed-attributes. - cookieAv = unparsedAttributes - unparsedAttributes = '' + function onRetry (err) { + if (err != null || this.aborted || isDisturbed(this.opts.body)) { + return this.handler.onError(err) + } + + if (this.start !== 0) { + const headers = { range: `bytes=${this.start}-${this.end ?? ''}` } + + // Weak etag check - weak etags will make comparison algorithms never match + if (this.etag != null) { + headers['if-match'] = this.etag + } + + this.opts = { + ...this.opts, + headers: { + ...this.opts.headers, + ...headers + } + } + } + + try { + this.retryCountCheckpoint = this.retryCount + this.dispatch(this.opts, this) + } catch (err) { + this.handler.onError(err) + } + } } +} - // Let the cookie-av string be the characters consumed in this step. +module.exports = RetryHandler - let attributeName = '' - let attributeValue = '' - // 4. If the cookie-av string contains a %x3D ("=") character: - if (cookieAv.includes('=')) { - // 1. The (possibly empty) attribute-name string consists of the - // characters up to, but not including, the first %x3D ("=") - // character, and the (possibly empty) attribute-value string - // consists of the characters after the first %x3D ("=") - // character. - const position = { position: 0 } +/***/ }), - attributeName = collectASequenceOfCodePointsFast( - '=', - cookieAv, - position - ) - attributeValue = cookieAv.slice(position.position + 1) - } else { - // Otherwise: - - // 1. The attribute-name string consists of the entire cookie-av - // string, and the attribute-value string is empty. - attributeName = cookieAv - } - - // 5. Remove any leading or trailing WSP characters from the attribute- - // name string and the attribute-value string. - attributeName = attributeName.trim() - attributeValue = attributeValue.trim() +/***/ 1386: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - // 6. If the attribute-value is longer than 1024 octets, ignore the - // cookie-av string and return to Step 1 of this algorithm. - if (attributeValue.length > maxAttributeValueSize) { - return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList) - } - // 7. Process the attribute-name and attribute-value according to the - // requirements in the following subsections. (Notice that - // attributes with unrecognized attribute-names are ignored.) - const attributeNameLowercase = attributeName.toLowerCase() +const { isIP } = __nccwpck_require__(7030) +const { lookup } = __nccwpck_require__(610) +const DecoratorHandler = __nccwpck_require__(6541) +const { InvalidArgumentError, InformationalError } = __nccwpck_require__(329) +const maxInt = Math.pow(2, 31) - 1 - // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.1 - // If the attribute-name case-insensitively matches the string - // "Expires", the user agent MUST process the cookie-av as follows. - if (attributeNameLowercase === 'expires') { - // 1. Let the expiry-time be the result of parsing the attribute-value - // as cookie-date (see Section 5.1.1). - const expiryTime = new Date(attributeValue) +class DNSInstance { + #maxTTL = 0 + #maxItems = 0 + #records = new Map() + dualStack = true + affinity = null + lookup = null + pick = null - // 2. If the attribute-value failed to parse as a cookie date, ignore - // the cookie-av. + constructor (opts) { + this.#maxTTL = opts.maxTTL + this.#maxItems = opts.maxItems + this.dualStack = opts.dualStack + this.affinity = opts.affinity + this.lookup = opts.lookup ?? this.#defaultLookup + this.pick = opts.pick ?? this.#defaultPick + } - cookieAttributeList.expires = expiryTime - } else if (attributeNameLowercase === 'max-age') { - // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.2 - // If the attribute-name case-insensitively matches the string "Max- - // Age", the user agent MUST process the cookie-av as follows. + get full () { + return this.#records.size === this.#maxItems + } - // 1. If the first character of the attribute-value is not a DIGIT or a - // "-" character, ignore the cookie-av. - const charCode = attributeValue.charCodeAt(0) + runLookup (origin, opts, cb) { + const ips = this.#records.get(origin.hostname) - if ((charCode < 48 || charCode > 57) && attributeValue[0] !== '-') { - return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList) + // If full, we just return the origin + if (ips == null && this.full) { + cb(null, origin.origin) + return } - // 2. If the remainder of attribute-value contains a non-DIGIT - // character, ignore the cookie-av. - if (!/^\d+$/.test(attributeValue)) { - return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList) + const newOpts = { + affinity: this.affinity, + dualStack: this.dualStack, + lookup: this.lookup, + pick: this.pick, + ...opts.dns, + maxTTL: this.#maxTTL, + maxItems: this.#maxItems } - // 3. Let delta-seconds be the attribute-value converted to an integer. - const deltaSeconds = Number(attributeValue) - - // 4. Let cookie-age-limit be the maximum age of the cookie (which - // SHOULD be 400 days or less, see Section 4.1.2.2). + // If no IPs we lookup + if (ips == null) { + this.lookup(origin, newOpts, (err, addresses) => { + if (err || addresses == null || addresses.length === 0) { + cb(err ?? new InformationalError('No DNS entries found')) + return + } - // 5. Set delta-seconds to the smaller of its present value and cookie- - // age-limit. - // deltaSeconds = Math.min(deltaSeconds * 1000, maxExpiresMs) + this.setRecords(origin, addresses) + const records = this.#records.get(origin.hostname) - // 6. If delta-seconds is less than or equal to zero (0), let expiry- - // time be the earliest representable date and time. Otherwise, let - // the expiry-time be the current date and time plus delta-seconds - // seconds. - // const expiryTime = deltaSeconds <= 0 ? Date.now() : Date.now() + deltaSeconds + const ip = this.pick( + origin, + records, + newOpts.affinity + ) - // 7. Append an attribute to the cookie-attribute-list with an - // attribute-name of Max-Age and an attribute-value of expiry-time. - cookieAttributeList.maxAge = deltaSeconds - } else if (attributeNameLowercase === 'domain') { - // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.3 - // If the attribute-name case-insensitively matches the string "Domain", - // the user agent MUST process the cookie-av as follows. + let port + if (typeof ip.port === 'number') { + port = `:${ip.port}` + } else if (origin.port !== '') { + port = `:${origin.port}` + } else { + port = '' + } - // 1. Let cookie-domain be the attribute-value. - let cookieDomain = attributeValue + cb( + null, + `${origin.protocol}//${ + ip.family === 6 ? `[${ip.address}]` : ip.address + }${port}` + ) + }) + } else { + // If there's IPs we pick + const ip = this.pick( + origin, + ips, + newOpts.affinity + ) - // 2. If cookie-domain starts with %x2E ("."), let cookie-domain be - // cookie-domain without its leading %x2E ("."). - if (cookieDomain[0] === '.') { - cookieDomain = cookieDomain.slice(1) - } + // If no IPs we lookup - deleting old records + if (ip == null) { + this.#records.delete(origin.hostname) + this.runLookup(origin, opts, cb) + return + } - // 3. Convert the cookie-domain to lower case. - cookieDomain = cookieDomain.toLowerCase() + let port + if (typeof ip.port === 'number') { + port = `:${ip.port}` + } else if (origin.port !== '') { + port = `:${origin.port}` + } else { + port = '' + } - // 4. Append an attribute to the cookie-attribute-list with an - // attribute-name of Domain and an attribute-value of cookie-domain. - cookieAttributeList.domain = cookieDomain - } else if (attributeNameLowercase === 'path') { - // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.4 - // If the attribute-name case-insensitively matches the string "Path", - // the user agent MUST process the cookie-av as follows. + cb( + null, + `${origin.protocol}//${ + ip.family === 6 ? `[${ip.address}]` : ip.address + }${port}` + ) + } + } - // 1. If the attribute-value is empty or if the first character of the - // attribute-value is not %x2F ("/"): - let cookiePath = '' - if (attributeValue.length === 0 || attributeValue[0] !== '/') { - // 1. Let cookie-path be the default-path. - cookiePath = '/' - } else { - // Otherwise: + #defaultLookup (origin, opts, cb) { + lookup( + origin.hostname, + { + all: true, + family: this.dualStack === false ? this.affinity : 0, + order: 'ipv4first' + }, + (err, addresses) => { + if (err) { + return cb(err) + } - // 1. Let cookie-path be the attribute-value. - cookiePath = attributeValue - } + const results = new Map() - // 2. Append an attribute to the cookie-attribute-list with an - // attribute-name of Path and an attribute-value of cookie-path. - cookieAttributeList.path = cookiePath - } else if (attributeNameLowercase === 'secure') { - // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.5 - // If the attribute-name case-insensitively matches the string "Secure", - // the user agent MUST append an attribute to the cookie-attribute-list - // with an attribute-name of Secure and an empty attribute-value. + for (const addr of addresses) { + // On linux we found duplicates, we attempt to remove them with + // the latest record + results.set(`${addr.address}:${addr.family}`, addr) + } - cookieAttributeList.secure = true - } else if (attributeNameLowercase === 'httponly') { - // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.6 - // If the attribute-name case-insensitively matches the string - // "HttpOnly", the user agent MUST append an attribute to the cookie- - // attribute-list with an attribute-name of HttpOnly and an empty - // attribute-value. + cb(null, results.values()) + } + ) + } - cookieAttributeList.httpOnly = true - } else if (attributeNameLowercase === 'samesite') { - // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.7 - // If the attribute-name case-insensitively matches the string - // "SameSite", the user agent MUST process the cookie-av as follows: + #defaultPick (origin, hostnameRecords, affinity) { + let ip = null + const { records, offset } = hostnameRecords - // 1. Let enforcement be "Default". - let enforcement = 'Default' + let family + if (this.dualStack) { + if (affinity == null) { + // Balance between ip families + if (offset == null || offset === maxInt) { + hostnameRecords.offset = 0 + affinity = 4 + } else { + hostnameRecords.offset++ + affinity = (hostnameRecords.offset & 1) === 1 ? 6 : 4 + } + } - const attributeValueLowercase = attributeValue.toLowerCase() - // 2. If cookie-av's attribute-value is a case-insensitive match for - // "None", set enforcement to "None". - if (attributeValueLowercase.includes('none')) { - enforcement = 'None' + if (records[affinity] != null && records[affinity].ips.length > 0) { + family = records[affinity] + } else { + family = records[affinity === 4 ? 6 : 4] + } + } else { + family = records[affinity] } - // 3. If cookie-av's attribute-value is a case-insensitive match for - // "Strict", set enforcement to "Strict". - if (attributeValueLowercase.includes('strict')) { - enforcement = 'Strict' + // If no IPs we return null + if (family == null || family.ips.length === 0) { + return ip } - // 4. If cookie-av's attribute-value is a case-insensitive match for - // "Lax", set enforcement to "Lax". - if (attributeValueLowercase.includes('lax')) { - enforcement = 'Lax' + if (family.offset == null || family.offset === maxInt) { + family.offset = 0 + } else { + family.offset++ } - // 5. Append an attribute to the cookie-attribute-list with an - // attribute-name of "SameSite" and an attribute-value of - // enforcement. - cookieAttributeList.sameSite = enforcement - } else { - cookieAttributeList.unparsed ??= [] - - cookieAttributeList.unparsed.push(`${attributeName}=${attributeValue}`) - } - - // 8. Return to Step 1 of this algorithm. - return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList) -} + const position = family.offset % family.ips.length + ip = family.ips[position] ?? null -module.exports = { - parseSetCookie, - parseUnparsedAttributes -} + if (ip == null) { + return ip + } + if (Date.now() - ip.timestamp > ip.ttl) { // record TTL is already in ms + // We delete expired records + // It is possible that they have different TTL, so we manage them individually + family.ips.splice(position, 1) + return this.pick(origin, hostnameRecords, affinity) + } -/***/ }), + return ip + } -/***/ 8033: -/***/ ((module) => { + setRecords (origin, addresses) { + const timestamp = Date.now() + const records = { records: { 4: null, 6: null } } + for (const record of addresses) { + record.timestamp = timestamp + if (typeof record.ttl === 'number') { + // The record TTL is expected to be in ms + record.ttl = Math.min(record.ttl, this.#maxTTL) + } else { + record.ttl = this.#maxTTL + } -"use strict"; + const familyRecords = records.records[record.family] ?? { ips: [] } + familyRecords.ips.push(record) + records.records[record.family] = familyRecords + } -/** - * @param {string} value - * @returns {boolean} - */ -function isCTLExcludingHtab (value) { - if (value.length === 0) { - return false + this.#records.set(origin.hostname, records) } - for (const char of value) { - const code = char.charCodeAt(0) - - if ( - (code >= 0x00 || code <= 0x08) || - (code >= 0x0A || code <= 0x1F) || - code === 0x7F - ) { - return false - } + getHandler (meta, opts) { + return new DNSDispatchHandler(this, meta, opts) } } -/** - CHAR = - token = 1* - separators = "(" | ")" | "<" | ">" | "@" - | "," | ";" | ":" | "\" | <"> - | "/" | "[" | "]" | "?" | "=" - | "{" | "}" | SP | HT - * @param {string} name - */ -function validateCookieName (name) { - for (const char of name) { - const code = char.charCodeAt(0) +class DNSDispatchHandler extends DecoratorHandler { + #state = null + #opts = null + #dispatch = null + #handler = null + #origin = null - if ( - (code <= 0x20 || code > 0x7F) || - char === '(' || - char === ')' || - char === '>' || - char === '<' || - char === '@' || - char === ',' || - char === ';' || - char === ':' || - char === '\\' || - char === '"' || - char === '/' || - char === '[' || - char === ']' || - char === '?' || - char === '=' || - char === '{' || - char === '}' - ) { - throw new Error('Invalid cookie name') - } + constructor (state, { origin, handler, dispatch }, opts) { + super(handler) + this.#origin = origin + this.#handler = handler + this.#opts = { ...opts } + this.#state = state + this.#dispatch = dispatch } -} -/** - cookie-value = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE ) - cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E - ; US-ASCII characters excluding CTLs, - ; whitespace DQUOTE, comma, semicolon, - ; and backslash - * @param {string} value - */ -function validateCookieValue (value) { - for (const char of value) { - const code = char.charCodeAt(0) + onError (err) { + switch (err.code) { + case 'ETIMEDOUT': + case 'ECONNREFUSED': { + if (this.#state.dualStack) { + // We delete the record and retry + this.#state.runLookup(this.#origin, this.#opts, (err, newOrigin) => { + if (err) { + return this.#handler.onError(err) + } - if ( - code < 0x21 || // exclude CTLs (0-31) - code === 0x22 || - code === 0x2C || - code === 0x3B || - code === 0x5C || - code > 0x7E // non-ascii - ) { - throw new Error('Invalid header value') - } - } -} + const dispatchOpts = { + ...this.#opts, + origin: newOrigin + } -/** - * path-value = - * @param {string} path - */ -function validateCookiePath (path) { - for (const char of path) { - const code = char.charCodeAt(0) + this.#dispatch(dispatchOpts, this) + }) - if (code < 0x21 || char === ';') { - throw new Error('Invalid cookie path') + // if dual-stack disabled, we error out + return + } + + this.#handler.onError(err) + return + } + case 'ENOTFOUND': + this.#state.deleteRecord(this.#origin) + // eslint-disable-next-line no-fallthrough + default: + this.#handler.onError(err) + break } } } -/** - * I have no idea why these values aren't allowed to be honest, - * but Deno tests these. - Khafra - * @param {string} domain - */ -function validateCookieDomain (domain) { +module.exports = interceptorOpts => { if ( - domain.startsWith('-') || - domain.endsWith('.') || - domain.endsWith('-') + interceptorOpts?.maxTTL != null && + (typeof interceptorOpts?.maxTTL !== 'number' || interceptorOpts?.maxTTL < 0) ) { - throw new Error('Invalid cookie domain') + throw new InvalidArgumentError('Invalid maxTTL. Must be a positive number') } -} -/** - * @see https://www.rfc-editor.org/rfc/rfc7231#section-7.1.1.1 - * @param {number|Date} date - IMF-fixdate = day-name "," SP date1 SP time-of-day SP GMT - ; fixed length/zone/capitalization subset of the format - ; see Section 3.3 of [RFC5322] + if ( + interceptorOpts?.maxItems != null && + (typeof interceptorOpts?.maxItems !== 'number' || + interceptorOpts?.maxItems < 1) + ) { + throw new InvalidArgumentError( + 'Invalid maxItems. Must be a positive number and greater than zero' + ) + } - day-name = %x4D.6F.6E ; "Mon", case-sensitive - / %x54.75.65 ; "Tue", case-sensitive - / %x57.65.64 ; "Wed", case-sensitive - / %x54.68.75 ; "Thu", case-sensitive - / %x46.72.69 ; "Fri", case-sensitive - / %x53.61.74 ; "Sat", case-sensitive - / %x53.75.6E ; "Sun", case-sensitive - date1 = day SP month SP year - ; e.g., 02 Jun 1982 + if ( + interceptorOpts?.affinity != null && + interceptorOpts?.affinity !== 4 && + interceptorOpts?.affinity !== 6 + ) { + throw new InvalidArgumentError('Invalid affinity. Must be either 4 or 6') + } - day = 2DIGIT - month = %x4A.61.6E ; "Jan", case-sensitive - / %x46.65.62 ; "Feb", case-sensitive - / %x4D.61.72 ; "Mar", case-sensitive - / %x41.70.72 ; "Apr", case-sensitive - / %x4D.61.79 ; "May", case-sensitive - / %x4A.75.6E ; "Jun", case-sensitive - / %x4A.75.6C ; "Jul", case-sensitive - / %x41.75.67 ; "Aug", case-sensitive - / %x53.65.70 ; "Sep", case-sensitive - / %x4F.63.74 ; "Oct", case-sensitive - / %x4E.6F.76 ; "Nov", case-sensitive - / %x44.65.63 ; "Dec", case-sensitive - year = 4DIGIT + if ( + interceptorOpts?.dualStack != null && + typeof interceptorOpts?.dualStack !== 'boolean' + ) { + throw new InvalidArgumentError('Invalid dualStack. Must be a boolean') + } - GMT = %x47.4D.54 ; "GMT", case-sensitive + if ( + interceptorOpts?.lookup != null && + typeof interceptorOpts?.lookup !== 'function' + ) { + throw new InvalidArgumentError('Invalid lookup. Must be a function') + } - time-of-day = hour ":" minute ":" second - ; 00:00:00 - 23:59:60 (leap second) + if ( + interceptorOpts?.pick != null && + typeof interceptorOpts?.pick !== 'function' + ) { + throw new InvalidArgumentError('Invalid pick. Must be a function') + } - hour = 2DIGIT - minute = 2DIGIT - second = 2DIGIT - */ -function toIMFDate (date) { - if (typeof date === 'number') { - date = new Date(date) + const dualStack = interceptorOpts?.dualStack ?? true + let affinity + if (dualStack) { + affinity = interceptorOpts?.affinity ?? null + } else { + affinity = interceptorOpts?.affinity ?? 4 } - const days = [ - 'Sun', 'Mon', 'Tue', 'Wed', - 'Thu', 'Fri', 'Sat' - ] + const opts = { + maxTTL: interceptorOpts?.maxTTL ?? 10e3, // Expressed in ms + lookup: interceptorOpts?.lookup ?? null, + pick: interceptorOpts?.pick ?? null, + dualStack, + affinity, + maxItems: interceptorOpts?.maxItems ?? Infinity + } - const months = [ - 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', - 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' - ] + const instance = new DNSInstance(opts) - const dayName = days[date.getUTCDay()] - const day = date.getUTCDate().toString().padStart(2, '0') - const month = months[date.getUTCMonth()] - const year = date.getUTCFullYear() - const hour = date.getUTCHours().toString().padStart(2, '0') - const minute = date.getUTCMinutes().toString().padStart(2, '0') - const second = date.getUTCSeconds().toString().padStart(2, '0') + return dispatch => { + return function dnsInterceptor (origDispatchOpts, handler) { + const origin = + origDispatchOpts.origin.constructor === URL + ? origDispatchOpts.origin + : new URL(origDispatchOpts.origin) - return `${dayName}, ${day} ${month} ${year} ${hour}:${minute}:${second} GMT` -} + if (isIP(origin.hostname) !== 0) { + return dispatch(origDispatchOpts, handler) + } -/** - max-age-av = "Max-Age=" non-zero-digit *DIGIT - ; In practice, both expires-av and max-age-av - ; are limited to dates representable by the - ; user agent. - * @param {number} maxAge - */ -function validateCookieMaxAge (maxAge) { - if (maxAge < 0) { - throw new Error('Invalid cookie max-age') - } -} - -/** - * @see https://www.rfc-editor.org/rfc/rfc6265#section-4.1.1 - * @param {import('./index').Cookie} cookie - */ -function stringify (cookie) { - if (cookie.name.length === 0) { - return null - } - - validateCookieName(cookie.name) - validateCookieValue(cookie.value) - - const out = [`${cookie.name}=${cookie.value}`] - - // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-cookie-prefixes-00#section-3.1 - // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-cookie-prefixes-00#section-3.2 - if (cookie.name.startsWith('__Secure-')) { - cookie.secure = true - } - - if (cookie.name.startsWith('__Host-')) { - cookie.secure = true - cookie.domain = null - cookie.path = '/' - } - - if (cookie.secure) { - out.push('Secure') - } - - if (cookie.httpOnly) { - out.push('HttpOnly') - } - - if (typeof cookie.maxAge === 'number') { - validateCookieMaxAge(cookie.maxAge) - out.push(`Max-Age=${cookie.maxAge}`) - } - - if (cookie.domain) { - validateCookieDomain(cookie.domain) - out.push(`Domain=${cookie.domain}`) - } - - if (cookie.path) { - validateCookiePath(cookie.path) - out.push(`Path=${cookie.path}`) - } + instance.runLookup(origin, origDispatchOpts, (err, newOrigin) => { + if (err) { + return handler.onError(err) + } - if (cookie.expires && cookie.expires.toString() !== 'Invalid Date') { - out.push(`Expires=${toIMFDate(cookie.expires)}`) - } + let dispatchOpts = null + dispatchOpts = { + ...origDispatchOpts, + servername: origin.hostname, // For SNI on TLS + origin: newOrigin, + headers: { + host: origin.hostname, + ...origDispatchOpts.headers + } + } - if (cookie.sameSite) { - out.push(`SameSite=${cookie.sameSite}`) - } + dispatch( + dispatchOpts, + instance.getHandler({ origin, dispatch, handler }, origDispatchOpts) + ) + }) - for (const part of cookie.unparsed) { - if (!part.includes('=')) { - throw new Error('Invalid unparsed') + return true } - - const [key, ...value] = part.split('=') - - out.push(`${key.trim()}=${value.join('=')}`) } - - return out.join('; ') -} - -module.exports = { - isCTLExcludingHtab, - validateCookieName, - validateCookiePath, - validateCookieValue, - toIMFDate, - stringify } /***/ }), -/***/ 9323: +/***/ 2546: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; - -const net = __nccwpck_require__(9278) -const assert = __nccwpck_require__(2613) -const util = __nccwpck_require__(5069) -const { InvalidArgumentError, ConnectTimeoutError } = __nccwpck_require__(6738) -let tls // include tls conditionally since it is not always available +const util = __nccwpck_require__(7234) +const { InvalidArgumentError, RequestAbortedError } = __nccwpck_require__(329) +const DecoratorHandler = __nccwpck_require__(6541) -// TODO: session re-use does not wait for the first -// connection to resolve the session and might therefore -// resolve the same servername multiple times even when -// re-use is enabled. +class DumpHandler extends DecoratorHandler { + #maxSize = 1024 * 1024 + #abort = null + #dumped = false + #aborted = false + #size = 0 + #reason = null + #handler = null -let SessionCache -// FIXME: remove workaround when the Node bug is fixed -// https://github.com/nodejs/node/issues/49344#issuecomment-1741776308 -if (global.FinalizationRegistry && !process.env.NODE_V8_COVERAGE) { - SessionCache = class WeakSessionCache { - constructor (maxCachedSessions) { - this._maxCachedSessions = maxCachedSessions - this._sessionCache = new Map() - this._sessionRegistry = new global.FinalizationRegistry((key) => { - if (this._sessionCache.size < this._maxCachedSessions) { - return - } + constructor ({ maxSize }, handler) { + super(handler) - const ref = this._sessionCache.get(key) - if (ref !== undefined && ref.deref() === undefined) { - this._sessionCache.delete(key) - } - }) + if (maxSize != null && (!Number.isFinite(maxSize) || maxSize < 1)) { + throw new InvalidArgumentError('maxSize must be a number greater than 0') } - get (sessionKey) { - const ref = this._sessionCache.get(sessionKey) - return ref ? ref.deref() : null - } + this.#maxSize = maxSize ?? this.#maxSize + this.#handler = handler + } - set (sessionKey, session) { - if (this._maxCachedSessions === 0) { - return - } + onConnect (abort) { + this.#abort = abort - this._sessionCache.set(sessionKey, new WeakRef(session)) - this._sessionRegistry.register(session, sessionKey) - } + this.#handler.onConnect(this.#customAbort.bind(this)) } -} else { - SessionCache = class SimpleSessionCache { - constructor (maxCachedSessions) { - this._maxCachedSessions = maxCachedSessions - this._sessionCache = new Map() - } - get (sessionKey) { - return this._sessionCache.get(sessionKey) - } + #customAbort (reason) { + this.#aborted = true + this.#reason = reason + } - set (sessionKey, session) { - if (this._maxCachedSessions === 0) { - return - } + // TODO: will require adjustment after new hooks are out + onHeaders (statusCode, rawHeaders, resume, statusMessage) { + const headers = util.parseHeaders(rawHeaders) + const contentLength = headers['content-length'] - if (this._sessionCache.size >= this._maxCachedSessions) { - // remove the oldest session - const { value: oldestKey } = this._sessionCache.keys().next() - this._sessionCache.delete(oldestKey) - } + if (contentLength != null && contentLength > this.#maxSize) { + throw new RequestAbortedError( + `Response size (${contentLength}) larger than maxSize (${ + this.#maxSize + })` + ) + } - this._sessionCache.set(sessionKey, session) + if (this.#aborted) { + return true } - } -} -function buildConnector ({ allowH2, maxCachedSessions, socketPath, timeout, ...opts }) { - if (maxCachedSessions != null && (!Number.isInteger(maxCachedSessions) || maxCachedSessions < 0)) { - throw new InvalidArgumentError('maxCachedSessions must be a positive integer or zero') + return this.#handler.onHeaders( + statusCode, + rawHeaders, + resume, + statusMessage + ) } - const options = { path: socketPath, ...opts } - const sessionCache = new SessionCache(maxCachedSessions == null ? 100 : maxCachedSessions) - timeout = timeout == null ? 10e3 : timeout - allowH2 = allowH2 != null ? allowH2 : false - return function connect ({ hostname, host, protocol, port, servername, localAddress, httpSocket }, callback) { - let socket - if (protocol === 'https:') { - if (!tls) { - tls = __nccwpck_require__(4756) - } - servername = servername || options.servername || util.getServerName(host) || null + onError (err) { + if (this.#dumped) { + return + } - const sessionKey = servername || hostname - const session = sessionCache.get(sessionKey) || null + err = this.#reason ?? err - assert(sessionKey) + this.#handler.onError(err) + } - socket = tls.connect({ - highWaterMark: 16384, // TLS in node can't have bigger HWM anyway... - ...options, - servername, - session, - localAddress, - // TODO(HTTP/2): Add support for h2c - ALPNProtocols: allowH2 ? ['http/1.1', 'h2'] : ['http/1.1'], - socket: httpSocket, // upgrade socket connection - port: port || 443, - host: hostname - }) + onData (chunk) { + this.#size = this.#size + chunk.length - socket - .on('session', function (session) { - // TODO (fix): Can a session become invalid once established? Don't think so? - sessionCache.set(sessionKey, session) - }) - } else { - assert(!httpSocket, 'httpSocket can only be sent on TLS update') - socket = net.connect({ - highWaterMark: 64 * 1024, // Same as nodejs fs streams. - ...options, - localAddress, - port: port || 80, - host: hostname - }) - } + if (this.#size >= this.#maxSize) { + this.#dumped = true - // Set TCP keep alive options on the socket here instead of in connect() for the case of assigning the socket - if (options.keepAlive == null || options.keepAlive) { - const keepAliveInitialDelay = options.keepAliveInitialDelay === undefined ? 60e3 : options.keepAliveInitialDelay - socket.setKeepAlive(true, keepAliveInitialDelay) + if (this.#aborted) { + this.#handler.onError(this.#reason) + } else { + this.#handler.onComplete([]) + } } - const cancelTimeout = setupTimeout(() => onConnectTimeout(socket), timeout) - - socket - .setNoDelay(true) - .once(protocol === 'https:' ? 'secureConnect' : 'connect', function () { - cancelTimeout() + return true + } - if (callback) { - const cb = callback - callback = null - cb(null, this) - } - }) - .on('error', function (err) { - cancelTimeout() + onComplete (trailers) { + if (this.#dumped) { + return + } - if (callback) { - const cb = callback - callback = null - cb(err) - } - }) + if (this.#aborted) { + this.#handler.onError(this.reason) + return + } - return socket + this.#handler.onComplete(trailers) } } -function setupTimeout (onConnectTimeout, timeout) { - if (!timeout) { - return () => {} +function createDumpInterceptor ( + { maxSize: defaultMaxSize } = { + maxSize: 1024 * 1024 } +) { + return dispatch => { + return function Intercept (opts, handler) { + const { dumpMaxSize = defaultMaxSize } = + opts - let s1 = null - let s2 = null - const timeoutId = setTimeout(() => { - // setImmediate is added to make sure that we priotorise socket error events over timeouts - s1 = setImmediate(() => { - if (process.platform === 'win32') { - // Windows needs an extra setImmediate probably due to implementation differences in the socket logic - s2 = setImmediate(() => onConnectTimeout()) - } else { - onConnectTimeout() - } - }) - }, timeout) - return () => { - clearTimeout(timeoutId) - clearImmediate(s1) - clearImmediate(s2) - } -} + const dumpHandler = new DumpHandler( + { maxSize: dumpMaxSize }, + handler + ) -function onConnectTimeout (socket) { - util.destroy(socket, new ConnectTimeoutError()) + return dispatch(opts, dumpHandler) + } + } } -module.exports = buildConnector +module.exports = createDumpInterceptor /***/ }), -/***/ 6356: -/***/ ((module) => { - -"use strict"; +/***/ 2642: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -/** @type {Record} */ -const headerNameLowerCasedRecord = {} -// https://developer.mozilla.org/docs/Web/HTTP/Headers -const wellknownHeaderNames = [ - 'Accept', - 'Accept-Encoding', - 'Accept-Language', - 'Accept-Ranges', - 'Access-Control-Allow-Credentials', - 'Access-Control-Allow-Headers', - 'Access-Control-Allow-Methods', - 'Access-Control-Allow-Origin', - 'Access-Control-Expose-Headers', - 'Access-Control-Max-Age', - 'Access-Control-Request-Headers', - 'Access-Control-Request-Method', - 'Age', - 'Allow', - 'Alt-Svc', - 'Alt-Used', - 'Authorization', - 'Cache-Control', - 'Clear-Site-Data', - 'Connection', - 'Content-Disposition', - 'Content-Encoding', - 'Content-Language', - 'Content-Length', - 'Content-Location', - 'Content-Range', - 'Content-Security-Policy', - 'Content-Security-Policy-Report-Only', - 'Content-Type', - 'Cookie', - 'Cross-Origin-Embedder-Policy', - 'Cross-Origin-Opener-Policy', - 'Cross-Origin-Resource-Policy', - 'Date', - 'Device-Memory', - 'Downlink', - 'ECT', - 'ETag', - 'Expect', - 'Expect-CT', - 'Expires', - 'Forwarded', - 'From', - 'Host', - 'If-Match', - 'If-Modified-Since', - 'If-None-Match', - 'If-Range', - 'If-Unmodified-Since', - 'Keep-Alive', - 'Last-Modified', - 'Link', - 'Location', - 'Max-Forwards', - 'Origin', - 'Permissions-Policy', - 'Pragma', - 'Proxy-Authenticate', - 'Proxy-Authorization', - 'RTT', - 'Range', - 'Referer', - 'Referrer-Policy', - 'Refresh', - 'Retry-After', - 'Sec-WebSocket-Accept', - 'Sec-WebSocket-Extensions', - 'Sec-WebSocket-Key', - 'Sec-WebSocket-Protocol', - 'Sec-WebSocket-Version', - 'Server', - 'Server-Timing', - 'Service-Worker-Allowed', - 'Service-Worker-Navigation-Preload', - 'Set-Cookie', - 'SourceMap', - 'Strict-Transport-Security', - 'Supports-Loading-Mode', - 'TE', - 'Timing-Allow-Origin', - 'Trailer', - 'Transfer-Encoding', - 'Upgrade', - 'Upgrade-Insecure-Requests', - 'User-Agent', - 'Vary', - 'Via', - 'WWW-Authenticate', - 'X-Content-Type-Options', - 'X-DNS-Prefetch-Control', - 'X-Frame-Options', - 'X-Permitted-Cross-Domain-Policies', - 'X-Powered-By', - 'X-Requested-With', - 'X-XSS-Protection' -] +const RedirectHandler = __nccwpck_require__(7608) -for (let i = 0; i < wellknownHeaderNames.length; ++i) { - const key = wellknownHeaderNames[i] - const lowerCasedKey = key.toLowerCase() - headerNameLowerCasedRecord[key] = headerNameLowerCasedRecord[lowerCasedKey] = - lowerCasedKey -} +function createRedirectInterceptor ({ maxRedirections: defaultMaxRedirections }) { + return (dispatch) => { + return function Intercept (opts, handler) { + const { maxRedirections = defaultMaxRedirections } = opts -// Note: object prototypes should not be able to be referenced. e.g. `Object#hasOwnProperty`. -Object.setPrototypeOf(headerNameLowerCasedRecord, null) + if (!maxRedirections) { + return dispatch(opts, handler) + } -module.exports = { - wellknownHeaderNames, - headerNameLowerCasedRecord + const redirectHandler = new RedirectHandler(dispatch, maxRedirections, opts, handler) + opts = { ...opts, maxRedirections: 0 } // Stop sub dispatcher from also redirecting. + return dispatch(opts, redirectHandler) + } + } } +module.exports = createRedirectInterceptor + /***/ }), -/***/ 6738: -/***/ ((module) => { +/***/ 3540: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; +const RedirectHandler = __nccwpck_require__(7608) -class UndiciError extends Error { - constructor (message) { - super(message) - this.name = 'UndiciError' - this.code = 'UND_ERR' - } -} +module.exports = opts => { + const globalMaxRedirections = opts?.maxRedirections + return dispatch => { + return function redirectInterceptor (opts, handler) { + const { maxRedirections = globalMaxRedirections, ...baseOpts } = opts -class ConnectTimeoutError extends UndiciError { - constructor (message) { - super(message) - Error.captureStackTrace(this, ConnectTimeoutError) - this.name = 'ConnectTimeoutError' - this.message = message || 'Connect Timeout Error' - this.code = 'UND_ERR_CONNECT_TIMEOUT' - } -} + if (!maxRedirections) { + return dispatch(opts, handler) + } -class HeadersTimeoutError extends UndiciError { - constructor (message) { - super(message) - Error.captureStackTrace(this, HeadersTimeoutError) - this.name = 'HeadersTimeoutError' - this.message = message || 'Headers Timeout Error' - this.code = 'UND_ERR_HEADERS_TIMEOUT' - } -} + const redirectHandler = new RedirectHandler( + dispatch, + maxRedirections, + opts, + handler + ) -class HeadersOverflowError extends UndiciError { - constructor (message) { - super(message) - Error.captureStackTrace(this, HeadersOverflowError) - this.name = 'HeadersOverflowError' - this.message = message || 'Headers Overflow Error' - this.code = 'UND_ERR_HEADERS_OVERFLOW' + return dispatch(baseOpts, redirectHandler) + } } } -class BodyTimeoutError extends UndiciError { - constructor (message) { - super(message) - Error.captureStackTrace(this, BodyTimeoutError) - this.name = 'BodyTimeoutError' - this.message = message || 'Body Timeout Error' - this.code = 'UND_ERR_BODY_TIMEOUT' - } -} -class ResponseStatusCodeError extends UndiciError { - constructor (message, statusCode, headers, body) { - super(message) - Error.captureStackTrace(this, ResponseStatusCodeError) - this.name = 'ResponseStatusCodeError' - this.message = message || 'Response Status Code Error' - this.code = 'UND_ERR_RESPONSE_STATUS_CODE' - this.body = body - this.status = statusCode - this.statusCode = statusCode - this.headers = headers - } -} +/***/ }), -class InvalidArgumentError extends UndiciError { - constructor (message) { - super(message) - Error.captureStackTrace(this, InvalidArgumentError) - this.name = 'InvalidArgumentError' - this.message = message || 'Invalid Argument Error' - this.code = 'UND_ERR_INVALID_ARG' - } -} +/***/ 3916: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -class InvalidReturnValueError extends UndiciError { - constructor (message) { - super(message) - Error.captureStackTrace(this, InvalidReturnValueError) - this.name = 'InvalidReturnValueError' - this.message = message || 'Invalid Return Value Error' - this.code = 'UND_ERR_INVALID_RETURN_VALUE' - } -} -class RequestAbortedError extends UndiciError { - constructor (message) { - super(message) - Error.captureStackTrace(this, RequestAbortedError) - this.name = 'AbortError' - this.message = message || 'Request aborted' - this.code = 'UND_ERR_ABORTED' - } -} +const RetryHandler = __nccwpck_require__(1838) -class InformationalError extends UndiciError { - constructor (message) { - super(message) - Error.captureStackTrace(this, InformationalError) - this.name = 'InformationalError' - this.message = message || 'Request information' - this.code = 'UND_ERR_INFO' +module.exports = globalOpts => { + return dispatch => { + return function retryInterceptor (opts, handler) { + return dispatch( + opts, + new RetryHandler( + { ...opts, retryOptions: { ...globalOpts, ...opts.retryOptions } }, + { + handler, + dispatch + } + ) + ) + } } } -class RequestContentLengthMismatchError extends UndiciError { - constructor (message) { - super(message) - Error.captureStackTrace(this, RequestContentLengthMismatchError) - this.name = 'RequestContentLengthMismatchError' - this.message = message || 'Request body length does not match content-length header' - this.code = 'UND_ERR_REQ_CONTENT_LENGTH_MISMATCH' - } -} -class ResponseContentLengthMismatchError extends UndiciError { - constructor (message) { - super(message) - Error.captureStackTrace(this, ResponseContentLengthMismatchError) - this.name = 'ResponseContentLengthMismatchError' - this.message = message || 'Response body length does not match content-length header' - this.code = 'UND_ERR_RES_CONTENT_LENGTH_MISMATCH' - } -} +/***/ }), -class ClientDestroyedError extends UndiciError { - constructor (message) { - super(message) - Error.captureStackTrace(this, ClientDestroyedError) - this.name = 'ClientDestroyedError' - this.message = message || 'The client is destroyed' - this.code = 'UND_ERR_DESTROYED' - } -} +/***/ 1114: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { -class ClientClosedError extends UndiciError { - constructor (message) { - super(message) - Error.captureStackTrace(this, ClientClosedError) - this.name = 'ClientClosedError' - this.message = message || 'The client is closed' - this.code = 'UND_ERR_CLOSED' - } -} -class SocketError extends UndiciError { - constructor (message, socket) { - super(message) - Error.captureStackTrace(this, SocketError) - this.name = 'SocketError' - this.message = message || 'Socket error' - this.code = 'UND_ERR_SOCKET' - this.socket = socket - } +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.SPECIAL_HEADERS = exports.HEADER_STATE = exports.MINOR = exports.MAJOR = exports.CONNECTION_TOKEN_CHARS = exports.HEADER_CHARS = exports.TOKEN = exports.STRICT_TOKEN = exports.HEX = exports.URL_CHAR = exports.STRICT_URL_CHAR = exports.USERINFO_CHARS = exports.MARK = exports.ALPHANUM = exports.NUM = exports.HEX_MAP = exports.NUM_MAP = exports.ALPHA = exports.FINISH = exports.H_METHOD_MAP = exports.METHOD_MAP = exports.METHODS_RTSP = exports.METHODS_ICE = exports.METHODS_HTTP = exports.METHODS = exports.LENIENT_FLAGS = exports.FLAGS = exports.TYPE = exports.ERROR = void 0; +const utils_1 = __nccwpck_require__(9298); +// C headers +var ERROR; +(function (ERROR) { + ERROR[ERROR["OK"] = 0] = "OK"; + ERROR[ERROR["INTERNAL"] = 1] = "INTERNAL"; + ERROR[ERROR["STRICT"] = 2] = "STRICT"; + ERROR[ERROR["LF_EXPECTED"] = 3] = "LF_EXPECTED"; + ERROR[ERROR["UNEXPECTED_CONTENT_LENGTH"] = 4] = "UNEXPECTED_CONTENT_LENGTH"; + ERROR[ERROR["CLOSED_CONNECTION"] = 5] = "CLOSED_CONNECTION"; + ERROR[ERROR["INVALID_METHOD"] = 6] = "INVALID_METHOD"; + ERROR[ERROR["INVALID_URL"] = 7] = "INVALID_URL"; + ERROR[ERROR["INVALID_CONSTANT"] = 8] = "INVALID_CONSTANT"; + ERROR[ERROR["INVALID_VERSION"] = 9] = "INVALID_VERSION"; + ERROR[ERROR["INVALID_HEADER_TOKEN"] = 10] = "INVALID_HEADER_TOKEN"; + ERROR[ERROR["INVALID_CONTENT_LENGTH"] = 11] = "INVALID_CONTENT_LENGTH"; + ERROR[ERROR["INVALID_CHUNK_SIZE"] = 12] = "INVALID_CHUNK_SIZE"; + ERROR[ERROR["INVALID_STATUS"] = 13] = "INVALID_STATUS"; + ERROR[ERROR["INVALID_EOF_STATE"] = 14] = "INVALID_EOF_STATE"; + ERROR[ERROR["INVALID_TRANSFER_ENCODING"] = 15] = "INVALID_TRANSFER_ENCODING"; + ERROR[ERROR["CB_MESSAGE_BEGIN"] = 16] = "CB_MESSAGE_BEGIN"; + ERROR[ERROR["CB_HEADERS_COMPLETE"] = 17] = "CB_HEADERS_COMPLETE"; + ERROR[ERROR["CB_MESSAGE_COMPLETE"] = 18] = "CB_MESSAGE_COMPLETE"; + ERROR[ERROR["CB_CHUNK_HEADER"] = 19] = "CB_CHUNK_HEADER"; + ERROR[ERROR["CB_CHUNK_COMPLETE"] = 20] = "CB_CHUNK_COMPLETE"; + ERROR[ERROR["PAUSED"] = 21] = "PAUSED"; + ERROR[ERROR["PAUSED_UPGRADE"] = 22] = "PAUSED_UPGRADE"; + ERROR[ERROR["PAUSED_H2_UPGRADE"] = 23] = "PAUSED_H2_UPGRADE"; + ERROR[ERROR["USER"] = 24] = "USER"; +})(ERROR = exports.ERROR || (exports.ERROR = {})); +var TYPE; +(function (TYPE) { + TYPE[TYPE["BOTH"] = 0] = "BOTH"; + TYPE[TYPE["REQUEST"] = 1] = "REQUEST"; + TYPE[TYPE["RESPONSE"] = 2] = "RESPONSE"; +})(TYPE = exports.TYPE || (exports.TYPE = {})); +var FLAGS; +(function (FLAGS) { + FLAGS[FLAGS["CONNECTION_KEEP_ALIVE"] = 1] = "CONNECTION_KEEP_ALIVE"; + FLAGS[FLAGS["CONNECTION_CLOSE"] = 2] = "CONNECTION_CLOSE"; + FLAGS[FLAGS["CONNECTION_UPGRADE"] = 4] = "CONNECTION_UPGRADE"; + FLAGS[FLAGS["CHUNKED"] = 8] = "CHUNKED"; + FLAGS[FLAGS["UPGRADE"] = 16] = "UPGRADE"; + FLAGS[FLAGS["CONTENT_LENGTH"] = 32] = "CONTENT_LENGTH"; + FLAGS[FLAGS["SKIPBODY"] = 64] = "SKIPBODY"; + FLAGS[FLAGS["TRAILING"] = 128] = "TRAILING"; + // 1 << 8 is unused + FLAGS[FLAGS["TRANSFER_ENCODING"] = 512] = "TRANSFER_ENCODING"; +})(FLAGS = exports.FLAGS || (exports.FLAGS = {})); +var LENIENT_FLAGS; +(function (LENIENT_FLAGS) { + LENIENT_FLAGS[LENIENT_FLAGS["HEADERS"] = 1] = "HEADERS"; + LENIENT_FLAGS[LENIENT_FLAGS["CHUNKED_LENGTH"] = 2] = "CHUNKED_LENGTH"; + LENIENT_FLAGS[LENIENT_FLAGS["KEEP_ALIVE"] = 4] = "KEEP_ALIVE"; +})(LENIENT_FLAGS = exports.LENIENT_FLAGS || (exports.LENIENT_FLAGS = {})); +var METHODS; +(function (METHODS) { + METHODS[METHODS["DELETE"] = 0] = "DELETE"; + METHODS[METHODS["GET"] = 1] = "GET"; + METHODS[METHODS["HEAD"] = 2] = "HEAD"; + METHODS[METHODS["POST"] = 3] = "POST"; + METHODS[METHODS["PUT"] = 4] = "PUT"; + /* pathological */ + METHODS[METHODS["CONNECT"] = 5] = "CONNECT"; + METHODS[METHODS["OPTIONS"] = 6] = "OPTIONS"; + METHODS[METHODS["TRACE"] = 7] = "TRACE"; + /* WebDAV */ + METHODS[METHODS["COPY"] = 8] = "COPY"; + METHODS[METHODS["LOCK"] = 9] = "LOCK"; + METHODS[METHODS["MKCOL"] = 10] = "MKCOL"; + METHODS[METHODS["MOVE"] = 11] = "MOVE"; + METHODS[METHODS["PROPFIND"] = 12] = "PROPFIND"; + METHODS[METHODS["PROPPATCH"] = 13] = "PROPPATCH"; + METHODS[METHODS["SEARCH"] = 14] = "SEARCH"; + METHODS[METHODS["UNLOCK"] = 15] = "UNLOCK"; + METHODS[METHODS["BIND"] = 16] = "BIND"; + METHODS[METHODS["REBIND"] = 17] = "REBIND"; + METHODS[METHODS["UNBIND"] = 18] = "UNBIND"; + METHODS[METHODS["ACL"] = 19] = "ACL"; + /* subversion */ + METHODS[METHODS["REPORT"] = 20] = "REPORT"; + METHODS[METHODS["MKACTIVITY"] = 21] = "MKACTIVITY"; + METHODS[METHODS["CHECKOUT"] = 22] = "CHECKOUT"; + METHODS[METHODS["MERGE"] = 23] = "MERGE"; + /* upnp */ + METHODS[METHODS["M-SEARCH"] = 24] = "M-SEARCH"; + METHODS[METHODS["NOTIFY"] = 25] = "NOTIFY"; + METHODS[METHODS["SUBSCRIBE"] = 26] = "SUBSCRIBE"; + METHODS[METHODS["UNSUBSCRIBE"] = 27] = "UNSUBSCRIBE"; + /* RFC-5789 */ + METHODS[METHODS["PATCH"] = 28] = "PATCH"; + METHODS[METHODS["PURGE"] = 29] = "PURGE"; + /* CalDAV */ + METHODS[METHODS["MKCALENDAR"] = 30] = "MKCALENDAR"; + /* RFC-2068, section 19.6.1.2 */ + METHODS[METHODS["LINK"] = 31] = "LINK"; + METHODS[METHODS["UNLINK"] = 32] = "UNLINK"; + /* icecast */ + METHODS[METHODS["SOURCE"] = 33] = "SOURCE"; + /* RFC-7540, section 11.6 */ + METHODS[METHODS["PRI"] = 34] = "PRI"; + /* RFC-2326 RTSP */ + METHODS[METHODS["DESCRIBE"] = 35] = "DESCRIBE"; + METHODS[METHODS["ANNOUNCE"] = 36] = "ANNOUNCE"; + METHODS[METHODS["SETUP"] = 37] = "SETUP"; + METHODS[METHODS["PLAY"] = 38] = "PLAY"; + METHODS[METHODS["PAUSE"] = 39] = "PAUSE"; + METHODS[METHODS["TEARDOWN"] = 40] = "TEARDOWN"; + METHODS[METHODS["GET_PARAMETER"] = 41] = "GET_PARAMETER"; + METHODS[METHODS["SET_PARAMETER"] = 42] = "SET_PARAMETER"; + METHODS[METHODS["REDIRECT"] = 43] = "REDIRECT"; + METHODS[METHODS["RECORD"] = 44] = "RECORD"; + /* RAOP */ + METHODS[METHODS["FLUSH"] = 45] = "FLUSH"; +})(METHODS = exports.METHODS || (exports.METHODS = {})); +exports.METHODS_HTTP = [ + METHODS.DELETE, + METHODS.GET, + METHODS.HEAD, + METHODS.POST, + METHODS.PUT, + METHODS.CONNECT, + METHODS.OPTIONS, + METHODS.TRACE, + METHODS.COPY, + METHODS.LOCK, + METHODS.MKCOL, + METHODS.MOVE, + METHODS.PROPFIND, + METHODS.PROPPATCH, + METHODS.SEARCH, + METHODS.UNLOCK, + METHODS.BIND, + METHODS.REBIND, + METHODS.UNBIND, + METHODS.ACL, + METHODS.REPORT, + METHODS.MKACTIVITY, + METHODS.CHECKOUT, + METHODS.MERGE, + METHODS['M-SEARCH'], + METHODS.NOTIFY, + METHODS.SUBSCRIBE, + METHODS.UNSUBSCRIBE, + METHODS.PATCH, + METHODS.PURGE, + METHODS.MKCALENDAR, + METHODS.LINK, + METHODS.UNLINK, + METHODS.PRI, + // TODO(indutny): should we allow it with HTTP? + METHODS.SOURCE, +]; +exports.METHODS_ICE = [ + METHODS.SOURCE, +]; +exports.METHODS_RTSP = [ + METHODS.OPTIONS, + METHODS.DESCRIBE, + METHODS.ANNOUNCE, + METHODS.SETUP, + METHODS.PLAY, + METHODS.PAUSE, + METHODS.TEARDOWN, + METHODS.GET_PARAMETER, + METHODS.SET_PARAMETER, + METHODS.REDIRECT, + METHODS.RECORD, + METHODS.FLUSH, + // For AirPlay + METHODS.GET, + METHODS.POST, +]; +exports.METHOD_MAP = utils_1.enumToMap(METHODS); +exports.H_METHOD_MAP = {}; +Object.keys(exports.METHOD_MAP).forEach((key) => { + if (/^H/.test(key)) { + exports.H_METHOD_MAP[key] = exports.METHOD_MAP[key]; + } +}); +var FINISH; +(function (FINISH) { + FINISH[FINISH["SAFE"] = 0] = "SAFE"; + FINISH[FINISH["SAFE_WITH_CB"] = 1] = "SAFE_WITH_CB"; + FINISH[FINISH["UNSAFE"] = 2] = "UNSAFE"; +})(FINISH = exports.FINISH || (exports.FINISH = {})); +exports.ALPHA = []; +for (let i = 'A'.charCodeAt(0); i <= 'Z'.charCodeAt(0); i++) { + // Upper case + exports.ALPHA.push(String.fromCharCode(i)); + // Lower case + exports.ALPHA.push(String.fromCharCode(i + 0x20)); } - -class NotSupportedError extends UndiciError { - constructor (message) { - super(message) - Error.captureStackTrace(this, NotSupportedError) - this.name = 'NotSupportedError' - this.message = message || 'Not supported error' - this.code = 'UND_ERR_NOT_SUPPORTED' - } +exports.NUM_MAP = { + 0: 0, 1: 1, 2: 2, 3: 3, 4: 4, + 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, +}; +exports.HEX_MAP = { + 0: 0, 1: 1, 2: 2, 3: 3, 4: 4, + 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, + A: 0XA, B: 0XB, C: 0XC, D: 0XD, E: 0XE, F: 0XF, + a: 0xa, b: 0xb, c: 0xc, d: 0xd, e: 0xe, f: 0xf, +}; +exports.NUM = [ + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', +]; +exports.ALPHANUM = exports.ALPHA.concat(exports.NUM); +exports.MARK = ['-', '_', '.', '!', '~', '*', '\'', '(', ')']; +exports.USERINFO_CHARS = exports.ALPHANUM + .concat(exports.MARK) + .concat(['%', ';', ':', '&', '=', '+', '$', ',']); +// TODO(indutny): use RFC +exports.STRICT_URL_CHAR = [ + '!', '"', '$', '%', '&', '\'', + '(', ')', '*', '+', ',', '-', '.', '/', + ':', ';', '<', '=', '>', + '@', '[', '\\', ']', '^', '_', + '`', + '{', '|', '}', '~', +].concat(exports.ALPHANUM); +exports.URL_CHAR = exports.STRICT_URL_CHAR + .concat(['\t', '\f']); +// All characters with 0x80 bit set to 1 +for (let i = 0x80; i <= 0xff; i++) { + exports.URL_CHAR.push(i); } - -class BalancedPoolMissingUpstreamError extends UndiciError { - constructor (message) { - super(message) - Error.captureStackTrace(this, NotSupportedError) - this.name = 'MissingUpstreamError' - this.message = message || 'No upstream has been added to the BalancedPool' - this.code = 'UND_ERR_BPL_MISSING_UPSTREAM' - } +exports.HEX = exports.NUM.concat(['a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F']); +/* Tokens as defined by rfc 2616. Also lowercases them. + * token = 1* + * separators = "(" | ")" | "<" | ">" | "@" + * | "," | ";" | ":" | "\" | <"> + * | "/" | "[" | "]" | "?" | "=" + * | "{" | "}" | SP | HT + */ +exports.STRICT_TOKEN = [ + '!', '#', '$', '%', '&', '\'', + '*', '+', '-', '.', + '^', '_', '`', + '|', '~', +].concat(exports.ALPHANUM); +exports.TOKEN = exports.STRICT_TOKEN.concat([' ']); +/* + * Verify that a char is a valid visible (printable) US-ASCII + * character or %x80-FF + */ +exports.HEADER_CHARS = ['\t']; +for (let i = 32; i <= 255; i++) { + if (i !== 127) { + exports.HEADER_CHARS.push(i); + } } +// ',' = \x44 +exports.CONNECTION_TOKEN_CHARS = exports.HEADER_CHARS.filter((c) => c !== 44); +exports.MAJOR = exports.NUM_MAP; +exports.MINOR = exports.MAJOR; +var HEADER_STATE; +(function (HEADER_STATE) { + HEADER_STATE[HEADER_STATE["GENERAL"] = 0] = "GENERAL"; + HEADER_STATE[HEADER_STATE["CONNECTION"] = 1] = "CONNECTION"; + HEADER_STATE[HEADER_STATE["CONTENT_LENGTH"] = 2] = "CONTENT_LENGTH"; + HEADER_STATE[HEADER_STATE["TRANSFER_ENCODING"] = 3] = "TRANSFER_ENCODING"; + HEADER_STATE[HEADER_STATE["UPGRADE"] = 4] = "UPGRADE"; + HEADER_STATE[HEADER_STATE["CONNECTION_KEEP_ALIVE"] = 5] = "CONNECTION_KEEP_ALIVE"; + HEADER_STATE[HEADER_STATE["CONNECTION_CLOSE"] = 6] = "CONNECTION_CLOSE"; + HEADER_STATE[HEADER_STATE["CONNECTION_UPGRADE"] = 7] = "CONNECTION_UPGRADE"; + HEADER_STATE[HEADER_STATE["TRANSFER_ENCODING_CHUNKED"] = 8] = "TRANSFER_ENCODING_CHUNKED"; +})(HEADER_STATE = exports.HEADER_STATE || (exports.HEADER_STATE = {})); +exports.SPECIAL_HEADERS = { + 'connection': HEADER_STATE.CONNECTION, + 'content-length': HEADER_STATE.CONTENT_LENGTH, + 'proxy-connection': HEADER_STATE.CONNECTION, + 'transfer-encoding': HEADER_STATE.TRANSFER_ENCODING, + 'upgrade': HEADER_STATE.UPGRADE, +}; +//# sourceMappingURL=constants.js.map -class HTTPParserError extends Error { - constructor (message, code, data) { - super(message) - Error.captureStackTrace(this, HTTPParserError) - this.name = 'HTTPParserError' - this.code = code ? `HPE_${code}` : undefined - this.data = data ? data.toString() : undefined - } -} +/***/ }), -class ResponseExceededMaxSizeError extends UndiciError { - constructor (message) { - super(message) - Error.captureStackTrace(this, ResponseExceededMaxSizeError) - this.name = 'ResponseExceededMaxSizeError' - this.message = message || 'Response content exceeded max size' - this.code = 'UND_ERR_RES_EXCEEDED_MAX_SIZE' - } -} +/***/ 3312: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -class RequestRetryError extends UndiciError { - constructor (message, code, { headers, data }) { - super(message) - Error.captureStackTrace(this, RequestRetryError) - this.name = 'RequestRetryError' - this.message = message || 'Request retry error' - this.code = 'UND_ERR_REQ_RETRY' - this.statusCode = code - this.data = data - this.headers = headers - } -} -module.exports = { - HTTPParserError, - UndiciError, - HeadersTimeoutError, - HeadersOverflowError, - BodyTimeoutError, - RequestContentLengthMismatchError, - ConnectTimeoutError, - ResponseStatusCodeError, - InvalidArgumentError, - InvalidReturnValueError, - RequestAbortedError, - ClientDestroyedError, - ClientClosedError, - InformationalError, - SocketError, - NotSupportedError, - ResponseContentLengthMismatchError, - BalancedPoolMissingUpstreamError, - ResponseExceededMaxSizeError, - RequestRetryError -} + +const { Buffer } = __nccwpck_require__(4573) + +module.exports = Buffer.from('AGFzbQEAAAABJwdgAX8Bf2ADf39/AX9gAX8AYAJ/fwBgBH9/f38Bf2AAAGADf39/AALLAQgDZW52GHdhc21fb25faGVhZGVyc19jb21wbGV0ZQAEA2VudhV3YXNtX29uX21lc3NhZ2VfYmVnaW4AAANlbnYLd2FzbV9vbl91cmwAAQNlbnYOd2FzbV9vbl9zdGF0dXMAAQNlbnYUd2FzbV9vbl9oZWFkZXJfZmllbGQAAQNlbnYUd2FzbV9vbl9oZWFkZXJfdmFsdWUAAQNlbnYMd2FzbV9vbl9ib2R5AAEDZW52GHdhc21fb25fbWVzc2FnZV9jb21wbGV0ZQAAAy0sBQYAAAIAAAAAAAACAQIAAgICAAADAAAAAAMDAwMBAQEBAQEBAQEAAAIAAAAEBQFwARISBQMBAAIGCAF/AUGA1AQLB9EFIgZtZW1vcnkCAAtfaW5pdGlhbGl6ZQAIGV9faW5kaXJlY3RfZnVuY3Rpb25fdGFibGUBAAtsbGh0dHBfaW5pdAAJGGxsaHR0cF9zaG91bGRfa2VlcF9hbGl2ZQAvDGxsaHR0cF9hbGxvYwALBm1hbGxvYwAxC2xsaHR0cF9mcmVlAAwEZnJlZQAMD2xsaHR0cF9nZXRfdHlwZQANFWxsaHR0cF9nZXRfaHR0cF9tYWpvcgAOFWxsaHR0cF9nZXRfaHR0cF9taW5vcgAPEWxsaHR0cF9nZXRfbWV0aG9kABAWbGxodHRwX2dldF9zdGF0dXNfY29kZQAREmxsaHR0cF9nZXRfdXBncmFkZQASDGxsaHR0cF9yZXNldAATDmxsaHR0cF9leGVjdXRlABQUbGxodHRwX3NldHRpbmdzX2luaXQAFQ1sbGh0dHBfZmluaXNoABYMbGxodHRwX3BhdXNlABcNbGxodHRwX3Jlc3VtZQAYG2xsaHR0cF9yZXN1bWVfYWZ0ZXJfdXBncmFkZQAZEGxsaHR0cF9nZXRfZXJybm8AGhdsbGh0dHBfZ2V0X2Vycm9yX3JlYXNvbgAbF2xsaHR0cF9zZXRfZXJyb3JfcmVhc29uABwUbGxodHRwX2dldF9lcnJvcl9wb3MAHRFsbGh0dHBfZXJybm9fbmFtZQAeEmxsaHR0cF9tZXRob2RfbmFtZQAfEmxsaHR0cF9zdGF0dXNfbmFtZQAgGmxsaHR0cF9zZXRfbGVu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PgtBhwEMPQtBiAEMPAtBiQEMOwtBigEMOgtBiwEMOQtBjAEMOAtBjQEMNwtBjgEMNgtBjwEMNQtBkAEMNAtBkQEMMwtBkgEMMgtBkwEMMQtBlAEMMAtBlQEMLwtBlgEMLgtBlwEMLQtBmAEMLAtBmQEMKwtBmgEMKgtBmwEMKQtBnAEMKAtBnQEMJwtBngEMJgtBnwEMJQtBoAEMJAtBoQEMIwtBogEMIgtBowEMIQtBpAEMIAtBpQEMHwtBpgEMHgtBpwEMHQtBqAEMHAtBqQEMGwtBqgEMGgtBqwEMGQtBrAEMGAtBrQEMFwtBrgEMFgtBAQwVC0GvAQwUC0GwAQwTC0GxAQwSC0GzAQwRC0GyAQwQC0G0AQwPC0G1AQwOC0G2AQwNC0G3AQwMC0G4AQwLC0G5AQwKC0G6AQwJC0G7AQwIC0HGAQwHC0G8AQwGC0G9AQwFC0G+AQwEC0G/AQwDC0HAAQwCC0HCAQwBC0HBAQshAwNAAkACQAJAAkACQAJAAkACQAJAIAICfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJ/AkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgAgJ/AkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACfwJAAkACfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAC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iQEhAwykAgtBASABLQAAQd8ARw1nGiABQQFqIQEMXgtBigEhAyABIARGDaICIAIoAgAiACAEIAFraiEFIAEgAGtBAWohBgNAIAEtAAAgAEGMzwBqLQAARw1kIABBAUYN+gEgAEEBaiEAIAQgAUEBaiIBRw0ACyACIAU2AgAMogILQYsBIQMgASAERg2hAiACKAIAIgAgBCABa2ohBSABIABrQQJqIQYCQANAIAEtAAAgAEGOzwBqLQAARw1kIABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAIgBTYCAAyiAgsgAkEANgIAIAZBAWohAUECDGULQYwBIQMgASAERg2gAiACKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEHwzwBqLQAARw1jIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAIgBTYCAAyhAgsgAkEANgIAIAZBAWohAUEfDGQLQY0BIQMgASAERg2fAiACKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEHyzwBqLQAARw1iIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAIgBTYCAAygAgsgAkEANgIAIAZBAWohAUEJDGMLIAEgBEYEQEGOASEDDJ8CCwJAAkAgAS0AAEHJAGsOBwBiYmJiYgFiCyABQQFqIQFB+AAhAwyGAgsgAUEBaiEBQfkAIQMMhQILQY8BIQMgASAERg2dAiACKAIAIgAgBCABa2ohBSABIABrQQVqIQYCQANAIAEtAAAgAEGRzwBqLQAARw1gIABBBUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAIgBTYCAAyeAgsgAkEANgIAIAZBAWohAUEYDGELQZABIQMgASAERg2cAiACKAIAIgAgBCABa2ohBSABIABrQQJqIQYCQANAIAEtAAAgAEGXzwBqLQAARw1fIABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAIgBTYCAAydAgsgAkEANgIAIAZBAWohAUEXDGALQZEBIQMgASAERg2bAiACKAIAIgAgBCABa2ohBSABIABrQQZqIQYCQANAIAEtAAAgAEGazwBqLQAARw1eIABBBkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAIgBTYCAAycAgsgAkEANgIAIAZBAWohAUEV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JSIARQ0RIAJB5QA2AhwgAiABNgIUIAIgADYCDEEAIQMMtAELIAIoAgQhACACQQA2AgQgAiAAIAEQJSIARQ0gIAJB0wA2AhwgAiABNgIUIAIgADYCDEEAIQMMswELIAIoAgQhACACQQA2AgQgAiAAIAEQJSIARQ0iIAJB0gA2AhwgAiABNgIUIAIgADYCDEEAIQMMsgELIAIoAgQhACACQQA2AgQgAiAAIAEQJSIARQ0OIAJB5QA2AhwgAiABNgIUIAIgADYCDEEAIQMMsQELIAIoAgQhACACQQA2AgQgAiAAIAEQJSIARQ0dIAJB0wA2AhwgAiABNgIUIAIgADYCDEEAIQMMsAELIAIoAgQhACACQQA2AgQgAiAAIAEQJSIARQ0fIAJB0gA2AhwgAiABNgIUIAIgADYCDEEAIQMMrwELIABBP0cNASABQQFqCyEBQQUhAwyUAQtBACEDIAJBADYCHCACIAE2AhQgAkH9EjYCECACQQc2AgwMrAELIAJBADYCHCACIAE2AhQgAkHcCDYCECACQQc2AgxBACEDDKsBCyACKAIEIQAgAkEANgIEIAIgACABECUiAEUNByACQeUANgIcIAIgATYCFCACIAA2AgxBACEDDKoBCyACKAIEIQAgAkEANgIEIAIgACABECUiAEUNFiACQdMANgIcIAIgATYCFCACIAA2AgxBACEDDKkBCyACKAIEIQAgAkEANgIEIAIgACABECUiAEUNGCACQdIANgIcIAIgATYCFCACIAA2AgxBACEDDKgBCyACQQA2AhwgAiABNgIUIAJBxgo2AhAgAkEHNgIMQQAhAwynAQsgAigCBCEAIAJBADYCBCACIAAgARAlIgBFDQMgAkHlADYCHCACIAE2AhQgAiAANgIMQQAhAwymAQsgAigCBCEAIAJBADYCBCACIAAgARAlIgBFDRIgAkHTADYCHCACIAE2AhQgAiAANgIMQQAhAwylAQsgAigCBCEAIAJBADYCBCACIAAgARAlIgBFDRQgAkHSADYCHCACIAE2AhQgAiAANgIMQQAhAwykAQsgAigCBCEAIAJBADYCBCACIAAgARAlIgBFDQAgAkHlADYCHCACIAE2AhQgAiAANgIMQQAhAwyjAQtB1QAhAwyJAQsgAEEVRwRAIAJBADYCHCACIAE2AhQgAkG5DTYCECACQRo2AgxB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AkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIABB5ABrDvQDY2IAAWFhYWFhYQIDBAVhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhBgcICQoLDA0OD2FhYWFhEGFhYWFhYWFhYWFhEWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYRITFBUWFxgZGhthYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhHB0eHyAhIiMkJSYnKCkqKywtLi8wMTIzNDU2YTc4OTphYWFhYWFhYTthYWE8YWFhYT0+P2FhYWFhYWFhQGFhQWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYUJDREVGR0hJSktMTU5PUFFSU2FhYWFhYWFhVFVWV1hZWlthXF1hYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFeYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhX2BhC0HhJw8LQaQhDwtByywPC0H+MQ8LQcAkDwtBqyQPC0GNKA8LQeImDwtBgDAPC0G5Lw8LQdckDwtB7x8PC0HhHw8LQfofDwtB8iAPC0GoLw8LQa4yDwtBiDAPC0HsJw8LQYIiDwtBjh0PC0HQLg8LQcojDwtBxTIPC0HfHA8LQdIcDwtBxCAPC0HXIA8LQaIfDwtB7S4PC0GrMA8LQdQlDwtBzC4PC0H6Lg8LQfwrDwtB0jAPC0HxHQ8LQbsgDwtB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CABB3AgLii1JbnZhbGlkIGNoYXIgaW4gdXJsIHF1ZXJ5AFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fYm9keQBDb250ZW50LUxlbmd0aCBvdmVyZmxvdwBDaHVuayBzaXplIG92ZXJmbG93AFJlc3BvbnNlIG92ZXJmbG93AEludmFsaWQgbWV0aG9kIGZvciBIVFRQL3gueCByZXF1ZXN0AEludmFsaWQgbWV0aG9kIGZvciBSVFNQL3gueCByZXF1ZXN0AEV4cGVjdGVkIFNPVVJDRSBtZXRob2QgZm9yIElDRS94LnggcmVxdWVzdABJbnZhbGlkIGNoYXIgaW4gdXJsIGZyYWdtZW50IHN0YXJ0AEV4cGVjdGVkIGRvdABTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3N0YXR1cwBJbnZhbGlkIHJlc3BvbnNlIHN0YXR1cwBJbnZhbGlkIGNoYXJhY3RlciBpbiBjaHVuayBleHRlbnNpb25zAFVzZXIgY2FsbGJhY2sgZXJyb3IAYG9uX3Jlc2V0YCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfaGVhZGVyYCBjYWxsYmFjayBlcnJvcgBgb25fbWVzc2FnZV9iZWdpbmAgY2FsbGJhY2sgZXJyb3IAYG9uX2NodW5rX2V4dGVuc2lvbl92YWx1ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX3N0YXR1c19jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX3ZlcnNpb25fY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl91cmxfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9jaHVua19jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX2hlYWRlcl92YWx1ZV9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX21lc3NhZ2VfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9tZXRob2RfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9oZWFkZXJfZmllbGRfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9jaHVua19leHRlbnNpb25fbmFtZWAgY2FsbGJhY2sgZXJyb3IAVW5leHBlY3RlZCBjaGFyIGluIHVybCBzZXJ2ZXIASW52YWxpZCBoZWFkZXIgdmFsdWUgY2hhcgBJbnZhbGlkIGhlYWRlciBmaWVsZCBjaGFyAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fdmVyc2lvbgBJbnZhbGlkIG1pbm9yIHZlcnNpb24ASW52YWxpZCBtYWpvciB2ZXJzaW9uAEV4cGVjdGVkIHNwYWNlIGFmdGVyIHZlcnNpb24ARXhwZWN0ZWQgQ1JMRiBhZnRlciB2ZXJzaW9uAEludmFsaWQgSFRUUCB2ZXJzaW9uAEludmFsaWQgaGVhZGVyIHRva2VuAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fdXJsAEludmFsaWQgY2hhcmFjdGVycyBpbiB1cmwAVW5leHBlY3RlZCBzdGFydCBjaGFyIGluIHVybABEb3VibGUgQCBpbiB1cmwARW1wdHkgQ29udGVudC1MZW5ndGgASW52YWxpZCBjaGFyYWN0ZXIgaW4gQ29udGVudC1MZW5ndGgARHVwbGljYXRlIENvbnRlbnQtTGVuZ3RoAEludmFsaWQgY2hhciBpbiB1cmwgcGF0aABDb250ZW50LUxlbmd0aCBjYW4ndCBiZSBwcmVzZW50IHdpdGggVHJhbnNmZXItRW5jb2RpbmcASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgc2l6ZQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX2hlYWRlcl92YWx1ZQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX2NodW5rX2V4dGVuc2lvbl92YWx1ZQBJbnZhbGlkIGNoYXJhY3RlciBpbiBjaHVuayBleHRlbnNpb25zIHZhbHVlAE1pc3NpbmcgZXhwZWN0ZWQgTEYgYWZ0ZXIgaGVhZGVyIHZhbHVlAEludmFsaWQgYFRyYW5zZmVyLUVuY29kaW5nYCBoZWFkZXIgdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyBxdW90ZSB2YWx1ZQBJbnZhbGlkIGNoYXJhY3RlciBpbiBjaHVuayBleHRlbnNpb25zIHF1b3RlZCB2YWx1ZQBQYXVzZWQgYnkgb25faGVhZGVyc19jb21wbGV0ZQBJbnZhbGlkIEVPRiBzdGF0ZQBvbl9yZXNldCBwYXVzZQBvbl9jaHVua19oZWFkZXIgcGF1c2UAb25fbWVzc2FnZV9iZWdpbiBwYXVzZQBvbl9jaHVua19leHRlbnNpb25fdmFsdWUgcGF1c2UAb25fc3RhdHVzX2NvbXBsZXRlIHBhdXNlAG9uX3ZlcnNpb25fY29tcGxldGUgcGF1c2UAb25fdXJsX2NvbXBsZXRlIHBhdXNlAG9uX2NodW5rX2NvbXBsZXRlIHBhdXNlAG9uX2hlYWRlcl92YWx1ZV9jb21wbGV0ZSBwYXVzZQBvbl9tZXNzYWdlX2NvbXBsZXRlIHBhdXNlAG9uX21ldGhvZF9jb21wbGV0ZSBwYXVzZQBvbl9oZWFkZXJfZmllbGRfY29tcGxldGUgcGF1c2UAb25fY2h1bmtfZXh0ZW5zaW9uX25hbWUgcGF1c2UAVW5leHBlY3RlZCBzcGFjZSBhZnRlciBzdGFydCBsaW5lAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fY2h1bmtfZXh0ZW5zaW9uX25hbWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyBuYW1lAFBhdXNlIG9uIENPTk5FQ1QvVXBncmFkZQBQYXVzZSBvbiBQUkkvVXBncmFkZQBFeHBlY3RlZCBIVFRQLzIgQ29ubmVjdGlvbiBQcmVmYWNlAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fbWV0aG9kAEV4cGVjdGVkIHNwYWNlIGFmdGVyIG1ldGhvZABTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX2hlYWRlcl9maWVsZABQYXVzZWQASW52YWxpZCB3b3JkIGVuY291bnRlcmVkAEludmFsaWQgbWV0aG9kIGVuY291bnRlcmVkAFVuZXhwZWN0ZWQgY2hhciBpbiB1cmwgc2NoZW1hAFJlcXVlc3QgaGFzIGludmFsaWQgYFRyYW5zZmVyLUVuY29kaW5nYABTV0lUQ0hfUFJPWFkAVVNFX1BST1hZAE1LQUNUSVZJVFkAVU5QUk9DRVNTQUJMRV9FTlRJVFkAQ09QWQBNT1ZFRF9QRVJNQU5FTlRMWQBUT09fRUFSTFkATk9USUZZAEZBSUxFRF9ERVBFTkRFTkNZAEJBRF9HQVRFV0FZAFBMQVkAUFVUAENIRUNLT1VUAEdBVEVXQVlfVElNRU9VVABSRVFVRVNUX1RJTUVPVVQATkVUV09SS19DT05ORUNUX1RJTUVPVVQAQ09OTkVDVElPTl9USU1FT1VUAExPR0lOX1RJTUVPVVQATkVUV09SS19SRUFEX1RJTUVPVVQAUE9TVABNSVNESVJFQ1RFRF9SRVFVRVNUAENMSUVOVF9DTE9TRURfUkVRVUVTVABDTElFTlRfQ0xPU0VEX0xPQURfQkFMQU5DRURfUkVRVUVTVABCQURfUkVRVUVTVABIVFRQX1JFUVVFU1RfU0VOVF9UT19IVFRQU19QT1JUAFJFUE9SVABJTV9BX1RFQVBPVABSRVNFVF9DT05URU5UAE5PX0NPTlRFTlQAUEFSVElBTF9DT05URU5UAEhQRV9JTlZBTElEX0NPTlNUQU5UAEhQRV9DQl9SRVNFVABHRVQASFBFX1NUUklDVABDT05GTElDVABURU1QT1JBUllfUkVESVJFQ1QAUEVSTUFORU5UX1JFRElSRUNUAENPTk5FQ1QATVVMVElfU1RBVFVTAEhQRV9JTlZBTElEX1NUQVRVUwBUT09fTUFOWV9SRVFVRVNUUwBFQVJMWV9ISU5UUwBVTkFWQUlMQUJMRV9GT1JfTEVHQUxfUkVBU09OUwBPUFRJT05TAFNXSVRDSElOR19QUk9UT0NPTFMAVkFSSUFOVF9BTFNPX05FR09USUFURVMATVVMVElQTEVfQ0hPSUNFUwBJTlRFUk5BTF9TRVJWRVJfRVJST1IAV0VCX1NFUlZFUl9VTktOT1dOX0VSUk9SAFJBSUxHVU5fRVJST1IASURFTlRJVFlfUFJPVklERVJfQVVUSEVOVElDQVRJT05fRVJST1IAU1NMX0NFUlRJRklDQVRFX0VSUk9SAElOVkFMSURfWF9GT1JXQVJERURfRk9SAFNFVF9QQVJBTUVURVIAR0VUX1BBUkFNRVRFUgBIUEVfVVNFUgBTRUVfT1RIRVIASFBFX0NCX0NIVU5LX0hFQURFUgBNS0NBTEVOREFSAFNFVFVQAFdFQl9TRVJWRVJfSVNfRE9XTgBURUFSRE9XTgBIUEVfQ0xPU0VEX0NPTk5FQ1RJT04ASEVVUklTVElDX0VYUElSQVRJT04ARElTQ09OTkVDVEVEX09QRVJBVElPTgBOT05fQVVUSE9SSVRBVElWRV9JTkZPUk1BVElPTgBIUEVfSU5WQUxJRF9WRVJTSU9OAEhQRV9DQl9NRVNTQUdFX0JFR0lOAFNJVEVfSVNfRlJPWkVOAEhQRV9JTlZBTElEX0hFQURFUl9UT0tFTgBJTlZBTElEX1RPS0VOAEZPUkJJRERFTgBFTkhBTkNFX1lPVVJfQ0FMTQBIUEVfSU5WQUxJRF9VUkwAQkxPQ0tFRF9CWV9QQVJFTlRBTF9DT05UUk9MAE1LQ09MAEFDTABIUEVfSU5URVJOQUwAUkVRVUVTVF9IRUFERVJfRklFTERTX1RPT19MQVJHRV9VTk9GRklDSUFMAEhQRV9PSwBVTkxJTksAVU5MT0NLAFBSSQBSRVRSWV9XSVRIAEhQRV9JTlZBTElEX0NPTlRFTlRfTEVOR1RIAEhQRV9VTkVYUEVDVEVEX0NPTlRFTlRfTEVOR1RIAEZMVVNIAFBST1BQQVRDSABNLVNFQVJDSABVUklfVE9PX0xPTkcAUFJPQ0VTU0lORwBNSVNDRUxMQU5FT1VTX1BFUlNJU1RFTlRfV0FSTklORwBNSVNDRUxMQU5FT1VTX1dBUk5JTkcASFBFX0lOVkFMSURfVFJBTlNGRVJfRU5DT0RJTkcARXhwZWN0ZWQgQ1JMRgBIUEVfSU5WQUxJRF9DSFVOS19TSVpFAE1PVkUAQ09OVElOVUUASFBFX0NCX1NUQVRVU19DT01QTEVURQBIUEVfQ0JfSEVBREVSU19DT01QTEVURQBIUEVfQ0JfVkVSU0lPTl9DT01QTEVURQBIUEVfQ0JfVVJMX0NPTVBMRVRFAEhQRV9DQl9DSFVOS19DT01QTEVURQBIUEVfQ0JfSEVBREVSX1ZBTFVFX0NPTVBMRVRFAEhQRV9DQl9DSFVOS19FWFRFTlNJT05fVkFMVUVfQ09NUExFVEUASFBFX0NCX0NIVU5LX0VYVEVOU0lPTl9OQU1FX0NPTVBMRVRFAEhQRV9DQl9NRVNTQUdFX0NPTVBMRVRFAEhQRV9DQl9NRVRIT0RfQ09NUExFVEUASFBFX0NCX0hFQURFUl9GSUVMRF9DT01QTEVURQBERUxFVEUASFBFX0lOVkFMSURfRU9GX1NUQVRFAElOVkFMSURfU1NMX0NFUlRJRklDQVRFAFBBVVNFAE5PX1JFU1BPTlNFAFVOU1VQUE9SVEVEX01FRElBX1RZUEUAR09ORQBOT1RfQUNDRVBUQUJMRQBTRVJWSUNFX1VOQVZBSUxBQkxFAFJBTkdFX05PVF9TQVRJU0ZJQUJMRQBPUklHSU5fSVNfVU5SRUFDSEFCTEUAUkVTUE9OU0VfSVNfU1RBTEUAUFVSR0UATUVSR0UAUkVRVUVTVF9IRUFERVJfRklFTERTX1RPT19MQVJHRQBSRVFVRVNUX0hFQURFUl9UT09fTEFSR0UAUEFZTE9BRF9UT09fTEFSR0UASU5TVUZGSUNJRU5UX1NUT1JBR0UASFBFX1BBVVNFRF9VUEdSQURFAEhQRV9QQVVTRURfSDJfVVBHUkFERQBTT1VSQ0UAQU5OT1VOQ0UAVFJBQ0UASFBFX1VORVhQRUNURURfU1BBQ0UAREVTQ1JJQkUAVU5TVUJTQ1JJQkUAUkVDT1JEAEhQRV9JTlZBTElEX01FVEhPRABOT1RfRk9VTkQAUFJPUEZJTkQAVU5CSU5EAFJFQklORABVTkFVVEhPUklaRUQATUVUSE9EX05PVF9BTExPV0VEAEhUVFBfVkVSU0lPTl9OT1RfU1VQUE9SVEVEAEFMUkVBRFlfUkVQT1JURUQAQUNDRVBURUQATk9UX0lNUExFTUVOVEVEAExPT1BfREVURUNURUQASFBFX0NSX0VYUEVDVEVEAEhQRV9MRl9FWFBFQ1RFRABDUkVBVEVEAElNX1VTRUQASFBFX1BBVVNFRABUSU1FT1VUX09DQ1VSRUQAUEFZTUVOVF9SRVFVSVJFRABQUkVDT05ESVRJT05fUkVRVUlSRUQAUFJPWFlfQVVUSEVOVElDQVRJT05fUkVRVUlSRUQATkVUV09SS19BVVRIRU5USUNBVElPTl9SRVFVSVJFRABMRU5HVEhfUkVRVUlSRUQAU1NMX0NFUlRJRklDQVRFX1JFUVVJUkVEAFVQR1JBREVfUkVRVUlSRUQAUEFHRV9FWFBJUkVEAFBSRUNPTkRJVElPTl9GQUlMRUQARVhQRUNUQVRJT05fRkFJTEVEAFJFVkFMSURBVElPTl9GQUlMRUQAU1NMX0hBTkRTSEFLRV9GQUlMRUQATE9DS0VEAFRSQU5TRk9STUFUSU9OX0FQUExJRUQATk9UX01PRElGSUVEAE5PVF9FWFRFTkRFRABCQU5EV0lEVEhfTElNSVRfRVhDRUVERUQAU0lURV9JU19PVkVSTE9BREVEAEhFQUQARXhwZWN0ZWQgSFRUUC8AAF4TAAAmEwAAMBAAAPAXAACdEwAAFRIAADkXAADwEgAAChAAAHUSAACtEgAAghMAAE8UAAB/EAAAoBUAACMUAACJEgAAixQAAE0VAADUEQAAzxQAABAYAADJFgAA3BYAAMERAADgFwAAuxQAAHQUAAB8FQAA5RQAAAgXAAAfEAAAZRUAAKMUAAAoFQAAAhUAAJkVAAAsEAAAixkAAE8PAADUDgAAahAAAM4QAAACFwAAiQ4AAG4TAAAcEwAAZhQAAFYXAADBEwAAzRMAAGwTAABoFwAAZhcAAF8XAAAiEwAAzg8AAGkOAADYDgAAYxYAAMsTAACqDgAAKBcAACYXAADFEwAAXRYAAOgRAABnEwAAZRMAAPIWAABzEwAAHRcAAPkWAADzEQAAzw4AAM4VAAAMEgAAsxEAAKURAABhEAAAMhcAALsTAEH5NQsBAQBBkDYL4AEBAQIBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQBB/TcLAQEAQZE4C14CAwICAgICAAACAgACAgACAgICAgICAgICAAQAAAAAAAICAgICAgICAgICAgICAgICAgICAgICAgICAAAAAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAAgACAEH9OQsBAQBBkToLXgIAAgICAgIAAAICAAICAAICAgICAgICAgIAAwAEAAAAAgICAgICAgICAgICAgICAgICAgICAgICAgIAAAACAgICAgICAgICAgICAgICAgICAgICAgICAgICAgACAAIAQfA7Cw1sb3NlZWVwLWFsaXZlAEGJPAsBAQBBoDwL4AEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQBBiT4LAQEAQaA+C+cBAQEBAQEBAQEBAQEBAgEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQFjaHVua2VkAEGwwAALXwEBAAEBAQEBAAABAQABAQABAQEBAQEBAQEBAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQABAEGQwgALIWVjdGlvbmVudC1sZW5ndGhvbnJveHktY29ubmVjdGlvbgBBwMIACy1yYW5zZmVyLWVuY29kaW5ncGdyYWRlDQoNCg0KU00NCg0KVFRQL0NFL1RTUC8AQfnCAAsFAQIAAQMAQZDDAAvgAQQBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAEH5xAALBQECAAEDAEGQxQAL4AEEAQEFAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQBB+cYACwQBAAABAEGRxwAL3wEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAEH6yAALBAEAAAIAQZDJAAtfAwQAAAQEBAQEBAQEBAQEBQQEBAQEBAQEBAQEBAAEAAYHBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQABAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAQAQfrKAAsEAQAAAQBBkMsACwEBAEGqywALQQIAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAEH6zAALBAEAAAEAQZDNAAsBAQBBms0ACwYCAAAAAAIAQbHNAAs6AwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwBB8M4AC5YBTk9VTkNFRUNLT1VUTkVDVEVURUNSSUJFTFVTSEVURUFEU0VBUkNIUkdFQ1RJVklUWUxFTkRBUlZFT1RJRllQVElPTlNDSFNFQVlTVEFUQ0hHRU9SRElSRUNUT1JUUkNIUEFSQU1FVEVSVVJDRUJTQ1JJQkVBUkRPV05BQ0VJTkROS0NLVUJTQ1JJQkVIVFRQL0FEVFAv', 'base64') /***/ }), -/***/ 2635: +/***/ 9768: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -const { - InvalidArgumentError, - NotSupportedError -} = __nccwpck_require__(6738) -const assert = __nccwpck_require__(2613) -const { kHTTP2BuildRequest, kHTTP2CopyHeaders, kHTTP1BuildRequest } = __nccwpck_require__(1028) -const util = __nccwpck_require__(5069) +const { Buffer } = __nccwpck_require__(4573) -// tokenRegExp and headerCharRegex have been lifted from -// https://github.com/nodejs/node/blob/main/lib/_http_common.js +module.exports = Buffer.from('AGFzbQEAAAABJwdgAX8Bf2ADf39/AX9gAX8AYAJ/fwBgBH9/f38Bf2AAAGADf39/AALLAQgDZW52GHdhc21fb25faGVhZGVyc19jb21wbGV0ZQAEA2VudhV3YXNtX29uX21lc3NhZ2VfYmVnaW4AAANlbnYLd2FzbV9vbl91cmwAAQNlbnYOd2FzbV9vbl9zdGF0dXMAAQNlbnYUd2FzbV9vbl9oZWFkZXJfZmllbGQAAQNlbnYUd2FzbV9vbl9oZWFkZXJfdmFsdWUAAQNlbnYMd2FzbV9vbl9ib2R5AAEDZW52GHdhc21fb25fbWVzc2FnZV9jb21wbGV0ZQAAAy0sBQYAAAIAAAAAAAACAQIAAgICAAADAAAAAAMDAwMBAQEBAQEBAQEAAAIAAAAEBQFwARISBQMBAAIGCAF/AUGA1AQLB9EFIgZtZW1vcnkCAAtfaW5pdGlhbGl6ZQAIGV9faW5kaXJlY3RfZnVuY3Rpb25fdGFibGUBAAtsbGh0dHBfaW5pdAAJGGxsaHR0cF9zaG91bGRfa2VlcF9hbGl2ZQAvDGxsaHR0cF9hbGxvYwALBm1hbGxvYwAxC2xsaHR0cF9mcmVlAAwEZnJlZQAMD2xsaHR0cF9nZXRfdHlwZQANFWxsaHR0cF9nZXRfaHR0cF9tYWpvcgAOFWxsaHR0cF9nZXRfaHR0cF9taW5vcgAPEWxsaHR0cF9nZXRfbWV0aG9kABAWbGxodHRwX2dldF9zdGF0dXNfY29kZQAREmxsaHR0cF9nZXRfdXBncmFkZQASDGxsaHR0cF9yZXNldAATDmxsaHR0cF9leGVjdXRlABQUbGxodHRwX3NldHRpbmdzX2luaXQAFQ1sbGh0dHBfZmluaXNoABYMbGxodHRwX3BhdXNlABcNbGxodHRwX3Jlc3VtZQAYG2xsaHR0cF9yZXN1bWVfYWZ0ZXJfdXBncmFkZQAZEGxsaHR0cF9nZXRfZXJybm8AGhdsbGh0dHBfZ2V0X2Vycm9yX3JlYXNvbgAbF2xsaHR0cF9zZXRfZXJyb3JfcmVhc29uABwUbGxodHRwX2dldF9lcnJvcl9wb3MAHRFsbGh0dHBfZXJybm9fbmFtZQAeEmxsaHR0cF9tZXRob2RfbmFtZQAfEmxsaHR0cF9zdGF0dXNfbmFtZQAgGmxsaHR0cF9zZXRfbGVu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PgtBhwEMPQtBiAEMPAtBiQEMOwtBigEMOgtBiwEMOQtBjAEMOAtBjQEMNwtBjgEMNgtBjwEMNQtBkAEMNAtBkQEMMwtBkgEMMgtBkwEMMQtBlAEMMAtBlQEMLwtBlgEMLgtBlwEMLQtBmAEMLAtBmQEMKwtBmgEMKgtBmwEMKQtBnAEMKAtBnQEMJwtBngEMJgtBnwEMJQtBoAEMJAtBoQEMIwtBogEMIgtBowEMIQtBpAEMIAtBpQEMHwtBpgEMHgtBpwEMHQtBqAEMHAtBqQEMGwtBqgEMGgtBqwEMGQtBrAEMGAtBrQEMFwtBrgEMFgtBAQwVC0GvAQwUC0GwAQwTC0GxAQwSC0GzAQwRC0GyAQwQC0G0AQwPC0G1AQwOC0G2AQwNC0G3AQwMC0G4AQwLC0G5AQwKC0G6AQwJC0G7AQwIC0HGAQwHC0G8AQwGC0G9AQwFC0G+AQwEC0G/AQwDC0HAAQwCC0HCAQwBC0HBAQshAwNAAkACQAJAAkACQAJAAkACQAJAIAICfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJ/AkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgAgJ/AkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACfwJAAkACfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAC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iQEhAwykAgtBASABLQAAQd8ARw1nGiABQQFqIQEMXgtBigEhAyABIARGDaICIAIoAgAiACAEIAFraiEFIAEgAGtBAWohBgNAIAEtAAAgAEGMzwBqLQAARw1kIABBAUYN+gEgAEEBaiEAIAQgAUEBaiIBRw0ACyACIAU2AgAMogILQYsBIQMgASAERg2hAiACKAIAIgAgBCABa2ohBSABIABrQQJqIQYCQANAIAEtAAAgAEGOzwBqLQAARw1kIABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAIgBTYCAAyiAgsgAkEANgIAIAZBAWohAUECDGULQYwBIQMgASAERg2gAiACKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEHwzwBqLQAARw1jIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAIgBTYCAAyhAgsgAkEANgIAIAZBAWohAUEfDGQLQY0BIQMgASAERg2fAiACKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEHyzwBqLQAARw1iIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAIgBTYCAAygAgsgAkEANgIAIAZBAWohAUEJDGMLIAEgBEYEQEGOASEDDJ8CCwJAAkAgAS0AAEHJAGsOBwBiYmJiYgFiCyABQQFqIQFB+AAhAwyGAgsgAUEBaiEBQfkAIQMMhQILQY8BIQMgASAERg2dAiACKAIAIgAgBCABa2ohBSABIABrQQVqIQYCQANAIAEtAAAgAEGRzwBqLQAARw1gIABBBUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAIgBTYCAAyeAgsgAkEANgIAIAZBAWohAUEYDGELQZABIQMgASAERg2cAiACKAIAIgAgBCABa2ohBSABIABrQQJqIQYCQANAIAEtAAAgAEGXzwBqLQAARw1fIABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAIgBTYCAAydAgsgAkEANgIAIAZBAWohAUEXDGALQZEBIQMgASAERg2bAiACKAIAIgAgBCABa2ohBSABIABrQQZqIQYCQANAIAEtAAAgAEGazwBqLQAARw1eIABBBkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAIgBTYCAAycAgsgAkEANgIAIAZBAWohAUEV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JSIARQ0RIAJB5QA2AhwgAiABNgIUIAIgADYCDEEAIQMMtAELIAIoAgQhACACQQA2AgQgAiAAIAEQJSIARQ0gIAJB0wA2AhwgAiABNgIUIAIgADYCDEEAIQMMswELIAIoAgQhACACQQA2AgQgAiAAIAEQJSIARQ0iIAJB0gA2AhwgAiABNgIUIAIgADYCDEEAIQMMsgELIAIoAgQhACACQQA2AgQgAiAAIAEQJSIARQ0OIAJB5QA2AhwgAiABNgIUIAIgADYCDEEAIQMMsQELIAIoAgQhACACQQA2AgQgAiAAIAEQJSIARQ0dIAJB0wA2AhwgAiABNgIUIAIgADYCDEEAIQMMsAELIAIoAgQhACACQQA2AgQgAiAAIAEQJSIARQ0fIAJB0gA2AhwgAiABNgIUIAIgADYCDEEAIQMMrwELIABBP0cNASABQQFqCyEBQQUhAwyUAQtBACEDIAJBADYCHCACIAE2AhQgAkH9EjYCECACQQc2AgwMrAELIAJBADYCHCACIAE2AhQgAkHcCDYCECACQQc2AgxBACEDDKsBCyACKAIEIQAgAkEANgIEIAIgACABECUiAEUNByACQeUANgIcIAIgATYCFCACIAA2AgxBACEDDKoBCyACKAIEIQAgAkEANgIEIAIgACABECUiAEUNFiACQdMANgIcIAIgATYCFCACIAA2AgxBACEDDKkBCyACKAIEIQAgAkEANgIEIAIgACABECUiAEUNGCACQdIANgIcIAIgATYCFCACIAA2AgxBACEDDKgBCyACQQA2AhwgAiABNgIUIAJBxgo2AhAgAkEHNgIMQQAhAwynAQsgAigCBCEAIAJBADYCBCACIAAgARAlIgBFDQMgAkHlADYCHCACIAE2AhQgAiAANgIMQQAhAwymAQsgAigCBCEAIAJBADYCBCACIAAgARAlIgBFDRIgAkHTADYCHCACIAE2AhQgAiAANgIMQQAhAwylAQsgAigCBCEAIAJBADYCBCACIAAgARAlIgBFDRQgAkHSADYCHCACIAE2AhQgAiAANgIMQQAhAwykAQsgAigCBCEAIAJBADYCBCACIAAgARAlIgBFDQAgAkHlADYCHCACIAE2AhQgAiAANgIMQQAhAwyjAQtB1QAhAwyJAQsgAEEVRwRAIAJBADYCHCACIAE2AhQgAkG5DTYCECACQRo2AgxB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AkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIABB5ABrDvQDY2IAAWFhYWFhYQIDBAVhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhBgcICQoLDA0OD2FhYWFhEGFhYWFhYWFhYWFhEWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYRITFBUWFxgZGhthYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhHB0eHyAhIiMkJSYnKCkqKywtLi8wMTIzNDU2YTc4OTphYWFhYWFhYTthYWE8YWFhYT0+P2FhYWFhYWFhQGFhQWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYUJDREVGR0hJSktMTU5PUFFSU2FhYWFhYWFhVFVWV1hZWlthXF1hYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFeYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhX2BhC0HhJw8LQaQhDwtByywPC0H+MQ8LQcAkDwtBqyQPC0GNKA8LQeImDwtBgDAPC0G5Lw8LQdckDwtB7x8PC0HhHw8LQfofDwtB8iAPC0GoLw8LQa4yDwtBiDAPC0HsJw8LQYIiDwtBjh0PC0HQLg8LQcojDwtBxTIPC0HfHA8LQdIcDwtBxCAPC0HXIA8LQaIfDwtB7S4PC0GrMA8LQdQlDwtBzC4PC0H6Lg8LQfwrDwtB0jAPC0HxHQ8LQbsgDwtB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AAADAEGUCAsFBAAAAAUAQaQICwkGAAAABwAAAAgAQdwIC4otSW52YWxpZCBjaGFyIGluIHVybCBxdWVyeQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX2JvZHkAQ29udGVudC1MZW5ndGggb3ZlcmZsb3cAQ2h1bmsgc2l6ZSBvdmVyZmxvdwBSZXNwb25zZSBvdmVyZmxvdwBJbnZhbGlkIG1ldGhvZCBmb3IgSFRUUC94LnggcmVxdWVzdABJbnZhbGlkIG1ldGhvZCBmb3IgUlRTUC94LnggcmVxdWVzdABFeHBlY3RlZCBTT1VSQ0UgbWV0aG9kIGZvciBJQ0UveC54IHJlcXVlc3QASW52YWxpZCBjaGFyIGluIHVybCBmcmFnbWVudCBzdGFydABFeHBlY3RlZCBkb3QAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9zdGF0dXMASW52YWxpZCByZXNwb25zZSBzdGF0dXMASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucwBVc2VyIGNhbGxiYWNrIGVycm9yAGBvbl9yZXNldGAgY2FsbGJhY2sgZXJyb3IAYG9uX2NodW5rX2hlYWRlcmAgY2FsbGJhY2sgZXJyb3IAYG9uX21lc3NhZ2VfYmVnaW5gIGNhbGxiYWNrIGVycm9yAGBvbl9jaHVua19leHRlbnNpb25fdmFsdWVgIGNhbGxiYWNrIGVycm9yAGBvbl9zdGF0dXNfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl92ZXJzaW9uX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fdXJsX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9oZWFkZXJfdmFsdWVfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9tZXNzYWdlX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fbWV0aG9kX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25faGVhZGVyX2ZpZWxkX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfZXh0ZW5zaW9uX25hbWVgIGNhbGxiYWNrIGVycm9yAFVuZXhwZWN0ZWQgY2hhciBpbiB1cmwgc2VydmVyAEludmFsaWQgaGVhZGVyIHZhbHVlIGNoYXIASW52YWxpZCBoZWFkZXIgZmllbGQgY2hhcgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3ZlcnNpb24ASW52YWxpZCBtaW5vciB2ZXJzaW9uAEludmFsaWQgbWFqb3IgdmVyc2lvbgBFeHBlY3RlZCBzcGFjZSBhZnRlciB2ZXJzaW9uAEV4cGVjdGVkIENSTEYgYWZ0ZXIgdmVyc2lvbgBJbnZhbGlkIEhUVFAgdmVyc2lvbgBJbnZhbGlkIGhlYWRlciB0b2tlbgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3VybABJbnZhbGlkIGNoYXJhY3RlcnMgaW4gdXJsAFVuZXhwZWN0ZWQgc3RhcnQgY2hhciBpbiB1cmwARG91YmxlIEAgaW4gdXJsAEVtcHR5IENvbnRlbnQtTGVuZ3RoAEludmFsaWQgY2hhcmFjdGVyIGluIENvbnRlbnQtTGVuZ3RoAER1cGxpY2F0ZSBDb250ZW50LUxlbmd0aABJbnZhbGlkIGNoYXIgaW4gdXJsIHBhdGgAQ29udGVudC1MZW5ndGggY2FuJ3QgYmUgcHJlc2VudCB3aXRoIFRyYW5zZmVyLUVuY29kaW5nAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIHNpemUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfdmFsdWUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9jaHVua19leHRlbnNpb25fdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyB2YWx1ZQBNaXNzaW5nIGV4cGVjdGVkIExGIGFmdGVyIGhlYWRlciB2YWx1ZQBJbnZhbGlkIGBUcmFuc2Zlci1FbmNvZGluZ2AgaGVhZGVyIHZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgcXVvdGUgdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyBxdW90ZWQgdmFsdWUAUGF1c2VkIGJ5IG9uX2hlYWRlcnNfY29tcGxldGUASW52YWxpZCBFT0Ygc3RhdGUAb25fcmVzZXQgcGF1c2UAb25fY2h1bmtfaGVhZGVyIHBhdXNlAG9uX21lc3NhZ2VfYmVnaW4gcGF1c2UAb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlIHBhdXNlAG9uX3N0YXR1c19jb21wbGV0ZSBwYXVzZQBvbl92ZXJzaW9uX2NvbXBsZXRlIHBhdXNlAG9uX3VybF9jb21wbGV0ZSBwYXVzZQBvbl9jaHVua19jb21wbGV0ZSBwYXVzZQBvbl9oZWFkZXJfdmFsdWVfY29tcGxldGUgcGF1c2UAb25fbWVzc2FnZV9jb21wbGV0ZSBwYXVzZQBvbl9tZXRob2RfY29tcGxldGUgcGF1c2UAb25faGVhZGVyX2ZpZWxkX2NvbXBsZXRlIHBhdXNlAG9uX2NodW5rX2V4dGVuc2lvbl9uYW1lIHBhdXNlAFVuZXhwZWN0ZWQgc3BhY2UgYWZ0ZXIgc3RhcnQgbGluZQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX2NodW5rX2V4dGVuc2lvbl9uYW1lAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgbmFtZQBQYXVzZSBvbiBDT05ORUNUL1VwZ3JhZGUAUGF1c2Ugb24gUFJJL1VwZ3JhZGUARXhwZWN0ZWQgSFRUUC8yIENvbm5lY3Rpb24gUHJlZmFjZQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX21ldGhvZABFeHBlY3RlZCBzcGFjZSBhZnRlciBtZXRob2QAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfZmllbGQAUGF1c2VkAEludmFsaWQgd29yZCBlbmNvdW50ZXJlZABJbnZhbGlkIG1ldGhvZCBlbmNvdW50ZXJlZABVbmV4cGVjdGVkIGNoYXIgaW4gdXJsIHNjaGVtYQBSZXF1ZXN0IGhhcyBpbnZhbGlkIGBUcmFuc2Zlci1FbmNvZGluZ2AAU1dJVENIX1BST1hZAFVTRV9QUk9YWQBNS0FDVElWSVRZAFVOUFJPQ0VTU0FCTEVfRU5USVRZAENPUFkATU9WRURfUEVSTUFORU5UTFkAVE9PX0VBUkxZAE5PVElGWQBGQUlMRURfREVQRU5ERU5DWQBCQURfR0FURVdBWQBQTEFZAFBVVABDSEVDS09VVABHQVRFV0FZX1RJTUVPVVQAUkVRVUVTVF9USU1FT1VUAE5FVFdPUktfQ09OTkVDVF9USU1FT1VUAENPTk5FQ1RJT05fVElNRU9VVABMT0dJTl9USU1FT1VUAE5FVFdPUktfUkVBRF9USU1FT1VUAFBPU1QATUlTRElSRUNURURfUkVRVUVTVABDTElFTlRfQ0xPU0VEX1JFUVVFU1QAQ0xJRU5UX0NMT1NFRF9MT0FEX0JBTEFOQ0VEX1JFUVVFU1QAQkFEX1JFUVVFU1QASFRUUF9SRVFVRVNUX1NFTlRfVE9fSFRUUFNfUE9SVABSRVBPUlQASU1fQV9URUFQT1QAUkVTRVRfQ09OVEVOVABOT19DT05URU5UAFBBUlRJQUxfQ09OVEVOVABIUEVfSU5WQUxJRF9DT05TVEFOVABIUEVfQ0JfUkVTRVQAR0VUAEhQRV9TVFJJQ1QAQ09ORkxJQ1QAVEVNUE9SQVJZX1JFRElSRUNUAFBFUk1BTkVOVF9SRURJUkVDVABDT05ORUNUAE1VTFRJX1NUQVRVUwBIUEVfSU5WQUxJRF9TVEFUVVMAVE9PX01BTllfUkVRVUVTVFMARUFSTFlfSElOVFMAVU5BVkFJTEFCTEVfRk9SX0xFR0FMX1JFQVNPTlMAT1BUSU9OUwBTV0lUQ0hJTkdfUFJPVE9DT0xTAFZBUklBTlRfQUxTT19ORUdPVElBVEVTAE1VTFRJUExFX0NIT0lDRVMASU5URVJOQUxfU0VSVkVSX0VSUk9SAFdFQl9TRVJWRVJfVU5LTk9XTl9FUlJPUgBSQUlMR1VOX0VSUk9SAElERU5USVRZX1BST1ZJREVSX0FVVEhFTlRJQ0FUSU9OX0VSUk9SAFNTTF9DRVJUSUZJQ0FURV9FUlJPUgBJTlZBTElEX1hfRk9SV0FSREVEX0ZPUgBTRVRfUEFSQU1FVEVSAEdFVF9QQVJBTUVURVIASFBFX1VTRVIAU0VFX09USEVSAEhQRV9DQl9DSFVOS19IRUFERVIATUtDQUxFTkRBUgBTRVRVUABXRUJfU0VSVkVSX0lTX0RPV04AVEVBUkRPV04ASFBFX0NMT1NFRF9DT05ORUNUSU9OAEhFVVJJU1RJQ19FWFBJUkFUSU9OAERJU0NPTk5FQ1RFRF9PUEVSQVRJT04ATk9OX0FVVEhPUklUQVRJVkVfSU5GT1JNQVRJT04ASFBFX0lOVkFMSURfVkVSU0lPTgBIUEVfQ0JfTUVTU0FHRV9CRUdJTgBTSVRFX0lTX0ZST1pFTgBIUEVfSU5WQUxJRF9IRUFERVJfVE9LRU4ASU5WQUxJRF9UT0tFTgBGT1JCSURERU4ARU5IQU5DRV9ZT1VSX0NBTE0ASFBFX0lOVkFMSURfVVJMAEJMT0NLRURfQllfUEFSRU5UQUxfQ09OVFJPTABNS0NPTABBQ0wASFBFX0lOVEVSTkFMAFJFUVVFU1RfSEVBREVSX0ZJRUxEU19UT09fTEFSR0VfVU5PRkZJQ0lBTABIUEVfT0sAVU5MSU5LAFVOTE9DSwBQUkkAUkVUUllfV0lUSABIUEVfSU5WQUxJRF9DT05URU5UX0xFTkdUSABIUEVfVU5FWFBFQ1RFRF9DT05URU5UX0xFTkdUSABGTFVTSABQUk9QUEFUQ0gATS1TRUFSQ0gAVVJJX1RPT19MT05HAFBST0NFU1NJTkcATUlTQ0VMTEFORU9VU19QRVJTSVNURU5UX1dBUk5JTkcATUlTQ0VMTEFORU9VU19XQVJOSU5HAEhQRV9JTlZBTElEX1RSQU5TRkVSX0VOQ09ESU5HAEV4cGVjdGVkIENSTEYASFBFX0lOVkFMSURfQ0hVTktfU0laRQBNT1ZFAENPTlRJTlVFAEhQRV9DQl9TVEFUVVNfQ09NUExFVEUASFBFX0NCX0hFQURFUlNfQ09NUExFVEUASFBFX0NCX1ZFUlNJT05fQ09NUExFVEUASFBFX0NCX1VSTF9DT01QTEVURQBIUEVfQ0JfQ0hVTktfQ09NUExFVEUASFBFX0NCX0hFQURFUl9WQUxVRV9DT01QTEVURQBIUEVfQ0JfQ0hVTktfRVhURU5TSU9OX1ZBTFVFX0NPTVBMRVRFAEhQRV9DQl9DSFVOS19FWFRFTlNJT05fTkFNRV9DT01QTEVURQBIUEVfQ0JfTUVTU0FHRV9DT01QTEVURQBIUEVfQ0JfTUVUSE9EX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJfRklFTERfQ09NUExFVEUAREVMRVRFAEhQRV9JTlZBTElEX0VPRl9TVEFURQBJTlZBTElEX1NTTF9DRVJUSUZJQ0FURQBQQVVTRQBOT19SRVNQT05TRQBVTlNVUFBPUlRFRF9NRURJQV9UWVBFAEdPTkUATk9UX0FDQ0VQVEFCTEUAU0VSVklDRV9VTkFWQUlMQUJMRQBSQU5HRV9OT1RfU0FUSVNGSUFCTEUAT1JJR0lOX0lTX1VOUkVBQ0hBQkxFAFJFU1BPTlNFX0lTX1NUQUxFAFBVUkdFAE1FUkdFAFJFUVVFU1RfSEVBREVSX0ZJRUxEU19UT09fTEFSR0UAUkVRVUVTVF9IRUFERVJfVE9PX0xBUkdFAFBBWUxPQURfVE9PX0xBUkdFAElOU1VGRklDSUVOVF9TVE9SQUdFAEhQRV9QQVVTRURfVVBHUkFERQBIUEVfUEFVU0VEX0gyX1VQR1JBREUAU09VUkNFAEFOTk9VTkNFAFRSQUNFAEhQRV9VTkVYUEVDVEVEX1NQQUNFAERFU0NSSUJFAFVOU1VCU0NSSUJFAFJFQ09SRABIUEVfSU5WQUxJRF9NRVRIT0QATk9UX0ZPVU5EAFBST1BGSU5EAFVOQklORABSRUJJTkQAVU5BVVRIT1JJWkVEAE1FVEhPRF9OT1RfQUxMT1dFRABIVFRQX1ZFUlNJT05fTk9UX1NVUFBPUlRFRABBTFJFQURZX1JFUE9SVEVEAEFDQ0VQVEVEAE5PVF9JTVBMRU1FTlRFRABMT09QX0RFVEVDVEVEAEhQRV9DUl9FWFBFQ1RFRABIUEVfTEZfRVhQRUNURUQAQ1JFQVRFRABJTV9VU0VEAEhQRV9QQVVTRUQAVElNRU9VVF9PQ0NVUkVEAFBBWU1FTlRfUkVRVUlSRUQAUFJFQ09ORElUSU9OX1JFUVVJUkVEAFBST1hZX0FVVEhFTlRJQ0FUSU9OX1JFUVVJUkVEAE5FVFdPUktfQVVUSEVOVElDQVRJT05fUkVRVUlSRUQATEVOR1RIX1JFUVVJUkVEAFNTTF9DRVJUSUZJQ0FURV9SRVFVSVJFRABVUEdSQURFX1JFUVVJUkVEAFBBR0VfRVhQSVJFRABQUkVDT05ESVRJT05fRkFJTEVEAEVYUEVDVEFUSU9OX0ZBSUxFRABSRVZBTElEQVRJT05fRkFJTEVEAFNTTF9IQU5EU0hBS0VfRkFJTEVEAExPQ0tFRABUUkFOU0ZPUk1BVElPTl9BUFBMSUVEAE5PVF9NT0RJRklFRABOT1RfRVhURU5ERUQAQkFORFdJRFRIX0xJTUlUX0VYQ0VFREVEAFNJVEVfSVNfT1ZFUkxPQURFRABIRUFEAEV4cGVjdGVkIEhUVFAvAABeEwAAJhMAADAQAADwFwAAnRMAABUSAAA5FwAA8BIAAAoQAAB1EgAArRIAAIITAABPFAAAfxAAAKAVAAAjFAAAiRIAAIsUAABNFQAA1BEAAM8UAAAQGAAAyRYAANwWAADBEQAA4BcAALsUAAB0FAAAfBUAAOUUAAAIFwAAHxAAAGUVAACjFAAAKBUAAAIVAACZFQAALBAAAIsZAABPDwAA1A4AAGoQAADOEAAAAhcAAIkOAABuEwAAHBMAAGYUAABWFwAAwRMAAM0TAABsEwAAaBcAAGYXAABfFwAAIhMAAM4PAABpDgAA2A4AAGMWAADLEwAAqg4AACgXAAAmFwAAxRMAAF0WAADoEQAAZxMAAGUTAADyFgAAcxMAAB0XAAD5FgAA8xEAAM8OAADOFQAADBIAALMRAAClEQAAYRAAADIXAAC7EwBB+TULAQEAQZA2C+ABAQECAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAQf03CwEBAEGROAteAgMCAgICAgAAAgIAAgIAAgICAgICAgICAgAEAAAAAAACAgICAgICAgICAgICAgICAgICAgICAgICAgAAAAICAgICAgICAgICAgICAgICAgICAgICAgICAgICAAIAAgBB/TkLAQEAQZE6C14CAAICAgICAAACAgACAgACAgICAgICAgICAAMABAAAAAICAgICAgICAgICAgICAgICAgICAgICAgICAAAAAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAAgACAEHwOwsNbG9zZWVlcC1hbGl2ZQBBiTwLAQEAQaA8C+ABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAQYk+CwEBAEGgPgvnAQEBAQEBAQEBAQEBAQIBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBY2h1bmtlZABBsMAAC18BAQABAQEBAQAAAQEAAQEAAQEBAQEBAQEBAQAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEAAQBBkMIACyFlY3Rpb25lbnQtbGVuZ3Rob25yb3h5LWNvbm5lY3Rpb24AQcDCAAstcmFuc2Zlci1lbmNvZGluZ3BncmFkZQ0KDQoNClNNDQoNClRUUC9DRS9UU1AvAEH5wgALBQECAAEDAEGQwwAL4AEEAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQBB+cQACwUBAgABAwBBkMUAC+ABBAEBBQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAQfnGAAsEAQAAAQBBkccAC98BAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQBB+sgACwQBAAACAEGQyQALXwMEAAAEBAQEBAQEBAQEBAUEBAQEBAQEBAQEBAQABAAGBwQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEAAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAEAEH6ygALBAEAAAEAQZDLAAsBAQBBqssAC0ECAAAAAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwBB+swACwQBAAABAEGQzQALAQEAQZrNAAsGAgAAAAACAEGxzQALOgMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAQfDOAAuWAU5PVU5DRUVDS09VVE5FQ1RFVEVDUklCRUxVU0hFVEVBRFNFQVJDSFJHRUNUSVZJVFlMRU5EQVJWRU9USUZZUFRJT05TQ0hTRUFZU1RBVENIR0VPUkRJUkVDVE9SVFJDSFBBUkFNRVRFUlVSQ0VCU0NSSUJFQVJET1dOQUNFSU5ETktDS1VCU0NSSUJFSFRUUC9BRFRQLw==', 'base64') -/** - * Verifies that the given val is a valid HTTP token - * per the rules defined in RFC 7230 - * See https://tools.ietf.org/html/rfc7230#section-3.2.6 - */ -const tokenRegExp = /^[\^_`a-zA-Z\-0-9!#$%&'*+.|~]+$/ -/** - * Matches if val contains an invalid field-vchar - * field-value = *( field-content / obs-fold ) - * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ] - * field-vchar = VCHAR / obs-text - */ -const headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/ +/***/ }), -// Verifies that a given path is valid does not contain control chars \x00 to \x20 -const invalidPathRegex = /[^\u0021-\u00ff]/ +/***/ 9298: +/***/ ((__unused_webpack_module, exports) => { -const kHandler = Symbol('handler') -const channels = {} +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.enumToMap = void 0; +function enumToMap(obj) { + const res = {}; + Object.keys(obj).forEach((key) => { + const value = obj[key]; + if (typeof value === 'number') { + res[key] = value; + } + }); + return res; +} +exports.enumToMap = enumToMap; +//# sourceMappingURL=utils.js.map -let extractBody +/***/ }), -try { - const diagnosticsChannel = __nccwpck_require__(1637) - channels.create = diagnosticsChannel.channel('undici:request:create') - channels.bodySent = diagnosticsChannel.channel('undici:request:bodySent') - channels.headers = diagnosticsChannel.channel('undici:request:headers') - channels.trailers = diagnosticsChannel.channel('undici:request:trailers') - channels.error = diagnosticsChannel.channel('undici:request:error') -} catch { - channels.create = { hasSubscribers: false } - channels.bodySent = { hasSubscribers: false } - channels.headers = { hasSubscribers: false } - channels.trailers = { hasSubscribers: false } - channels.error = { hasSubscribers: false } -} +/***/ 5955: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -class Request { - constructor (origin, { - path, - method, - body, - headers, - query, - idempotent, - blocking, - upgrade, - headersTimeout, - bodyTimeout, - reset, - throwOnError, - expectContinue - }, handler) { - if (typeof path !== 'string') { - throw new InvalidArgumentError('path must be a string') - } else if ( - path[0] !== '/' && - !(path.startsWith('http://') || path.startsWith('https://')) && - method !== 'CONNECT' - ) { - throw new InvalidArgumentError('path must be an absolute URL or start with a slash') - } else if (invalidPathRegex.exec(path) !== null) { - throw new InvalidArgumentError('invalid request path') - } - if (typeof method !== 'string') { - throw new InvalidArgumentError('method must be a string') - } else if (tokenRegExp.exec(method) === null) { - throw new InvalidArgumentError('invalid request method') - } - if (upgrade && typeof upgrade !== 'string') { - throw new InvalidArgumentError('upgrade must be a string') - } +const { kClients } = __nccwpck_require__(7417) +const Agent = __nccwpck_require__(4779) +const { + kAgent, + kMockAgentSet, + kMockAgentGet, + kDispatches, + kIsMockActive, + kNetConnect, + kGetNetConnect, + kOptions, + kFactory +} = __nccwpck_require__(4755) +const MockClient = __nccwpck_require__(4111) +const MockPool = __nccwpck_require__(2958) +const { matchValue, buildMockOptions } = __nccwpck_require__(6471) +const { InvalidArgumentError, UndiciError } = __nccwpck_require__(329) +const Dispatcher = __nccwpck_require__(5137) +const Pluralizer = __nccwpck_require__(5231) +const PendingInterceptorsFormatter = __nccwpck_require__(9212) - if (headersTimeout != null && (!Number.isFinite(headersTimeout) || headersTimeout < 0)) { - throw new InvalidArgumentError('invalid headersTimeout') - } +class MockAgent extends Dispatcher { + constructor (opts) { + super(opts) - if (bodyTimeout != null && (!Number.isFinite(bodyTimeout) || bodyTimeout < 0)) { - throw new InvalidArgumentError('invalid bodyTimeout') - } + this[kNetConnect] = true + this[kIsMockActive] = true - if (reset != null && typeof reset !== 'boolean') { - throw new InvalidArgumentError('invalid reset') + // Instantiate Agent and encapsulate + if ((opts?.agent && typeof opts.agent.dispatch !== 'function')) { + throw new InvalidArgumentError('Argument opts.agent must implement Agent') } + const agent = opts?.agent ? opts.agent : new Agent(opts) + this[kAgent] = agent - if (expectContinue != null && typeof expectContinue !== 'boolean') { - throw new InvalidArgumentError('invalid expectContinue') - } + this[kClients] = agent[kClients] + this[kOptions] = buildMockOptions(opts) + } - this.headersTimeout = headersTimeout + get (origin) { + let dispatcher = this[kMockAgentGet](origin) - this.bodyTimeout = bodyTimeout + if (!dispatcher) { + dispatcher = this[kFactory](origin) + this[kMockAgentSet](origin, dispatcher) + } + return dispatcher + } - this.throwOnError = throwOnError === true + dispatch (opts, handler) { + // Call MockAgent.get to perform additional setup before dispatching as normal + this.get(opts.origin) + return this[kAgent].dispatch(opts, handler) + } - this.method = method + async close () { + await this[kAgent].close() + this[kClients].clear() + } - this.abort = null + deactivate () { + this[kIsMockActive] = false + } - if (body == null) { - this.body = null - } else if (util.isStream(body)) { - this.body = body - - const rState = this.body._readableState - if (!rState || !rState.autoDestroy) { - this.endHandler = function autoDestroy () { - util.destroy(this) - } - this.body.on('end', this.endHandler) - } + activate () { + this[kIsMockActive] = true + } - this.errorHandler = err => { - if (this.abort) { - this.abort(err) - } else { - this.error = err - } + enableNetConnect (matcher) { + if (typeof matcher === 'string' || typeof matcher === 'function' || matcher instanceof RegExp) { + if (Array.isArray(this[kNetConnect])) { + this[kNetConnect].push(matcher) + } else { + this[kNetConnect] = [matcher] } - this.body.on('error', this.errorHandler) - } else if (util.isBuffer(body)) { - this.body = body.byteLength ? body : null - } else if (ArrayBuffer.isView(body)) { - this.body = body.buffer.byteLength ? Buffer.from(body.buffer, body.byteOffset, body.byteLength) : null - } else if (body instanceof ArrayBuffer) { - this.body = body.byteLength ? Buffer.from(body) : null - } else if (typeof body === 'string') { - this.body = body.length ? Buffer.from(body) : null - } else if (util.isFormDataLike(body) || util.isIterable(body) || util.isBlobLike(body)) { - this.body = body + } else if (typeof matcher === 'undefined') { + this[kNetConnect] = true } else { - throw new InvalidArgumentError('body must be a string, a Buffer, a Readable stream, an iterable, or an async iterable') + throw new InvalidArgumentError('Unsupported matcher. Must be one of String|Function|RegExp.') } + } - this.completed = false + disableNetConnect () { + this[kNetConnect] = false + } - this.aborted = false + // This is required to bypass issues caused by using global symbols - see: + // https://github.com/nodejs/undici/issues/1447 + get isMockActive () { + return this[kIsMockActive] + } - this.upgrade = upgrade || null + [kMockAgentSet] (origin, dispatcher) { + this[kClients].set(origin, dispatcher) + } - this.path = query ? util.buildURL(path, query) : path + [kFactory] (origin) { + const mockOptions = Object.assign({ agent: this }, this[kOptions]) + return this[kOptions] && this[kOptions].connections === 1 + ? new MockClient(origin, mockOptions) + : new MockPool(origin, mockOptions) + } - this.origin = origin + [kMockAgentGet] (origin) { + // First check if we can immediately find it + const client = this[kClients].get(origin) + if (client) { + return client + } - this.idempotent = idempotent == null - ? method === 'HEAD' || method === 'GET' - : idempotent + // If the origin is not a string create a dummy parent pool and return to user + if (typeof origin !== 'string') { + const dispatcher = this[kFactory]('http://localhost:9999') + this[kMockAgentSet](origin, dispatcher) + return dispatcher + } - this.blocking = blocking == null ? false : blocking + // If we match, create a pool and assign the same dispatches + for (const [keyMatcher, nonExplicitDispatcher] of Array.from(this[kClients])) { + if (nonExplicitDispatcher && typeof keyMatcher !== 'string' && matchValue(keyMatcher, origin)) { + const dispatcher = this[kFactory](origin) + this[kMockAgentSet](origin, dispatcher) + dispatcher[kDispatches] = nonExplicitDispatcher[kDispatches] + return dispatcher + } + } + } - this.reset = reset == null ? null : reset + [kGetNetConnect] () { + return this[kNetConnect] + } - this.host = null + pendingInterceptors () { + const mockAgentClients = this[kClients] - this.contentLength = null + return Array.from(mockAgentClients.entries()) + .flatMap(([origin, scope]) => scope[kDispatches].map(dispatch => ({ ...dispatch, origin }))) + .filter(({ pending }) => pending) + } - this.contentType = null + assertNoPendingInterceptors ({ pendingInterceptorsFormatter = new PendingInterceptorsFormatter() } = {}) { + const pending = this.pendingInterceptors() - this.headers = '' + if (pending.length === 0) { + return + } - // Only for H2 - this.expectContinue = expectContinue != null ? expectContinue : false + const pluralizer = new Pluralizer('interceptor', 'interceptors').pluralize(pending.length) - if (Array.isArray(headers)) { - if (headers.length % 2 !== 0) { - throw new InvalidArgumentError('headers array must be even') - } - for (let i = 0; i < headers.length; i += 2) { - processHeader(this, headers[i], headers[i + 1]) - } - } else if (headers && typeof headers === 'object') { - const keys = Object.keys(headers) - for (let i = 0; i < keys.length; i++) { - const key = keys[i] - processHeader(this, key, headers[key]) - } - } else if (headers != null) { - throw new InvalidArgumentError('headers must be an object or an array') - } + throw new UndiciError(` +${pluralizer.count} ${pluralizer.noun} ${pluralizer.is} pending: - if (util.isFormDataLike(this.body)) { - if (util.nodeMajor < 16 || (util.nodeMajor === 16 && util.nodeMinor < 8)) { - throw new InvalidArgumentError('Form-Data bodies are only supported in node v16.8 and newer.') - } +${pendingInterceptorsFormatter.format(pending)} +`.trim()) + } +} - if (!extractBody) { - extractBody = (__nccwpck_require__(1056).extractBody) - } +module.exports = MockAgent - const [bodyStream, contentType] = extractBody(body) - if (this.contentType == null) { - this.contentType = contentType - this.headers += `content-type: ${contentType}\r\n` - } - this.body = bodyStream.stream - this.contentLength = bodyStream.length - } else if (util.isBlobLike(body) && this.contentType == null && body.type) { - this.contentType = body.type - this.headers += `content-type: ${body.type}\r\n` - } - util.validateHandler(handler, method, upgrade) +/***/ }), - this.servername = util.getServerName(this.host) +/***/ 4111: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - this[kHandler] = handler - if (channels.create.hasSubscribers) { - channels.create.publish({ request: this }) + +const { promisify } = __nccwpck_require__(7975) +const Client = __nccwpck_require__(9143) +const { buildMockDispatch } = __nccwpck_require__(6471) +const { + kDispatches, + kMockAgent, + kClose, + kOriginalClose, + kOrigin, + kOriginalDispatch, + kConnected +} = __nccwpck_require__(4755) +const { MockInterceptor } = __nccwpck_require__(633) +const Symbols = __nccwpck_require__(7417) +const { InvalidArgumentError } = __nccwpck_require__(329) + +/** + * MockClient provides an API that extends the Client to influence the mockDispatches. + */ +class MockClient extends Client { + constructor (origin, opts) { + super(origin, opts) + + if (!opts || !opts.agent || typeof opts.agent.dispatch !== 'function') { + throw new InvalidArgumentError('Argument opts.agent must implement Agent') } + + this[kMockAgent] = opts.agent + this[kOrigin] = origin + this[kDispatches] = [] + this[kConnected] = 1 + this[kOriginalDispatch] = this.dispatch + this[kOriginalClose] = this.close.bind(this) + + this.dispatch = buildMockDispatch.call(this) + this.close = this[kClose] } - onBodySent (chunk) { - if (this[kHandler].onBodySent) { - try { - return this[kHandler].onBodySent(chunk) - } catch (err) { - this.abort(err) - } - } + get [Symbols.kConnected] () { + return this[kConnected] } - onRequestSent () { - if (channels.bodySent.hasSubscribers) { - channels.bodySent.publish({ request: this }) - } + /** + * Sets up the base interceptor for mocking replies from undici. + */ + intercept (opts) { + return new MockInterceptor(opts, this[kDispatches]) + } - if (this[kHandler].onRequestSent) { - try { - return this[kHandler].onRequestSent() - } catch (err) { - this.abort(err) - } - } + async [kClose] () { + await promisify(this[kOriginalClose])() + this[kConnected] = 0 + this[kMockAgent][Symbols.kClients].delete(this[kOrigin]) } +} - onConnect (abort) { - assert(!this.aborted) - assert(!this.completed) +module.exports = MockClient - if (this.error) { - abort(this.error) - } else { - this.abort = abort - return this[kHandler].onConnect(abort) - } + +/***/ }), + +/***/ 6843: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + + + +const { UndiciError } = __nccwpck_require__(329) + +const kMockNotMatchedError = Symbol.for('undici.error.UND_MOCK_ERR_MOCK_NOT_MATCHED') + +/** + * The request does not match any registered mock dispatches. + */ +class MockNotMatchedError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, MockNotMatchedError) + this.name = 'MockNotMatchedError' + this.message = message || 'The request does not match any registered mock dispatches' + this.code = 'UND_MOCK_ERR_MOCK_NOT_MATCHED' } - onHeaders (statusCode, headers, resume, statusText) { - assert(!this.aborted) - assert(!this.completed) + static [Symbol.hasInstance] (instance) { + return instance && instance[kMockNotMatchedError] === true + } - if (channels.headers.hasSubscribers) { - channels.headers.publish({ request: this, response: { statusCode, headers, statusText } }) - } + [kMockNotMatchedError] = true +} - try { - return this[kHandler].onHeaders(statusCode, headers, resume, statusText) - } catch (err) { - this.abort(err) +module.exports = { + MockNotMatchedError +} + + +/***/ }), + +/***/ 633: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + + + +const { getResponseData, buildKey, addMockDispatch } = __nccwpck_require__(6471) +const { + kDispatches, + kDispatchKey, + kDefaultHeaders, + kDefaultTrailers, + kContentLength, + kMockDispatch +} = __nccwpck_require__(4755) +const { InvalidArgumentError } = __nccwpck_require__(329) +const { buildURL } = __nccwpck_require__(7234) + +/** + * Defines the scope API for an interceptor reply + */ +class MockScope { + constructor (mockDispatch) { + this[kMockDispatch] = mockDispatch + } + + /** + * Delay a reply by a set amount in ms. + */ + delay (waitInMs) { + if (typeof waitInMs !== 'number' || !Number.isInteger(waitInMs) || waitInMs <= 0) { + throw new InvalidArgumentError('waitInMs must be a valid integer > 0') } + + this[kMockDispatch].delay = waitInMs + return this } - onData (chunk) { - assert(!this.aborted) - assert(!this.completed) + /** + * For a defined reply, never mark as consumed. + */ + persist () { + this[kMockDispatch].persist = true + return this + } - try { - return this[kHandler].onData(chunk) - } catch (err) { - this.abort(err) - return false + /** + * Allow one to define a reply for a set amount of matching requests. + */ + times (repeatTimes) { + if (typeof repeatTimes !== 'number' || !Number.isInteger(repeatTimes) || repeatTimes <= 0) { + throw new InvalidArgumentError('repeatTimes must be a valid integer > 0') } + + this[kMockDispatch].times = repeatTimes + return this } +} - onUpgrade (statusCode, headers, socket) { - assert(!this.aborted) - assert(!this.completed) +/** + * Defines an interceptor for a Mock + */ +class MockInterceptor { + constructor (opts, mockDispatches) { + if (typeof opts !== 'object') { + throw new InvalidArgumentError('opts must be an object') + } + if (typeof opts.path === 'undefined') { + throw new InvalidArgumentError('opts.path must be defined') + } + if (typeof opts.method === 'undefined') { + opts.method = 'GET' + } + // See https://github.com/nodejs/undici/issues/1245 + // As per RFC 3986, clients are not supposed to send URI + // fragments to servers when they retrieve a document, + if (typeof opts.path === 'string') { + if (opts.query) { + opts.path = buildURL(opts.path, opts.query) + } else { + // Matches https://github.com/nodejs/undici/blob/main/lib/web/fetch/index.js#L1811 + const parsedURL = new URL(opts.path, 'data://') + opts.path = parsedURL.pathname + parsedURL.search + } + } + if (typeof opts.method === 'string') { + opts.method = opts.method.toUpperCase() + } - return this[kHandler].onUpgrade(statusCode, headers, socket) + this[kDispatchKey] = buildKey(opts) + this[kDispatches] = mockDispatches + this[kDefaultHeaders] = {} + this[kDefaultTrailers] = {} + this[kContentLength] = false } - onComplete (trailers) { - this.onFinally() + createMockScopeDispatchData ({ statusCode, data, responseOptions }) { + const responseData = getResponseData(data) + const contentLength = this[kContentLength] ? { 'content-length': responseData.length } : {} + const headers = { ...this[kDefaultHeaders], ...contentLength, ...responseOptions.headers } + const trailers = { ...this[kDefaultTrailers], ...responseOptions.trailers } - assert(!this.aborted) + return { statusCode, data, headers, trailers } + } - this.completed = true - if (channels.trailers.hasSubscribers) { - channels.trailers.publish({ request: this, trailers }) + validateReplyParameters (replyParameters) { + if (typeof replyParameters.statusCode === 'undefined') { + throw new InvalidArgumentError('statusCode must be defined') } - - try { - return this[kHandler].onComplete(trailers) - } catch (err) { - // TODO (fix): This might be a bad idea? - this.onError(err) + if (typeof replyParameters.responseOptions !== 'object' || replyParameters.responseOptions === null) { + throw new InvalidArgumentError('responseOptions must be an object') } } - onError (error) { - this.onFinally() + /** + * Mock an undici request with a defined reply. + */ + reply (replyOptionsCallbackOrStatusCode) { + // Values of reply aren't available right now as they + // can only be available when the reply callback is invoked. + if (typeof replyOptionsCallbackOrStatusCode === 'function') { + // We'll first wrap the provided callback in another function, + // this function will properly resolve the data from the callback + // when invoked. + const wrappedDefaultsCallback = (opts) => { + // Our reply options callback contains the parameter for statusCode, data and options. + const resolvedData = replyOptionsCallbackOrStatusCode(opts) - if (channels.error.hasSubscribers) { - channels.error.publish({ request: this, error }) + // Check if it is in the right format + if (typeof resolvedData !== 'object' || resolvedData === null) { + throw new InvalidArgumentError('reply options callback must return an object') + } + + const replyParameters = { data: '', responseOptions: {}, ...resolvedData } + this.validateReplyParameters(replyParameters) + // Since the values can be obtained immediately we return them + // from this higher order function that will be resolved later. + return { + ...this.createMockScopeDispatchData(replyParameters) + } + } + + // Add usual dispatch data, but this time set the data parameter to function that will eventually provide data. + const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], wrappedDefaultsCallback) + return new MockScope(newMockDispatch) } - if (this.aborted) { - return + // We can have either one or three parameters, if we get here, + // we should have 1-3 parameters. So we spread the arguments of + // this function to obtain the parameters, since replyData will always + // just be the statusCode. + const replyParameters = { + statusCode: replyOptionsCallbackOrStatusCode, + data: arguments[1] === undefined ? '' : arguments[1], + responseOptions: arguments[2] === undefined ? {} : arguments[2] } - this.aborted = true + this.validateReplyParameters(replyParameters) - return this[kHandler].onError(error) + // Send in-already provided data like usual + const dispatchData = this.createMockScopeDispatchData(replyParameters) + const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], dispatchData) + return new MockScope(newMockDispatch) } - onFinally () { - if (this.errorHandler) { - this.body.off('error', this.errorHandler) - this.errorHandler = null + /** + * Mock an undici request with a defined error. + */ + replyWithError (error) { + if (typeof error === 'undefined') { + throw new InvalidArgumentError('error must be defined') } - if (this.endHandler) { - this.body.off('end', this.endHandler) - this.endHandler = null + const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], { error }) + return new MockScope(newMockDispatch) + } + + /** + * Set default reply headers on the interceptor for subsequent replies + */ + defaultReplyHeaders (headers) { + if (typeof headers === 'undefined') { + throw new InvalidArgumentError('headers must be defined') } + + this[kDefaultHeaders] = headers + return this } - // TODO: adjust to support H2 - addHeader (key, value) { - processHeader(this, key, value) + /** + * Set default reply trailers on the interceptor for subsequent replies + */ + defaultReplyTrailers (trailers) { + if (typeof trailers === 'undefined') { + throw new InvalidArgumentError('trailers must be defined') + } + + this[kDefaultTrailers] = trailers return this } - static [kHTTP1BuildRequest] (origin, opts, handler) { - // TODO: Migrate header parsing here, to make Requests - // HTTP agnostic - return new Request(origin, opts, handler) + /** + * Set reply content length header for replies on the interceptor + */ + replyContentLength () { + this[kContentLength] = true + return this } +} - static [kHTTP2BuildRequest] (origin, opts, handler) { - const headers = opts.headers - opts = { ...opts, headers: null } +module.exports.MockInterceptor = MockInterceptor +module.exports.MockScope = MockScope - const request = new Request(origin, opts, handler) - request.headers = {} +/***/ }), - if (Array.isArray(headers)) { - if (headers.length % 2 !== 0) { - throw new InvalidArgumentError('headers array must be even') - } - for (let i = 0; i < headers.length; i += 2) { - processHeader(request, headers[i], headers[i + 1], true) - } - } else if (headers && typeof headers === 'object') { - const keys = Object.keys(headers) - for (let i = 0; i < keys.length; i++) { - const key = keys[i] - processHeader(request, key, headers[key], true) - } - } else if (headers != null) { - throw new InvalidArgumentError('headers must be an object or an array') - } +/***/ 2958: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - return request - } - static [kHTTP2CopyHeaders] (raw) { - const rawHeaders = raw.split('\r\n') - const headers = {} - for (const header of rawHeaders) { - const [key, value] = header.split(': ') +const { promisify } = __nccwpck_require__(7975) +const Pool = __nccwpck_require__(4105) +const { buildMockDispatch } = __nccwpck_require__(6471) +const { + kDispatches, + kMockAgent, + kClose, + kOriginalClose, + kOrigin, + kOriginalDispatch, + kConnected +} = __nccwpck_require__(4755) +const { MockInterceptor } = __nccwpck_require__(633) +const Symbols = __nccwpck_require__(7417) +const { InvalidArgumentError } = __nccwpck_require__(329) - if (value == null || value.length === 0) continue +/** + * MockPool provides an API that extends the Pool to influence the mockDispatches. + */ +class MockPool extends Pool { + constructor (origin, opts) { + super(origin, opts) - if (headers[key]) headers[key] += `,${value}` - else headers[key] = value + if (!opts || !opts.agent || typeof opts.agent.dispatch !== 'function') { + throw new InvalidArgumentError('Argument opts.agent must implement Agent') } - return headers - } -} + this[kMockAgent] = opts.agent + this[kOrigin] = origin + this[kDispatches] = [] + this[kConnected] = 1 + this[kOriginalDispatch] = this.dispatch + this[kOriginalClose] = this.close.bind(this) -function processHeaderValue (key, val, skipAppend) { - if (val && typeof val === 'object') { - throw new InvalidArgumentError(`invalid ${key} header`) + this.dispatch = buildMockDispatch.call(this) + this.close = this[kClose] } - val = val != null ? `${val}` : '' - - if (headerCharRegex.exec(val) !== null) { - throw new InvalidArgumentError(`invalid ${key} header`) + get [Symbols.kConnected] () { + return this[kConnected] } - return skipAppend ? val : `${key}: ${val}\r\n` -} + /** + * Sets up the base interceptor for mocking replies from undici. + */ + intercept (opts) { + return new MockInterceptor(opts, this[kDispatches]) + } -function processHeader (request, key, val, skipAppend = false) { - if (val && (typeof val === 'object' && !Array.isArray(val))) { - throw new InvalidArgumentError(`invalid ${key} header`) - } else if (val === undefined) { - return - } - - if ( - request.host === null && - key.length === 4 && - key.toLowerCase() === 'host' - ) { - if (headerCharRegex.exec(val) !== null) { - throw new InvalidArgumentError(`invalid ${key} header`) - } - // Consumed by Client - request.host = val - } else if ( - request.contentLength === null && - key.length === 14 && - key.toLowerCase() === 'content-length' - ) { - request.contentLength = parseInt(val, 10) - if (!Number.isFinite(request.contentLength)) { - throw new InvalidArgumentError('invalid content-length header') - } - } else if ( - request.contentType === null && - key.length === 12 && - key.toLowerCase() === 'content-type' - ) { - request.contentType = val - if (skipAppend) request.headers[key] = processHeaderValue(key, val, skipAppend) - else request.headers += processHeaderValue(key, val) - } else if ( - key.length === 17 && - key.toLowerCase() === 'transfer-encoding' - ) { - throw new InvalidArgumentError('invalid transfer-encoding header') - } else if ( - key.length === 10 && - key.toLowerCase() === 'connection' - ) { - const value = typeof val === 'string' ? val.toLowerCase() : null - if (value !== 'close' && value !== 'keep-alive') { - throw new InvalidArgumentError('invalid connection header') - } else if (value === 'close') { - request.reset = true - } - } else if ( - key.length === 10 && - key.toLowerCase() === 'keep-alive' - ) { - throw new InvalidArgumentError('invalid keep-alive header') - } else if ( - key.length === 7 && - key.toLowerCase() === 'upgrade' - ) { - throw new InvalidArgumentError('invalid upgrade header') - } else if ( - key.length === 6 && - key.toLowerCase() === 'expect' - ) { - throw new NotSupportedError('expect header not supported') - } else if (tokenRegExp.exec(key) === null) { - throw new InvalidArgumentError('invalid header key') - } else { - if (Array.isArray(val)) { - for (let i = 0; i < val.length; i++) { - if (skipAppend) { - if (request.headers[key]) request.headers[key] += `,${processHeaderValue(key, val[i], skipAppend)}` - else request.headers[key] = processHeaderValue(key, val[i], skipAppend) - } else { - request.headers += processHeaderValue(key, val[i]) - } - } - } else { - if (skipAppend) request.headers[key] = processHeaderValue(key, val, skipAppend) - else request.headers += processHeaderValue(key, val) - } + async [kClose] () { + await promisify(this[kOriginalClose])() + this[kConnected] = 0 + this[kMockAgent][Symbols.kClients].delete(this[kOrigin]) } } -module.exports = Request +module.exports = MockPool /***/ }), -/***/ 1028: +/***/ 4755: /***/ ((module) => { + + module.exports = { + kAgent: Symbol('agent'), + kOptions: Symbol('options'), + kFactory: Symbol('factory'), + kDispatches: Symbol('dispatches'), + kDispatchKey: Symbol('dispatch key'), + kDefaultHeaders: Symbol('default headers'), + kDefaultTrailers: Symbol('default trailers'), + kContentLength: Symbol('content length'), + kMockAgent: Symbol('mock agent'), + kMockAgentSet: Symbol('mock agent set'), + kMockAgentGet: Symbol('mock agent get'), + kMockDispatch: Symbol('mock dispatch'), kClose: Symbol('close'), - kDestroy: Symbol('destroy'), - kDispatch: Symbol('dispatch'), - kUrl: Symbol('url'), - kWriting: Symbol('writing'), - kResuming: Symbol('resuming'), - kQueue: Symbol('queue'), - kConnect: Symbol('connect'), - kConnecting: Symbol('connecting'), - kHeadersList: Symbol('headers list'), - kKeepAliveDefaultTimeout: Symbol('default keep alive timeout'), - kKeepAliveMaxTimeout: Symbol('max keep alive timeout'), - kKeepAliveTimeoutThreshold: Symbol('keep alive timeout threshold'), - kKeepAliveTimeoutValue: Symbol('keep alive timeout'), - kKeepAlive: Symbol('keep alive'), - kHeadersTimeout: Symbol('headers timeout'), - kBodyTimeout: Symbol('body timeout'), - kServerName: Symbol('server name'), - kLocalAddress: Symbol('local address'), - kHost: Symbol('host'), - kNoRef: Symbol('no ref'), - kBodyUsed: Symbol('used'), - kRunning: Symbol('running'), - kBlocking: Symbol('blocking'), - kPending: Symbol('pending'), - kSize: Symbol('size'), - kBusy: Symbol('busy'), - kQueued: Symbol('queued'), - kFree: Symbol('free'), - kConnected: Symbol('connected'), - kClosed: Symbol('closed'), - kNeedDrain: Symbol('need drain'), - kReset: Symbol('reset'), - kDestroyed: Symbol.for('nodejs.stream.destroyed'), - kMaxHeadersSize: Symbol('max headers size'), - kRunningIdx: Symbol('running index'), - kPendingIdx: Symbol('pending index'), - kError: Symbol('error'), - kClients: Symbol('clients'), - kClient: Symbol('client'), - kParser: Symbol('parser'), - kOnDestroyed: Symbol('destroy callbacks'), - kPipelining: Symbol('pipelining'), - kSocket: Symbol('socket'), - kHostHeader: Symbol('host header'), - kConnector: Symbol('connector'), - kStrictContentLength: Symbol('strict content length'), - kMaxRedirections: Symbol('maxRedirections'), - kMaxRequests: Symbol('maxRequestsPerClient'), - kProxy: Symbol('proxy agent options'), - kCounter: Symbol('socket request counter'), - kInterceptors: Symbol('dispatch interceptors'), - kMaxResponseSize: Symbol('max response size'), - kHTTP2Session: Symbol('http2Session'), - kHTTP2SessionState: Symbol('http2Session state'), - kHTTP2BuildRequest: Symbol('http2 build request'), - kHTTP1BuildRequest: Symbol('http1 build request'), - kHTTP2CopyHeaders: Symbol('http2 copy headers'), - kHTTPConnVersion: Symbol('http connection version'), - kRetryHandlerDefaultRetry: Symbol('retry agent default retry'), - kConstruct: Symbol('constructable') + kOriginalClose: Symbol('original agent close'), + kOrigin: Symbol('origin'), + kIsMockActive: Symbol('is mock active'), + kNetConnect: Symbol('net connect'), + kGetNetConnect: Symbol('get net connect'), + kConnected: Symbol('connected') } /***/ }), -/***/ 5069: +/***/ 6471: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -const assert = __nccwpck_require__(2613) -const { kDestroyed, kBodyUsed } = __nccwpck_require__(1028) -const { IncomingMessage } = __nccwpck_require__(8611) -const stream = __nccwpck_require__(2203) -const net = __nccwpck_require__(9278) -const { InvalidArgumentError } = __nccwpck_require__(6738) -const { Blob } = __nccwpck_require__(181) -const nodeUtil = __nccwpck_require__(9023) -const { stringify } = __nccwpck_require__(3480) -const { headerNameLowerCasedRecord } = __nccwpck_require__(6356) - -const [nodeMajor, nodeMinor] = process.versions.node.split('.').map(v => Number(v)) - -function nop () {} +const { MockNotMatchedError } = __nccwpck_require__(6843) +const { + kDispatches, + kMockAgent, + kOriginalDispatch, + kOrigin, + kGetNetConnect +} = __nccwpck_require__(4755) +const { buildURL } = __nccwpck_require__(7234) +const { STATUS_CODES } = __nccwpck_require__(7067) +const { + types: { + isPromise + } +} = __nccwpck_require__(7975) -function isStream (obj) { - return obj && typeof obj === 'object' && typeof obj.pipe === 'function' && typeof obj.on === 'function' +function matchValue (match, value) { + if (typeof match === 'string') { + return match === value + } + if (match instanceof RegExp) { + return match.test(value) + } + if (typeof match === 'function') { + return match(value) === true + } + return false } -// based on https://github.com/node-fetch/fetch-blob/blob/8ab587d34080de94140b54f07168451e7d0b655e/index.js#L229-L241 (MIT License) -function isBlobLike (object) { - return (Blob && object instanceof Blob) || ( - object && - typeof object === 'object' && - (typeof object.stream === 'function' || - typeof object.arrayBuffer === 'function') && - /^(Blob|File)$/.test(object[Symbol.toStringTag]) +function lowerCaseEntries (headers) { + return Object.fromEntries( + Object.entries(headers).map(([headerName, headerValue]) => { + return [headerName.toLocaleLowerCase(), headerValue] + }) ) } -function buildURL (url, queryParams) { - if (url.includes('?') || url.includes('#')) { - throw new Error('Query params cannot be passed when url already contains "?" or "#".') - } - - const stringified = stringify(queryParams) +/** + * @param {import('../../index').Headers|string[]|Record} headers + * @param {string} key + */ +function getHeaderByName (headers, key) { + if (Array.isArray(headers)) { + for (let i = 0; i < headers.length; i += 2) { + if (headers[i].toLocaleLowerCase() === key.toLocaleLowerCase()) { + return headers[i + 1] + } + } - if (stringified) { - url += '?' + stringified + return undefined + } else if (typeof headers.get === 'function') { + return headers.get(key) + } else { + return lowerCaseEntries(headers)[key.toLocaleLowerCase()] } - - return url } -function parseURL (url) { - if (typeof url === 'string') { - url = new URL(url) +/** @param {string[]} headers */ +function buildHeadersFromArray (headers) { // fetch HeadersList + const clone = headers.slice() + const entries = [] + for (let index = 0; index < clone.length; index += 2) { + entries.push([clone[index], clone[index + 1]]) + } + return Object.fromEntries(entries) +} - if (!/^https?:/.test(url.origin || url.protocol)) { - throw new InvalidArgumentError('Invalid URL protocol: the URL must start with `http:` or `https:`.') +function matchHeaders (mockDispatch, headers) { + if (typeof mockDispatch.headers === 'function') { + if (Array.isArray(headers)) { // fetch HeadersList + headers = buildHeadersFromArray(headers) } - - return url + return mockDispatch.headers(headers ? lowerCaseEntries(headers) : {}) } - - if (!url || typeof url !== 'object') { - throw new InvalidArgumentError('Invalid URL: The URL argument must be a non-null object.') + if (typeof mockDispatch.headers === 'undefined') { + return true } - - if (!/^https?:/.test(url.origin || url.protocol)) { - throw new InvalidArgumentError('Invalid URL protocol: the URL must start with `http:` or `https:`.') + if (typeof headers !== 'object' || typeof mockDispatch.headers !== 'object') { + return false } - if (!(url instanceof URL)) { - if (url.port != null && url.port !== '' && !Number.isFinite(parseInt(url.port))) { - throw new InvalidArgumentError('Invalid URL: port must be a valid integer or a string representation of an integer.') - } - - if (url.path != null && typeof url.path !== 'string') { - throw new InvalidArgumentError('Invalid URL path: the path must be a string or null/undefined.') - } - - if (url.pathname != null && typeof url.pathname !== 'string') { - throw new InvalidArgumentError('Invalid URL pathname: the pathname must be a string or null/undefined.') - } - - if (url.hostname != null && typeof url.hostname !== 'string') { - throw new InvalidArgumentError('Invalid URL hostname: the hostname must be a string or null/undefined.') - } - - if (url.origin != null && typeof url.origin !== 'string') { - throw new InvalidArgumentError('Invalid URL origin: the origin must be a string or null/undefined.') - } - - const port = url.port != null - ? url.port - : (url.protocol === 'https:' ? 443 : 80) - let origin = url.origin != null - ? url.origin - : `${url.protocol}//${url.hostname}:${port}` - let path = url.path != null - ? url.path - : `${url.pathname || ''}${url.search || ''}` - - if (origin.endsWith('/')) { - origin = origin.substring(0, origin.length - 1) - } + for (const [matchHeaderName, matchHeaderValue] of Object.entries(mockDispatch.headers)) { + const headerValue = getHeaderByName(headers, matchHeaderName) - if (path && !path.startsWith('/')) { - path = `/${path}` + if (!matchValue(matchHeaderValue, headerValue)) { + return false } - // new URL(path, origin) is unsafe when `path` contains an absolute URL - // From https://developer.mozilla.org/en-US/docs/Web/API/URL/URL: - // If first parameter is a relative URL, second param is required, and will be used as the base URL. - // If first parameter is an absolute URL, a given second param will be ignored. - url = new URL(origin + path) } - - return url + return true } -function parseOrigin (url) { - url = parseURL(url) - - if (url.pathname !== '/' || url.search || url.hash) { - throw new InvalidArgumentError('invalid url') +function safeUrl (path) { + if (typeof path !== 'string') { + return path } - return url -} - -function getHostname (host) { - if (host[0] === '[') { - const idx = host.indexOf(']') + const pathSegments = path.split('?') - assert(idx !== -1) - return host.substring(1, idx) + if (pathSegments.length !== 2) { + return path } - const idx = host.indexOf(':') - if (idx === -1) return host - - return host.substring(0, idx) + const qp = new URLSearchParams(pathSegments.pop()) + qp.sort() + return [...pathSegments, qp.toString()].join('?') } -// IP addresses are not valid server names per RFC6066 -// > Currently, the only server names supported are DNS hostnames -function getServerName (host) { - if (!host) { - return null - } - - assert.strictEqual(typeof host, 'string') +function matchKey (mockDispatch, { path, method, body, headers }) { + const pathMatch = matchValue(mockDispatch.path, path) + const methodMatch = matchValue(mockDispatch.method, method) + const bodyMatch = typeof mockDispatch.body !== 'undefined' ? matchValue(mockDispatch.body, body) : true + const headersMatch = matchHeaders(mockDispatch, headers) + return pathMatch && methodMatch && bodyMatch && headersMatch +} - const servername = getHostname(host) - if (net.isIP(servername)) { - return '' +function getResponseData (data) { + if (Buffer.isBuffer(data)) { + return data + } else if (data instanceof Uint8Array) { + return data + } else if (data instanceof ArrayBuffer) { + return data + } else if (typeof data === 'object') { + return JSON.stringify(data) + } else { + return data.toString() } - - return servername } -function deepClone (obj) { - return JSON.parse(JSON.stringify(obj)) -} +function getMockDispatch (mockDispatches, key) { + const basePath = key.query ? buildURL(key.path, key.query) : key.path + const resolvedPath = typeof basePath === 'string' ? safeUrl(basePath) : basePath -function isAsyncIterable (obj) { - return !!(obj != null && typeof obj[Symbol.asyncIterator] === 'function') -} + // Match path + let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path }) => matchValue(safeUrl(path), resolvedPath)) + if (matchedMockDispatches.length === 0) { + throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`) + } -function isIterable (obj) { - return !!(obj != null && (typeof obj[Symbol.iterator] === 'function' || typeof obj[Symbol.asyncIterator] === 'function')) -} + // Match method + matchedMockDispatches = matchedMockDispatches.filter(({ method }) => matchValue(method, key.method)) + if (matchedMockDispatches.length === 0) { + throw new MockNotMatchedError(`Mock dispatch not matched for method '${key.method}' on path '${resolvedPath}'`) + } -function bodyLength (body) { - if (body == null) { - return 0 - } else if (isStream(body)) { - const state = body._readableState - return state && state.objectMode === false && state.ended === true && Number.isFinite(state.length) - ? state.length - : null - } else if (isBlobLike(body)) { - return body.size != null ? body.size : null - } else if (isBuffer(body)) { - return body.byteLength + // Match body + matchedMockDispatches = matchedMockDispatches.filter(({ body }) => typeof body !== 'undefined' ? matchValue(body, key.body) : true) + if (matchedMockDispatches.length === 0) { + throw new MockNotMatchedError(`Mock dispatch not matched for body '${key.body}' on path '${resolvedPath}'`) } - return null -} + // Match headers + matchedMockDispatches = matchedMockDispatches.filter((mockDispatch) => matchHeaders(mockDispatch, key.headers)) + if (matchedMockDispatches.length === 0) { + const headers = typeof key.headers === 'object' ? JSON.stringify(key.headers) : key.headers + throw new MockNotMatchedError(`Mock dispatch not matched for headers '${headers}' on path '${resolvedPath}'`) + } -function isDestroyed (stream) { - return !stream || !!(stream.destroyed || stream[kDestroyed]) + return matchedMockDispatches[0] } -function isReadableAborted (stream) { - const state = stream && stream._readableState - return isDestroyed(stream) && state && !state.endEmitted +function addMockDispatch (mockDispatches, key, data) { + const baseData = { timesInvoked: 0, times: 1, persist: false, consumed: false } + const replyData = typeof data === 'function' ? { callback: data } : { ...data } + const newMockDispatch = { ...baseData, ...key, pending: true, data: { error: null, ...replyData } } + mockDispatches.push(newMockDispatch) + return newMockDispatch } -function destroy (stream, err) { - if (stream == null || !isStream(stream) || isDestroyed(stream)) { - return - } - - if (typeof stream.destroy === 'function') { - if (Object.getPrototypeOf(stream).constructor === IncomingMessage) { - // See: https://github.com/nodejs/node/pull/38505/files - stream.socket = null +function deleteMockDispatch (mockDispatches, key) { + const index = mockDispatches.findIndex(dispatch => { + if (!dispatch.consumed) { + return false } - - stream.destroy(err) - } else if (err) { - process.nextTick((stream, err) => { - stream.emit('error', err) - }, stream, err) + return matchKey(dispatch, key) + }) + if (index !== -1) { + mockDispatches.splice(index, 1) } +} - if (stream.destroyed !== true) { - stream[kDestroyed] = true +function buildKey (opts) { + const { path, method, body, headers, query } = opts + return { + path, + method, + body, + headers, + query } } -const KEEPALIVE_TIMEOUT_EXPR = /timeout=(\d+)/ -function parseKeepAliveTimeout (val) { - const m = val.toString().match(KEEPALIVE_TIMEOUT_EXPR) - return m ? parseInt(m[1], 10) * 1000 : null +function generateKeyValues (data) { + const keys = Object.keys(data) + const result = [] + for (let i = 0; i < keys.length; ++i) { + const key = keys[i] + const value = data[key] + const name = Buffer.from(`${key}`) + if (Array.isArray(value)) { + for (let j = 0; j < value.length; ++j) { + result.push(name, Buffer.from(`${value[j]}`)) + } + } else { + result.push(name, Buffer.from(`${value}`)) + } + } + return result } /** - * Retrieves a header name and returns its lowercase value. - * @param {string | Buffer} value Header name - * @returns {string} + * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Status + * @param {number} statusCode */ -function headerNameToString (value) { - return headerNameLowerCasedRecord[value] || value.toLowerCase() +function getStatusText (statusCode) { + return STATUS_CODES[statusCode] || 'unknown' } -function parseHeaders (headers, obj = {}) { - // For H2 support - if (!Array.isArray(headers)) return headers - - for (let i = 0; i < headers.length; i += 2) { - const key = headers[i].toString().toLowerCase() - let val = obj[key] - - if (!val) { - if (Array.isArray(headers[i + 1])) { - obj[key] = headers[i + 1].map(x => x.toString('utf8')) - } else { - obj[key] = headers[i + 1].toString('utf8') - } - } else { - if (!Array.isArray(val)) { - val = [val] - obj[key] = val - } - val.push(headers[i + 1].toString('utf8')) - } - } - - // See https://github.com/nodejs/node/pull/46528 - if ('content-length' in obj && 'content-disposition' in obj) { - obj['content-disposition'] = Buffer.from(obj['content-disposition']).toString('latin1') +async function getResponse (body) { + const buffers = [] + for await (const data of body) { + buffers.push(data) } - - return obj + return Buffer.concat(buffers).toString('utf8') } -function parseRawHeaders (headers) { - const ret = [] - let hasContentLength = false - let contentDispositionIdx = -1 - - for (let n = 0; n < headers.length; n += 2) { - const key = headers[n + 0].toString() - const val = headers[n + 1].toString('utf8') +/** + * Mock dispatch function used to simulate undici dispatches + */ +function mockDispatch (opts, handler) { + // Get mock dispatch from built key + const key = buildKey(opts) + const mockDispatch = getMockDispatch(this[kDispatches], key) - if (key.length === 14 && (key === 'content-length' || key.toLowerCase() === 'content-length')) { - ret.push(key, val) - hasContentLength = true - } else if (key.length === 19 && (key === 'content-disposition' || key.toLowerCase() === 'content-disposition')) { - contentDispositionIdx = ret.push(key, val) - 1 - } else { - ret.push(key, val) - } - } + mockDispatch.timesInvoked++ - // See https://github.com/nodejs/node/pull/46528 - if (hasContentLength && contentDispositionIdx !== -1) { - ret[contentDispositionIdx] = Buffer.from(ret[contentDispositionIdx]).toString('latin1') + // Here's where we resolve a callback if a callback is present for the dispatch data. + if (mockDispatch.data.callback) { + mockDispatch.data = { ...mockDispatch.data, ...mockDispatch.data.callback(opts) } } - return ret -} - -function isBuffer (buffer) { - // See, https://github.com/mcollina/undici/pull/319 - return buffer instanceof Uint8Array || Buffer.isBuffer(buffer) -} + // Parse mockDispatch data + const { data: { statusCode, data, headers, trailers, error }, delay, persist } = mockDispatch + const { timesInvoked, times } = mockDispatch -function validateHandler (handler, method, upgrade) { - if (!handler || typeof handler !== 'object') { - throw new InvalidArgumentError('handler must be an object') - } + // If it's used up and not persistent, mark as consumed + mockDispatch.consumed = !persist && timesInvoked >= times + mockDispatch.pending = timesInvoked < times - if (typeof handler.onConnect !== 'function') { - throw new InvalidArgumentError('invalid onConnect method') + // If specified, trigger dispatch error + if (error !== null) { + deleteMockDispatch(this[kDispatches], key) + handler.onError(error) + return true } - if (typeof handler.onError !== 'function') { - throw new InvalidArgumentError('invalid onError method') + // Handle the request with a delay if necessary + if (typeof delay === 'number' && delay > 0) { + setTimeout(() => { + handleReply(this[kDispatches]) + }, delay) + } else { + handleReply(this[kDispatches]) } - if (typeof handler.onBodySent !== 'function' && handler.onBodySent !== undefined) { - throw new InvalidArgumentError('invalid onBodySent method') - } + function handleReply (mockDispatches, _data = data) { + // fetch's HeadersList is a 1D string array + const optsHeaders = Array.isArray(opts.headers) + ? buildHeadersFromArray(opts.headers) + : opts.headers + const body = typeof _data === 'function' + ? _data({ ...opts, headers: optsHeaders }) + : _data - if (upgrade || method === 'CONNECT') { - if (typeof handler.onUpgrade !== 'function') { - throw new InvalidArgumentError('invalid onUpgrade method') - } - } else { - if (typeof handler.onHeaders !== 'function') { - throw new InvalidArgumentError('invalid onHeaders method') + // util.types.isPromise is likely needed for jest. + if (isPromise(body)) { + // If handleReply is asynchronous, throwing an error + // in the callback will reject the promise, rather than + // synchronously throw the error, which breaks some tests. + // Rather, we wait for the callback to resolve if it is a + // promise, and then re-run handleReply with the new body. + body.then((newData) => handleReply(mockDispatches, newData)) + return } - if (typeof handler.onData !== 'function') { - throw new InvalidArgumentError('invalid onData method') - } + const responseData = getResponseData(body) + const responseHeaders = generateKeyValues(headers) + const responseTrailers = generateKeyValues(trailers) - if (typeof handler.onComplete !== 'function') { - throw new InvalidArgumentError('invalid onComplete method') - } + handler.onConnect?.(err => handler.onError(err), null) + handler.onHeaders?.(statusCode, responseHeaders, resume, getStatusText(statusCode)) + handler.onData?.(Buffer.from(responseData)) + handler.onComplete?.(responseTrailers) + deleteMockDispatch(mockDispatches, key) } -} - -// A body is disturbed if it has been read from and it cannot -// be re-used without losing state or data. -function isDisturbed (body) { - return !!(body && ( - stream.isDisturbed - ? stream.isDisturbed(body) || body[kBodyUsed] // TODO (fix): Why is body[kBodyUsed] needed? - : body[kBodyUsed] || - body.readableDidRead || - (body._readableState && body._readableState.dataEmitted) || - isReadableAborted(body) - )) -} - -function isErrored (body) { - return !!(body && ( - stream.isErrored - ? stream.isErrored(body) - : /state: 'errored'/.test(nodeUtil.inspect(body) - ))) -} - -function isReadable (body) { - return !!(body && ( - stream.isReadable - ? stream.isReadable(body) - : /state: 'readable'/.test(nodeUtil.inspect(body) - ))) -} -function getSocketInfo (socket) { - return { - localAddress: socket.localAddress, - localPort: socket.localPort, - remoteAddress: socket.remoteAddress, - remotePort: socket.remotePort, - remoteFamily: socket.remoteFamily, - timeout: socket.timeout, - bytesWritten: socket.bytesWritten, - bytesRead: socket.bytesRead - } -} + function resume () {} -async function * convertIterableToBuffer (iterable) { - for await (const chunk of iterable) { - yield Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk) - } + return true } -let ReadableStream -function ReadableStreamFrom (iterable) { - if (!ReadableStream) { - ReadableStream = (__nccwpck_require__(3774).ReadableStream) - } - - if (ReadableStream.from) { - return ReadableStream.from(convertIterableToBuffer(iterable)) - } +function buildMockDispatch () { + const agent = this[kMockAgent] + const origin = this[kOrigin] + const originalDispatch = this[kOriginalDispatch] - let iterator - return new ReadableStream( - { - async start () { - iterator = iterable[Symbol.asyncIterator]() - }, - async pull (controller) { - const { done, value } = await iterator.next() - if (done) { - queueMicrotask(() => { - controller.close() - }) + return function dispatch (opts, handler) { + if (agent.isMockActive) { + try { + mockDispatch.call(this, opts, handler) + } catch (error) { + if (error instanceof MockNotMatchedError) { + const netConnect = agent[kGetNetConnect]() + if (netConnect === false) { + throw new MockNotMatchedError(`${error.message}: subsequent request to origin ${origin} was not allowed (net.connect disabled)`) + } + if (checkNetConnect(netConnect, origin)) { + originalDispatch.call(this, opts, handler) + } else { + throw new MockNotMatchedError(`${error.message}: subsequent request to origin ${origin} was not allowed (net.connect is not enabled for this origin)`) + } } else { - const buf = Buffer.isBuffer(value) ? value : Buffer.from(value) - controller.enqueue(new Uint8Array(buf)) + throw error } - return controller.desiredSize > 0 - }, - async cancel (reason) { - await iterator.return() } - }, - 0 - ) -} - -// The chunk should be a FormData instance and contains -// all the required methods. -function isFormDataLike (object) { - return ( - object && - typeof object === 'object' && - typeof object.append === 'function' && - typeof object.delete === 'function' && - typeof object.get === 'function' && - typeof object.getAll === 'function' && - typeof object.has === 'function' && - typeof object.set === 'function' && - object[Symbol.toStringTag] === 'FormData' - ) -} - -function throwIfAborted (signal) { - if (!signal) { return } - if (typeof signal.throwIfAborted === 'function') { - signal.throwIfAborted() - } else { - if (signal.aborted) { - // DOMException not available < v17.0.0 - const err = new Error('The operation was aborted') - err.name = 'AbortError' - throw err + } else { + originalDispatch.call(this, opts, handler) } } } -function addAbortListener (signal, listener) { - if ('addEventListener' in signal) { - signal.addEventListener('abort', listener, { once: true }) - return () => signal.removeEventListener('abort', listener) +function checkNetConnect (netConnect, origin) { + const url = new URL(origin) + if (netConnect === true) { + return true + } else if (Array.isArray(netConnect) && netConnect.some((matcher) => matchValue(matcher, url.host))) { + return true } - signal.addListener('abort', listener) - return () => signal.removeListener('abort', listener) + return false } -const hasToWellFormed = !!String.prototype.toWellFormed - -/** - * @param {string} val - */ -function toUSVString (val) { - if (hasToWellFormed) { - return `${val}`.toWellFormed() - } else if (nodeUtil.toUSVString) { - return nodeUtil.toUSVString(val) +function buildMockOptions (opts) { + if (opts) { + const { agent, ...mockOptions } = opts + return mockOptions } - - return `${val}` -} - -// Parsed accordingly to RFC 9110 -// https://www.rfc-editor.org/rfc/rfc9110#field.content-range -function parseRangeHeader (range) { - if (range == null || range === '') return { start: 0, end: null, size: null } - - const m = range ? range.match(/^bytes (\d+)-(\d+)\/(\d+)?$/) : null - return m - ? { - start: parseInt(m[1]), - end: m[2] ? parseInt(m[2]) : null, - size: m[3] ? parseInt(m[3]) : null - } - : null } -const kEnumerableProperty = Object.create(null) -kEnumerableProperty.enumerable = true - module.exports = { - kEnumerableProperty, - nop, - isDisturbed, - isErrored, - isReadable, - toUSVString, - isReadableAborted, - isBlobLike, - parseOrigin, - parseURL, - getServerName, - isStream, - isIterable, - isAsyncIterable, - isDestroyed, - headerNameToString, - parseRawHeaders, - parseHeaders, - parseKeepAliveTimeout, - destroy, - bodyLength, - deepClone, - ReadableStreamFrom, - isBuffer, - validateHandler, - getSocketInfo, - isFormDataLike, - buildURL, - throwIfAborted, - addAbortListener, - parseRangeHeader, - nodeMajor, - nodeMinor, - nodeHasAutoSelectFamily: nodeMajor > 18 || (nodeMajor === 18 && nodeMinor >= 13), - safeHTTPMethods: ['GET', 'HEAD', 'OPTIONS', 'TRACE'] + getResponseData, + getMockDispatch, + addMockDispatch, + deleteMockDispatch, + buildKey, + generateKeyValues, + matchValue, + getResponse, + getStatusText, + mockDispatch, + buildMockDispatch, + checkNetConnect, + buildMockOptions, + getHeaderByName, + buildHeadersFromArray } /***/ }), -/***/ 7172: +/***/ 9212: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; - - -const Dispatcher = __nccwpck_require__(8016) -const { - ClientDestroyedError, - ClientClosedError, - InvalidArgumentError -} = __nccwpck_require__(6738) -const { kDestroy, kClose, kDispatch, kInterceptors } = __nccwpck_require__(1028) - -const kDestroyed = Symbol('destroyed') -const kClosed = Symbol('closed') -const kOnDestroyed = Symbol('onDestroyed') -const kOnClosed = Symbol('onClosed') -const kInterceptedDispatch = Symbol('Intercepted Dispatch') - -class DispatcherBase extends Dispatcher { - constructor () { - super() - - this[kDestroyed] = false - this[kOnDestroyed] = null - this[kClosed] = false - this[kOnClosed] = [] - } - - get destroyed () { - return this[kDestroyed] - } - - get closed () { - return this[kClosed] - } - - get interceptors () { - return this[kInterceptors] - } - - set interceptors (newInterceptors) { - if (newInterceptors) { - for (let i = newInterceptors.length - 1; i >= 0; i--) { - const interceptor = this[kInterceptors][i] - if (typeof interceptor !== 'function') { - throw new InvalidArgumentError('interceptor must be an function') - } - } - } - - this[kInterceptors] = newInterceptors - } - - close (callback) { - if (callback === undefined) { - return new Promise((resolve, reject) => { - this.close((err, data) => { - return err ? reject(err) : resolve(data) - }) - }) - } - - if (typeof callback !== 'function') { - throw new InvalidArgumentError('invalid callback') - } - - if (this[kDestroyed]) { - queueMicrotask(() => callback(new ClientDestroyedError(), null)) - return - } - - if (this[kClosed]) { - if (this[kOnClosed]) { - this[kOnClosed].push(callback) - } else { - queueMicrotask(() => callback(null, null)) - } - return - } - - this[kClosed] = true - this[kOnClosed].push(callback) - - const onClosed = () => { - const callbacks = this[kOnClosed] - this[kOnClosed] = null - for (let i = 0; i < callbacks.length; i++) { - callbacks[i](null, null) - } - } - - // Should not error. - this[kClose]() - .then(() => this.destroy()) - .then(() => { - queueMicrotask(onClosed) - }) - } - destroy (err, callback) { - if (typeof err === 'function') { - callback = err - err = null - } - if (callback === undefined) { - return new Promise((resolve, reject) => { - this.destroy(err, (err, data) => { - return err ? /* istanbul ignore next: should never error */ reject(err) : resolve(data) - }) - }) - } +const { Transform } = __nccwpck_require__(7075) +const { Console } = __nccwpck_require__(7540) - if (typeof callback !== 'function') { - throw new InvalidArgumentError('invalid callback') - } +const PERSISTENT = process.versions.icu ? '✅' : 'Y ' +const NOT_PERSISTENT = process.versions.icu ? '❌' : 'N ' - if (this[kDestroyed]) { - if (this[kOnDestroyed]) { - this[kOnDestroyed].push(callback) - } else { - queueMicrotask(() => callback(null, null)) +/** + * Gets the output of `console.table(…)` as a string. + */ +module.exports = class PendingInterceptorsFormatter { + constructor ({ disableColors } = {}) { + this.transform = new Transform({ + transform (chunk, _enc, cb) { + cb(null, chunk) } - return - } - - if (!err) { - err = new ClientDestroyedError() - } - - this[kDestroyed] = true - this[kOnDestroyed] = this[kOnDestroyed] || [] - this[kOnDestroyed].push(callback) + }) - const onDestroyed = () => { - const callbacks = this[kOnDestroyed] - this[kOnDestroyed] = null - for (let i = 0; i < callbacks.length; i++) { - callbacks[i](null, null) + this.logger = new Console({ + stdout: this.transform, + inspectOptions: { + colors: !disableColors && !process.env.CI } - } - - // Should not error. - this[kDestroy](err).then(() => { - queueMicrotask(onDestroyed) }) } - [kInterceptedDispatch] (opts, handler) { - if (!this[kInterceptors] || this[kInterceptors].length === 0) { - this[kInterceptedDispatch] = this[kDispatch] - return this[kDispatch](opts, handler) - } - - let dispatch = this[kDispatch].bind(this) - for (let i = this[kInterceptors].length - 1; i >= 0; i--) { - dispatch = this[kInterceptors][i](dispatch) - } - this[kInterceptedDispatch] = dispatch - return dispatch(opts, handler) - } - - dispatch (opts, handler) { - if (!handler || typeof handler !== 'object') { - throw new InvalidArgumentError('handler must be an object') - } - - try { - if (!opts || typeof opts !== 'object') { - throw new InvalidArgumentError('opts must be an object.') - } - - if (this[kDestroyed] || this[kOnDestroyed]) { - throw new ClientDestroyedError() - } - - if (this[kClosed]) { - throw new ClientClosedError() - } - - return this[kInterceptedDispatch](opts, handler) - } catch (err) { - if (typeof handler.onError !== 'function') { - throw new InvalidArgumentError('invalid onError method') - } - - handler.onError(err) + format (pendingInterceptors) { + const withPrettyHeaders = pendingInterceptors.map( + ({ method, path, data: { statusCode }, persist, times, timesInvoked, origin }) => ({ + Method: method, + Origin: origin, + Path: path, + 'Status code': statusCode, + Persistent: persist ? PERSISTENT : NOT_PERSISTENT, + Invocations: timesInvoked, + Remaining: persist ? Infinity : times - timesInvoked + })) - return false - } + this.logger.table(withPrettyHeaders) + return this.transform.read().toString() } } -module.exports = DispatcherBase - /***/ }), -/***/ 8016: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +/***/ 5231: +/***/ ((module) => { -"use strict"; -const EventEmitter = __nccwpck_require__(4434) +const singulars = { + pronoun: 'it', + is: 'is', + was: 'was', + this: 'this' +} -class Dispatcher extends EventEmitter { - dispatch () { - throw new Error('not implemented') - } +const plurals = { + pronoun: 'they', + is: 'are', + was: 'were', + this: 'these' +} - close () { - throw new Error('not implemented') +module.exports = class Pluralizer { + constructor (singular, plural) { + this.singular = singular + this.plural = plural } - destroy () { - throw new Error('not implemented') + pluralize (count) { + const one = count === 1 + const keys = one ? singulars : plurals + const noun = one ? this.singular : this.plural + return { ...keys, count, noun } } } -module.exports = Dispatcher - /***/ }), -/***/ 1056: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -"use strict"; +/***/ 5969: +/***/ ((module) => { -const Busboy = __nccwpck_require__(7483) -const util = __nccwpck_require__(5069) -const { - ReadableStreamFrom, - isBlobLike, - isReadableStreamLike, - readableStreamClose, - createDeferredPromise, - fullyReadBody -} = __nccwpck_require__(1612) -const { FormData } = __nccwpck_require__(322) -const { kState } = __nccwpck_require__(2895) -const { webidl } = __nccwpck_require__(8201) -const { DOMException, structuredClone } = __nccwpck_require__(3283) -const { Blob, File: NativeFile } = __nccwpck_require__(181) -const { kBodyUsed } = __nccwpck_require__(1028) -const assert = __nccwpck_require__(2613) -const { isErrored } = __nccwpck_require__(5069) -const { isUint8Array, isArrayBuffer } = __nccwpck_require__(8253) -const { File: UndiciFile } = __nccwpck_require__(7206) -const { parseMIMEType, serializeAMimeType } = __nccwpck_require__(4955) -let random -try { - const crypto = __nccwpck_require__(7598) - random = (max) => crypto.randomInt(0, max) -} catch { - random = (max) => Math.floor(Math.random(max)) -} +/** + * This module offers an optimized timer implementation designed for scenarios + * where high precision is not critical. + * + * The timer achieves faster performance by using a low-resolution approach, + * with an accuracy target of within 500ms. This makes it particularly useful + * for timers with delays of 1 second or more, where exact timing is less + * crucial. + * + * It's important to note that Node.js timers are inherently imprecise, as + * delays can occur due to the event loop being blocked by other operations. + * Consequently, timers may trigger later than their scheduled time. + */ -let ReadableStream = globalThis.ReadableStream +/** + * The fastNow variable contains the internal fast timer clock value. + * + * @type {number} + */ +let fastNow = 0 -/** @type {globalThis['File']} */ -const File = NativeFile ?? UndiciFile -const textEncoder = new TextEncoder() -const textDecoder = new TextDecoder() +/** + * RESOLUTION_MS represents the target resolution time in milliseconds. + * + * @type {number} + * @default 1000 + */ +const RESOLUTION_MS = 1e3 -// https://fetch.spec.whatwg.org/#concept-bodyinit-extract -function extractBody (object, keepalive = false) { - if (!ReadableStream) { - ReadableStream = (__nccwpck_require__(3774).ReadableStream) - } +/** + * TICK_MS defines the desired interval in milliseconds between each tick. + * The target value is set to half the resolution time, minus 1 ms, to account + * for potential event loop overhead. + * + * @type {number} + * @default 499 + */ +const TICK_MS = (RESOLUTION_MS >> 1) - 1 - // 1. Let stream be null. - let stream = null - - // 2. If object is a ReadableStream object, then set stream to object. - if (object instanceof ReadableStream) { - stream = object - } else if (isBlobLike(object)) { - // 3. Otherwise, if object is a Blob object, set stream to the - // result of running object’s get stream. - stream = object.stream() - } else { - // 4. Otherwise, set stream to a new ReadableStream object, and set - // up stream. - stream = new ReadableStream({ - async pull (controller) { - controller.enqueue( - typeof source === 'string' ? textEncoder.encode(source) : source - ) - queueMicrotask(() => readableStreamClose(controller)) - }, - start () {}, - type: undefined - }) - } - - // 5. Assert: stream is a ReadableStream object. - assert(isReadableStreamLike(stream)) - - // 6. Let action be null. - let action = null - - // 7. Let source be null. - let source = null - - // 8. Let length be null. - let length = null - - // 9. Let type be null. - let type = null +/** + * fastNowTimeout is a Node.js timer used to manage and process + * the FastTimers stored in the `fastTimers` array. + * + * @type {NodeJS.Timeout} + */ +let fastNowTimeout - // 10. Switch on object: - if (typeof object === 'string') { - // Set source to the UTF-8 encoding of object. - // Note: setting source to a Uint8Array here breaks some mocking assumptions. - source = object +/** + * The kFastTimer symbol is used to identify FastTimer instances. + * + * @type {Symbol} + */ +const kFastTimer = Symbol('kFastTimer') - // Set type to `text/plain;charset=UTF-8`. - type = 'text/plain;charset=UTF-8' - } else if (object instanceof URLSearchParams) { - // URLSearchParams +/** + * The fastTimers array contains all active FastTimers. + * + * @type {FastTimer[]} + */ +const fastTimers = [] - // spec says to run application/x-www-form-urlencoded on body.list - // this is implemented in Node.js as apart of an URLSearchParams instance toString method - // See: https://github.com/nodejs/node/blob/e46c680bf2b211bbd52cf959ca17ee98c7f657f5/lib/internal/url.js#L490 - // and https://github.com/nodejs/node/blob/e46c680bf2b211bbd52cf959ca17ee98c7f657f5/lib/internal/url.js#L1100 +/** + * These constants represent the various states of a FastTimer. + */ - // Set source to the result of running the application/x-www-form-urlencoded serializer with object’s list. - source = object.toString() +/** + * The `NOT_IN_LIST` constant indicates that the FastTimer is not included + * in the `fastTimers` array. Timers with this status will not be processed + * during the next tick by the `onTick` function. + * + * A FastTimer can be re-added to the `fastTimers` array by invoking the + * `refresh` method on the FastTimer instance. + * + * @type {-2} + */ +const NOT_IN_LIST = -2 - // Set type to `application/x-www-form-urlencoded;charset=UTF-8`. - type = 'application/x-www-form-urlencoded;charset=UTF-8' - } else if (isArrayBuffer(object)) { - // BufferSource/ArrayBuffer +/** + * The `TO_BE_CLEARED` constant indicates that the FastTimer is scheduled + * for removal from the `fastTimers` array. A FastTimer in this state will + * be removed in the next tick by the `onTick` function and will no longer + * be processed. + * + * This status is also set when the `clear` method is called on the FastTimer instance. + * + * @type {-1} + */ +const TO_BE_CLEARED = -1 - // Set source to a copy of the bytes held by object. - source = new Uint8Array(object.slice()) - } else if (ArrayBuffer.isView(object)) { - // BufferSource/ArrayBufferView +/** + * The `PENDING` constant signifies that the FastTimer is awaiting processing + * in the next tick by the `onTick` function. Timers with this status will have + * their `_idleStart` value set and their status updated to `ACTIVE` in the next tick. + * + * @type {0} + */ +const PENDING = 0 - // Set source to a copy of the bytes held by object. - source = new Uint8Array(object.buffer.slice(object.byteOffset, object.byteOffset + object.byteLength)) - } else if (util.isFormDataLike(object)) { - const boundary = `----formdata-undici-0${`${random(1e11)}`.padStart(11, '0')}` - const prefix = `--${boundary}\r\nContent-Disposition: form-data` +/** + * The `ACTIVE` constant indicates that the FastTimer is active and waiting + * for its timer to expire. During the next tick, the `onTick` function will + * check if the timer has expired, and if so, it will execute the associated callback. + * + * @type {1} + */ +const ACTIVE = 1 - /*! formdata-polyfill. MIT License. Jimmy Wärting */ - const escape = (str) => - str.replace(/\n/g, '%0A').replace(/\r/g, '%0D').replace(/"/g, '%22') - const normalizeLinefeeds = (value) => value.replace(/\r?\n|\r/g, '\r\n') +/** + * The onTick function processes the fastTimers array. + * + * @returns {void} + */ +function onTick () { + /** + * Increment the fastNow value by the TICK_MS value, despite the actual time + * that has passed since the last tick. This approach ensures independence + * from the system clock and delays caused by a blocked event loop. + * + * @type {number} + */ + fastNow += TICK_MS - // Set action to this step: run the multipart/form-data - // encoding algorithm, with object’s entry list and UTF-8. - // - This ensures that the body is immutable and can't be changed afterwords - // - That the content-length is calculated in advance. - // - And that all parts are pre-encoded and ready to be sent. + /** + * The `idx` variable is used to iterate over the `fastTimers` array. + * Expired timers are removed by replacing them with the last element in the array. + * Consequently, `idx` is only incremented when the current element is not removed. + * + * @type {number} + */ + let idx = 0 - const blobParts = [] - const rn = new Uint8Array([13, 10]) // '\r\n' - length = 0 - let hasUnknownSizeValue = false + /** + * The len variable will contain the length of the fastTimers array + * and will be decremented when a FastTimer should be removed from the + * fastTimers array. + * + * @type {number} + */ + let len = fastTimers.length - for (const [name, value] of object) { - if (typeof value === 'string') { - const chunk = textEncoder.encode(prefix + - `; name="${escape(normalizeLinefeeds(name))}"` + - `\r\n\r\n${normalizeLinefeeds(value)}\r\n`) - blobParts.push(chunk) - length += chunk.byteLength - } else { - const chunk = textEncoder.encode(`${prefix}; name="${escape(normalizeLinefeeds(name))}"` + - (value.name ? `; filename="${escape(value.name)}"` : '') + '\r\n' + - `Content-Type: ${ - value.type || 'application/octet-stream' - }\r\n\r\n`) - blobParts.push(chunk, value, rn) - if (typeof value.size === 'number') { - length += chunk.byteLength + value.size + rn.byteLength - } else { - hasUnknownSizeValue = true - } - } - } + while (idx < len) { + /** + * @type {FastTimer} + */ + const timer = fastTimers[idx] - const chunk = textEncoder.encode(`--${boundary}--`) - blobParts.push(chunk) - length += chunk.byteLength - if (hasUnknownSizeValue) { - length = null + // If the timer is in the ACTIVE state and the timer has expired, it will + // be processed in the next tick. + if (timer._state === PENDING) { + // Set the _idleStart value to the fastNow value minus the TICK_MS value + // to account for the time the timer was in the PENDING state. + timer._idleStart = fastNow - TICK_MS + timer._state = ACTIVE + } else if ( + timer._state === ACTIVE && + fastNow >= timer._idleStart + timer._idleTimeout + ) { + timer._state = TO_BE_CLEARED + timer._idleStart = -1 + timer._onTimeout(timer._timerArg) } - // Set source to object. - source = object + if (timer._state === TO_BE_CLEARED) { + timer._state = NOT_IN_LIST - action = async function * () { - for (const part of blobParts) { - if (part.stream) { - yield * part.stream() - } else { - yield part - } + // Move the last element to the current index and decrement len if it is + // not the only element in the array. + if (--len !== 0) { + fastTimers[idx] = fastTimers[len] } + } else { + ++idx } - - // Set type to `multipart/form-data; boundary=`, - // followed by the multipart/form-data boundary string generated - // by the multipart/form-data encoding algorithm. - type = 'multipart/form-data; boundary=' + boundary - } else if (isBlobLike(object)) { - // Blob - - // Set source to object. - source = object - - // Set length to object’s size. - length = object.size - - // If object’s type attribute is not the empty byte sequence, set - // type to its value. - if (object.type) { - type = object.type - } - } else if (typeof object[Symbol.asyncIterator] === 'function') { - // If keepalive is true, then throw a TypeError. - if (keepalive) { - throw new TypeError('keepalive') - } - - // If object is disturbed or locked, then throw a TypeError. - if (util.isDisturbed(object) || object.locked) { - throw new TypeError( - 'Response body object should not be disturbed or locked' - ) - } - - stream = - object instanceof ReadableStream ? object : ReadableStreamFrom(object) } - // 11. If source is a byte sequence, then set action to a - // step that returns source and length to source’s length. - if (typeof source === 'string' || util.isBuffer(source)) { - length = Buffer.byteLength(source) - } + // Set the length of the fastTimers array to the new length and thus + // removing the excess FastTimers elements from the array. + fastTimers.length = len - // 12. If action is non-null, then run these steps in in parallel: - if (action != null) { - // Run action. - let iterator - stream = new ReadableStream({ - async start () { - iterator = action(object)[Symbol.asyncIterator]() - }, - async pull (controller) { - const { value, done } = await iterator.next() - if (done) { - // When running action is done, close stream. - queueMicrotask(() => { - controller.close() - }) - } else { - // Whenever one or more bytes are available and stream is not errored, - // enqueue a Uint8Array wrapping an ArrayBuffer containing the available - // bytes into stream. - if (!isErrored(stream)) { - controller.enqueue(new Uint8Array(value)) - } - } - return controller.desiredSize > 0 - }, - async cancel (reason) { - await iterator.return() - }, - type: undefined - }) + // If there are still active FastTimers in the array, refresh the Timer. + // If there are no active FastTimers, the timer will be refreshed again + // when a new FastTimer is instantiated. + if (fastTimers.length !== 0) { + refreshTimeout() } - - // 13. Let body be a body whose stream is stream, source is source, - // and length is length. - const body = { stream, source, length } - - // 14. Return (body, type). - return [body, type] } -// https://fetch.spec.whatwg.org/#bodyinit-safely-extract -function safelyExtractBody (object, keepalive = false) { - if (!ReadableStream) { - // istanbul ignore next - ReadableStream = (__nccwpck_require__(3774).ReadableStream) - } - - // To safely extract a body and a `Content-Type` value from - // a byte sequence or BodyInit object object, run these steps: +function refreshTimeout () { + // If the fastNowTimeout is already set, refresh it. + if (fastNowTimeout) { + fastNowTimeout.refresh() + // fastNowTimeout is not instantiated yet, create a new Timer. + } else { + clearTimeout(fastNowTimeout) + fastNowTimeout = setTimeout(onTick, TICK_MS) - // 1. If object is a ReadableStream object, then: - if (object instanceof ReadableStream) { - // Assert: object is neither disturbed nor locked. - // istanbul ignore next - assert(!util.isDisturbed(object), 'The body has already been consumed.') - // istanbul ignore next - assert(!object.locked, 'The stream is locked.') + // If the Timer has an unref method, call it to allow the process to exit if + // there are no other active handles. + if (fastNowTimeout.unref) { + fastNowTimeout.unref() + } } - - // 2. Return the results of extracting object. - return extractBody(object, keepalive) } -function cloneBody (body) { - // To clone a body body, run these steps: +/** + * The `FastTimer` class is a data structure designed to store and manage + * timer information. + */ +class FastTimer { + [kFastTimer] = true - // https://fetch.spec.whatwg.org/#concept-body-clone + /** + * The state of the timer, which can be one of the following: + * - NOT_IN_LIST (-2) + * - TO_BE_CLEARED (-1) + * - PENDING (0) + * - ACTIVE (1) + * + * @type {-2|-1|0|1} + * @private + */ + _state = NOT_IN_LIST - // 1. Let « out1, out2 » be the result of teeing body’s stream. - const [out1, out2] = body.stream.tee() - const out2Clone = structuredClone(out2, { transfer: [out2] }) - // This, for whatever reasons, unrefs out2Clone which allows - // the process to exit by itself. - const [, finalClone] = out2Clone.tee() + /** + * The number of milliseconds to wait before calling the callback. + * + * @type {number} + * @private + */ + _idleTimeout = -1 - // 2. Set body’s stream to out1. - body.stream = out1 + /** + * The time in milliseconds when the timer was started. This value is used to + * calculate when the timer should expire. + * + * @type {number} + * @default -1 + * @private + */ + _idleStart = -1 - // 3. Return a body whose stream is out2 and other members are copied from body. - return { - stream: finalClone, - length: body.length, - source: body.source - } -} + /** + * The function to be executed when the timer expires. + * @type {Function} + * @private + */ + _onTimeout -async function * consumeBody (body) { - if (body) { - if (isUint8Array(body)) { - yield body - } else { - const stream = body.stream + /** + * The argument to be passed to the callback when the timer expires. + * + * @type {*} + * @private + */ + _timerArg - if (util.isDisturbed(stream)) { - throw new TypeError('The body has already been consumed.') - } + /** + * @constructor + * @param {Function} callback A function to be executed after the timer + * expires. + * @param {number} delay The time, in milliseconds that the timer should wait + * before the specified function or code is executed. + * @param {*} arg + */ + constructor (callback, delay, arg) { + this._onTimeout = callback + this._idleTimeout = delay + this._timerArg = arg - if (stream.locked) { - throw new TypeError('The stream is locked.') - } + this.refresh() + } - // Compat. - stream[kBodyUsed] = true + /** + * Sets the timer's start time to the current time, and reschedules the timer + * to call its callback at the previously specified duration adjusted to the + * current time. + * Using this on a timer that has already called its callback will reactivate + * the timer. + * + * @returns {void} + */ + refresh () { + // In the special case that the timer is not in the list of active timers, + // add it back to the array to be processed in the next tick by the onTick + // function. + if (this._state === NOT_IN_LIST) { + fastTimers.push(this) + } - yield * stream + // If the timer is the only active timer, refresh the fastNowTimeout for + // better resolution. + if (!fastNowTimeout || fastTimers.length === 1) { + refreshTimeout() } - } -} -function throwIfAborted (state) { - if (state.aborted) { - throw new DOMException('The operation was aborted.', 'AbortError') + // Setting the state to PENDING will cause the timer to be reset in the + // next tick by the onTick function. + this._state = PENDING } -} - -function bodyMixinMethods (instance) { - const methods = { - blob () { - // The blob() method steps are to return the result of - // running consume body with this and the following step - // given a byte sequence bytes: return a Blob whose - // contents are bytes and whose type attribute is this’s - // MIME type. - return specConsumeBody(this, (bytes) => { - let mimeType = bodyMimeType(this) - - if (mimeType === 'failure') { - mimeType = '' - } else if (mimeType) { - mimeType = serializeAMimeType(mimeType) - } - - // Return a Blob whose contents are bytes and type attribute - // is mimeType. - return new Blob([bytes], { type: mimeType }) - }, instance) - }, - - arrayBuffer () { - // The arrayBuffer() method steps are to return the result - // of running consume body with this and the following step - // given a byte sequence bytes: return a new ArrayBuffer - // whose contents are bytes. - return specConsumeBody(this, (bytes) => { - return new Uint8Array(bytes).buffer - }, instance) - }, - - text () { - // The text() method steps are to return the result of running - // consume body with this and UTF-8 decode. - return specConsumeBody(this, utf8DecodeBytes, instance) - }, - - json () { - // The json() method steps are to return the result of running - // consume body with this and parse JSON from bytes. - return specConsumeBody(this, parseJSONFromBytes, instance) - }, - - async formData () { - webidl.brandCheck(this, instance) - throwIfAborted(this[kState]) - - const contentType = this.headers.get('Content-Type') - - // If mimeType’s essence is "multipart/form-data", then: - if (/multipart\/form-data/.test(contentType)) { - const headers = {} - for (const [key, value] of this.headers) headers[key.toLowerCase()] = value - - const responseFormData = new FormData() - - let busboy - - try { - busboy = new Busboy({ - headers, - preservePath: true - }) - } catch (err) { - throw new DOMException(`${err}`, 'AbortError') - } - - busboy.on('field', (name, value) => { - responseFormData.append(name, value) - }) - busboy.on('file', (name, value, filename, encoding, mimeType) => { - const chunks = [] - - if (encoding === 'base64' || encoding.toLowerCase() === 'base64') { - let base64chunk = '' - - value.on('data', (chunk) => { - base64chunk += chunk.toString().replace(/[\r\n]/gm, '') + /** + * The `clear` method cancels the timer, preventing it from executing. + * + * @returns {void} + * @private + */ + clear () { + // Set the state to TO_BE_CLEARED to mark the timer for removal in the next + // tick by the onTick function. + this._state = TO_BE_CLEARED - const end = base64chunk.length - base64chunk.length % 4 - chunks.push(Buffer.from(base64chunk.slice(0, end), 'base64')) + // Reset the _idleStart value to -1 to indicate that the timer is no longer + // active. + this._idleStart = -1 + } +} - base64chunk = base64chunk.slice(end) - }) - value.on('end', () => { - chunks.push(Buffer.from(base64chunk, 'base64')) - responseFormData.append(name, new File(chunks, filename, { type: mimeType })) - }) - } else { - value.on('data', (chunk) => { - chunks.push(chunk) - }) - value.on('end', () => { - responseFormData.append(name, new File(chunks, filename, { type: mimeType })) - }) - } - }) - - const busboyResolve = new Promise((resolve, reject) => { - busboy.on('finish', resolve) - busboy.on('error', (err) => reject(new TypeError(err))) - }) - - if (this.body !== null) for await (const chunk of consumeBody(this[kState].body)) busboy.write(chunk) - busboy.end() - await busboyResolve +/** + * This module exports a setTimeout and clearTimeout function that can be + * used as a drop-in replacement for the native functions. + */ +module.exports = { + /** + * The setTimeout() method sets a timer which executes a function once the + * timer expires. + * @param {Function} callback A function to be executed after the timer + * expires. + * @param {number} delay The time, in milliseconds that the timer should + * wait before the specified function or code is executed. + * @param {*} [arg] An optional argument to be passed to the callback function + * when the timer expires. + * @returns {NodeJS.Timeout|FastTimer} + */ + setTimeout (callback, delay, arg) { + // If the delay is less than or equal to the RESOLUTION_MS value return a + // native Node.js Timer instance. + return delay <= RESOLUTION_MS + ? setTimeout(callback, delay, arg) + : new FastTimer(callback, delay, arg) + }, + /** + * The clearTimeout method cancels an instantiated Timer previously created + * by calling setTimeout. + * + * @param {NodeJS.Timeout|FastTimer} timeout + */ + clearTimeout (timeout) { + // If the timeout is a FastTimer, call its own clear method. + if (timeout[kFastTimer]) { + /** + * @type {FastTimer} + */ + timeout.clear() + // Otherwise it is an instance of a native NodeJS.Timeout, so call the + // Node.js native clearTimeout function. + } else { + clearTimeout(timeout) + } + }, + /** + * The setFastTimeout() method sets a fastTimer which executes a function once + * the timer expires. + * @param {Function} callback A function to be executed after the timer + * expires. + * @param {number} delay The time, in milliseconds that the timer should + * wait before the specified function or code is executed. + * @param {*} [arg] An optional argument to be passed to the callback function + * when the timer expires. + * @returns {FastTimer} + */ + setFastTimeout (callback, delay, arg) { + return new FastTimer(callback, delay, arg) + }, + /** + * The clearTimeout method cancels an instantiated FastTimer previously + * created by calling setFastTimeout. + * + * @param {FastTimer} timeout + */ + clearFastTimeout (timeout) { + timeout.clear() + }, + /** + * The now method returns the value of the internal fast timer clock. + * + * @returns {number} + */ + now () { + return fastNow + }, + /** + * Trigger the onTick function to process the fastTimers array. + * Exported for testing purposes only. + * Marking as deprecated to discourage any use outside of testing. + * @deprecated + * @param {number} [delay=0] The delay in milliseconds to add to the now value. + */ + tick (delay = 0) { + fastNow += delay - RESOLUTION_MS + 1 + onTick() + onTick() + }, + /** + * Reset FastTimers. + * Exported for testing purposes only. + * Marking as deprecated to discourage any use outside of testing. + * @deprecated + */ + reset () { + fastNow = 0 + fastTimers.length = 0 + clearTimeout(fastNowTimeout) + fastNowTimeout = null + }, + /** + * Exporting for testing purposes only. + * Marking as deprecated to discourage any use outside of testing. + * @deprecated + */ + kFastTimer +} - return responseFormData - } else if (/application\/x-www-form-urlencoded/.test(contentType)) { - // Otherwise, if mimeType’s essence is "application/x-www-form-urlencoded", then: - // 1. Let entries be the result of parsing bytes. - let entries - try { - let text = '' - // application/x-www-form-urlencoded parser will keep the BOM. - // https://url.spec.whatwg.org/#concept-urlencoded-parser - // Note that streaming decoder is stateful and cannot be reused - const streamingDecoder = new TextDecoder('utf-8', { ignoreBOM: true }) - - for await (const chunk of consumeBody(this[kState].body)) { - if (!isUint8Array(chunk)) { - throw new TypeError('Expected Uint8Array chunk') - } - text += streamingDecoder.decode(chunk, { stream: true }) - } - text += streamingDecoder.decode() - entries = new URLSearchParams(text) - } catch (err) { - // istanbul ignore next: Unclear when new URLSearchParams can fail on a string. - // 2. If entries is failure, then throw a TypeError. - throw Object.assign(new TypeError(), { cause: err }) - } +/***/ }), - // 3. Return a new FormData object whose entries are entries. - const formData = new FormData() - for (const [name, value] of entries) { - formData.append(name, value) - } - return formData - } else { - // Wait a tick before checking if the request has been aborted. - // Otherwise, a TypeError can be thrown when an AbortError should. - await Promise.resolve() +/***/ 6172: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - throwIfAborted(this[kState]) - // Otherwise, throw a TypeError. - throw webidl.errors.exception({ - header: `${instance.name}.formData`, - message: 'Could not parse content as FormData.' - }) - } - } - } - return methods -} +const { kConstruct } = __nccwpck_require__(7415) +const { urlEquals, getFieldValues } = __nccwpck_require__(3399) +const { kEnumerableProperty, isDisturbed } = __nccwpck_require__(7234) +const { webidl } = __nccwpck_require__(4859) +const { Response, cloneResponse, fromInnerResponse } = __nccwpck_require__(4317) +const { Request, fromInnerRequest } = __nccwpck_require__(5417) +const { kState } = __nccwpck_require__(1445) +const { fetching } = __nccwpck_require__(5780) +const { urlIsHttpHttpsScheme, createDeferredPromise, readAllBytes } = __nccwpck_require__(1046) +const assert = __nccwpck_require__(4589) -function mixinBody (prototype) { - Object.assign(prototype.prototype, bodyMixinMethods(prototype)) -} +/** + * @see https://w3c.github.io/ServiceWorker/#dfn-cache-batch-operation + * @typedef {Object} CacheBatchOperation + * @property {'delete' | 'put'} type + * @property {any} request + * @property {any} response + * @property {import('../../types/cache').CacheQueryOptions} options + */ /** - * @see https://fetch.spec.whatwg.org/#concept-body-consume-body - * @param {Response|Request} object - * @param {(value: unknown) => unknown} convertBytesToJSValue - * @param {Response|Request} instance + * @see https://w3c.github.io/ServiceWorker/#dfn-request-response-list + * @typedef {[any, any][]} requestResponseList */ -async function specConsumeBody (object, convertBytesToJSValue, instance) { - webidl.brandCheck(object, instance) - throwIfAborted(object[kState]) +class Cache { + /** + * @see https://w3c.github.io/ServiceWorker/#dfn-relevant-request-response-list + * @type {requestResponseList} + */ + #relevantRequestResponseList - // 1. If object is unusable, then return a promise rejected - // with a TypeError. - if (bodyUnusable(object[kState].body)) { - throw new TypeError('Body is unusable') + constructor () { + if (arguments[0] !== kConstruct) { + webidl.illegalConstructor() + } + + webidl.util.markAsUncloneable(this) + this.#relevantRequestResponseList = arguments[1] } - // 2. Let promise be a new promise. - const promise = createDeferredPromise() + async match (request, options = {}) { + webidl.brandCheck(this, Cache) - // 3. Let errorSteps given error be to reject promise with error. - const errorSteps = (error) => promise.reject(error) + const prefix = 'Cache.match' + webidl.argumentLengthCheck(arguments, 1, prefix) - // 4. Let successSteps given a byte sequence data be to resolve - // promise with the result of running convertBytesToJSValue - // with data. If that threw an exception, then run errorSteps - // with that exception. - const successSteps = (data) => { - try { - promise.resolve(convertBytesToJSValue(data)) - } catch (e) { - errorSteps(e) + request = webidl.converters.RequestInfo(request, prefix, 'request') + options = webidl.converters.CacheQueryOptions(options, prefix, 'options') + + const p = this.#internalMatchAll(request, options, 1) + + if (p.length === 0) { + return } - } - // 5. If object’s body is null, then run successSteps with an - // empty byte sequence. - if (object[kState].body == null) { - successSteps(new Uint8Array()) - return promise.promise + return p[0] } - // 6. Otherwise, fully read object’s body given successSteps, - // errorSteps, and object’s relevant global object. - await fullyReadBody(object[kState].body, successSteps, errorSteps) - - // 7. Return promise. - return promise.promise -} + async matchAll (request = undefined, options = {}) { + webidl.brandCheck(this, Cache) -// https://fetch.spec.whatwg.org/#body-unusable -function bodyUnusable (body) { - // An object including the Body interface mixin is - // said to be unusable if its body is non-null and - // its body’s stream is disturbed or locked. - return body != null && (body.stream.locked || util.isDisturbed(body.stream)) -} + const prefix = 'Cache.matchAll' + if (request !== undefined) request = webidl.converters.RequestInfo(request, prefix, 'request') + options = webidl.converters.CacheQueryOptions(options, prefix, 'options') -/** - * @see https://encoding.spec.whatwg.org/#utf-8-decode - * @param {Buffer} buffer - */ -function utf8DecodeBytes (buffer) { - if (buffer.length === 0) { - return '' + return this.#internalMatchAll(request, options) } - // 1. Let buffer be the result of peeking three bytes from - // ioQueue, converted to a byte sequence. - - // 2. If buffer is 0xEF 0xBB 0xBF, then read three - // bytes from ioQueue. (Do nothing with those bytes.) - if (buffer[0] === 0xEF && buffer[1] === 0xBB && buffer[2] === 0xBF) { - buffer = buffer.subarray(3) - } + async add (request) { + webidl.brandCheck(this, Cache) - // 3. Process a queue with an instance of UTF-8’s - // decoder, ioQueue, output, and "replacement". - const output = textDecoder.decode(buffer) + const prefix = 'Cache.add' + webidl.argumentLengthCheck(arguments, 1, prefix) - // 4. Return output. - return output -} + request = webidl.converters.RequestInfo(request, prefix, 'request') -/** - * @see https://infra.spec.whatwg.org/#parse-json-bytes-to-a-javascript-value - * @param {Uint8Array} bytes - */ -function parseJSONFromBytes (bytes) { - return JSON.parse(utf8DecodeBytes(bytes)) -} + // 1. + const requests = [request] -/** - * @see https://fetch.spec.whatwg.org/#concept-body-mime-type - * @param {import('./response').Response|import('./request').Request} object - */ -function bodyMimeType (object) { - const { headersList } = object[kState] - const contentType = headersList.get('content-type') + // 2. + const responseArrayPromise = this.addAll(requests) - if (contentType === null) { - return 'failure' + // 3. + return await responseArrayPromise } - return parseMIMEType(contentType) -} + async addAll (requests) { + webidl.brandCheck(this, Cache) -module.exports = { - extractBody, - safelyExtractBody, - cloneBody, - mixinBody -} + const prefix = 'Cache.addAll' + webidl.argumentLengthCheck(arguments, 1, prefix) + // 1. + const responsePromises = [] -/***/ }), + // 2. + const requestList = [] -/***/ 3283: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // 3. + for (let request of requests) { + if (request === undefined) { + throw webidl.errors.conversionFailed({ + prefix, + argument: 'Argument 1', + types: ['undefined is not allowed'] + }) + } -"use strict"; + request = webidl.converters.RequestInfo(request) + if (typeof request === 'string') { + continue + } -const { MessageChannel, receiveMessageOnPort } = __nccwpck_require__(8167) + // 3.1 + const r = request[kState] -const corsSafeListedMethods = ['GET', 'HEAD', 'POST'] -const corsSafeListedMethodsSet = new Set(corsSafeListedMethods) + // 3.2 + if (!urlIsHttpHttpsScheme(r.url) || r.method !== 'GET') { + throw webidl.errors.exception({ + header: prefix, + message: 'Expected http/s scheme when method is not GET.' + }) + } + } -const nullBodyStatus = [101, 204, 205, 304] + // 4. + /** @type {ReturnType[]} */ + const fetchControllers = [] -const redirectStatus = [301, 302, 303, 307, 308] -const redirectStatusSet = new Set(redirectStatus) + // 5. + for (const request of requests) { + // 5.1 + const r = new Request(request)[kState] -// https://fetch.spec.whatwg.org/#block-bad-port -const badPorts = [ - '1', '7', '9', '11', '13', '15', '17', '19', '20', '21', '22', '23', '25', '37', '42', '43', '53', '69', '77', '79', - '87', '95', '101', '102', '103', '104', '109', '110', '111', '113', '115', '117', '119', '123', '135', '137', - '139', '143', '161', '179', '389', '427', '465', '512', '513', '514', '515', '526', '530', '531', '532', - '540', '548', '554', '556', '563', '587', '601', '636', '989', '990', '993', '995', '1719', '1720', '1723', - '2049', '3659', '4045', '5060', '5061', '6000', '6566', '6665', '6666', '6667', '6668', '6669', '6697', - '10080' -] + // 5.2 + if (!urlIsHttpHttpsScheme(r.url)) { + throw webidl.errors.exception({ + header: prefix, + message: 'Expected http/s scheme.' + }) + } -const badPortsSet = new Set(badPorts) + // 5.4 + r.initiator = 'fetch' + r.destination = 'subresource' -// https://w3c.github.io/webappsec-referrer-policy/#referrer-policies -const referrerPolicy = [ - '', - 'no-referrer', - 'no-referrer-when-downgrade', - 'same-origin', - 'origin', - 'strict-origin', - 'origin-when-cross-origin', - 'strict-origin-when-cross-origin', - 'unsafe-url' -] -const referrerPolicySet = new Set(referrerPolicy) + // 5.5 + requestList.push(r) -const requestRedirect = ['follow', 'manual', 'error'] + // 5.6 + const responsePromise = createDeferredPromise() -const safeMethods = ['GET', 'HEAD', 'OPTIONS', 'TRACE'] -const safeMethodsSet = new Set(safeMethods) + // 5.7 + fetchControllers.push(fetching({ + request: r, + processResponse (response) { + // 1. + if (response.type === 'error' || response.status === 206 || response.status < 200 || response.status > 299) { + responsePromise.reject(webidl.errors.exception({ + header: 'Cache.addAll', + message: 'Received an invalid status code or the request failed.' + })) + } else if (response.headersList.contains('vary')) { // 2. + // 2.1 + const fieldValues = getFieldValues(response.headersList.get('vary')) -const requestMode = ['navigate', 'same-origin', 'no-cors', 'cors'] + // 2.2 + for (const fieldValue of fieldValues) { + // 2.2.1 + if (fieldValue === '*') { + responsePromise.reject(webidl.errors.exception({ + header: 'Cache.addAll', + message: 'invalid vary field value' + })) -const requestCredentials = ['omit', 'same-origin', 'include'] + for (const controller of fetchControllers) { + controller.abort() + } -const requestCache = [ - 'default', - 'no-store', - 'reload', - 'no-cache', - 'force-cache', - 'only-if-cached' -] + return + } + } + } + }, + processResponseEndOfBody (response) { + // 1. + if (response.aborted) { + responsePromise.reject(new DOMException('aborted', 'AbortError')) + return + } -// https://fetch.spec.whatwg.org/#request-body-header-name -const requestBodyHeader = [ - 'content-encoding', - 'content-language', - 'content-location', - 'content-type', - // See https://github.com/nodejs/undici/issues/2021 - // 'Content-Length' is a forbidden header name, which is typically - // removed in the Headers implementation. However, undici doesn't - // filter out headers, so we add it here. - 'content-length' -] + // 2. + responsePromise.resolve(response) + } + })) -// https://fetch.spec.whatwg.org/#enumdef-requestduplex -const requestDuplex = [ - 'half' -] + // 5.8 + responsePromises.push(responsePromise.promise) + } -// http://fetch.spec.whatwg.org/#forbidden-method -const forbiddenMethods = ['CONNECT', 'TRACE', 'TRACK'] -const forbiddenMethodsSet = new Set(forbiddenMethods) + // 6. + const p = Promise.all(responsePromises) -const subresource = [ - 'audio', - 'audioworklet', - 'font', - 'image', - 'manifest', - 'paintworklet', - 'script', - 'style', - 'track', - 'video', - 'xslt', - '' -] -const subresourceSet = new Set(subresource) + // 7. + const responses = await p -/** @type {globalThis['DOMException']} */ -const DOMException = globalThis.DOMException ?? (() => { - // DOMException was only made a global in Node v17.0.0, - // but fetch supports >= v16.8. - try { - atob('~') - } catch (err) { - return Object.getPrototypeOf(err).constructor - } -})() + // 7.1 + const operations = [] -let channel + // 7.2 + let index = 0 -/** @type {globalThis['structuredClone']} */ -const structuredClone = - globalThis.structuredClone ?? - // https://github.com/nodejs/node/blob/b27ae24dcc4251bad726d9d84baf678d1f707fed/lib/internal/structured_clone.js - // structuredClone was added in v17.0.0, but fetch supports v16.8 - function structuredClone (value, options = undefined) { - if (arguments.length === 0) { - throw new TypeError('missing argument') - } + // 7.3 + for (const response of responses) { + // 7.3.1 + /** @type {CacheBatchOperation} */ + const operation = { + type: 'put', // 7.3.2 + request: requestList[index], // 7.3.3 + response // 7.3.4 + } + + operations.push(operation) // 7.3.5 - if (!channel) { - channel = new MessageChannel() + index++ // 7.3.6 } - channel.port1.unref() - channel.port2.unref() - channel.port1.postMessage(value, options?.transfer) - return receiveMessageOnPort(channel.port2).message - } -module.exports = { - DOMException, - structuredClone, - subresource, - forbiddenMethods, - requestBodyHeader, - referrerPolicy, - requestRedirect, - requestMode, - requestCredentials, - requestCache, - redirectStatus, - corsSafeListedMethods, - nullBodyStatus, - safeMethods, - badPorts, - requestDuplex, - subresourceSet, - badPortsSet, - redirectStatusSet, - corsSafeListedMethodsSet, - safeMethodsSet, - forbiddenMethodsSet, - referrerPolicySet -} + // 7.5 + const cacheJobPromise = createDeferredPromise() + // 7.6.1 + let errorData = null -/***/ }), + // 7.6.2 + try { + this.#batchCacheOperations(operations) + } catch (e) { + errorData = e + } -/***/ 4955: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // 7.6.3 + queueMicrotask(() => { + // 7.6.3.1 + if (errorData === null) { + cacheJobPromise.resolve(undefined) + } else { + // 7.6.3.2 + cacheJobPromise.reject(errorData) + } + }) -const assert = __nccwpck_require__(2613) -const { atob } = __nccwpck_require__(181) -const { isomorphicDecode } = __nccwpck_require__(1612) + // 7.7 + return cacheJobPromise.promise + } -const encoder = new TextEncoder() + async put (request, response) { + webidl.brandCheck(this, Cache) -/** - * @see https://mimesniff.spec.whatwg.org/#http-token-code-point - */ -const HTTP_TOKEN_CODEPOINTS = /^[!#$%&'*+-.^_|~A-Za-z0-9]+$/ -const HTTP_WHITESPACE_REGEX = /(\u000A|\u000D|\u0009|\u0020)/ // eslint-disable-line -/** - * @see https://mimesniff.spec.whatwg.org/#http-quoted-string-token-code-point - */ -const HTTP_QUOTED_STRING_TOKENS = /[\u0009|\u0020-\u007E|\u0080-\u00FF]/ // eslint-disable-line + const prefix = 'Cache.put' + webidl.argumentLengthCheck(arguments, 2, prefix) -// https://fetch.spec.whatwg.org/#data-url-processor -/** @param {URL} dataURL */ -function dataURLProcessor (dataURL) { - // 1. Assert: dataURL’s scheme is "data". - assert(dataURL.protocol === 'data:') + request = webidl.converters.RequestInfo(request, prefix, 'request') + response = webidl.converters.Response(response, prefix, 'response') - // 2. Let input be the result of running the URL - // serializer on dataURL with exclude fragment - // set to true. - let input = URLSerializer(dataURL, true) + // 1. + let innerRequest = null - // 3. Remove the leading "data:" string from input. - input = input.slice(5) + // 2. + if (request instanceof Request) { + innerRequest = request[kState] + } else { // 3. + innerRequest = new Request(request)[kState] + } - // 4. Let position point at the start of input. - const position = { position: 0 } - - // 5. Let mimeType be the result of collecting a - // sequence of code points that are not equal - // to U+002C (,), given position. - let mimeType = collectASequenceOfCodePointsFast( - ',', - input, - position - ) - - // 6. Strip leading and trailing ASCII whitespace - // from mimeType. - // Undici implementation note: we need to store the - // length because if the mimetype has spaces removed, - // the wrong amount will be sliced from the input in - // step #9 - const mimeTypeLength = mimeType.length - mimeType = removeASCIIWhitespace(mimeType, true, true) - - // 7. If position is past the end of input, then - // return failure - if (position.position >= input.length) { - return 'failure' - } - - // 8. Advance position by 1. - position.position++ - - // 9. Let encodedBody be the remainder of input. - const encodedBody = input.slice(mimeTypeLength + 1) + // 4. + if (!urlIsHttpHttpsScheme(innerRequest.url) || innerRequest.method !== 'GET') { + throw webidl.errors.exception({ + header: prefix, + message: 'Expected an http/s scheme when method is not GET' + }) + } - // 10. Let body be the percent-decoding of encodedBody. - let body = stringPercentDecode(encodedBody) + // 5. + const innerResponse = response[kState] - // 11. If mimeType ends with U+003B (;), followed by - // zero or more U+0020 SPACE, followed by an ASCII - // case-insensitive match for "base64", then: - if (/;(\u0020){0,}base64$/i.test(mimeType)) { - // 1. Let stringBody be the isomorphic decode of body. - const stringBody = isomorphicDecode(body) + // 6. + if (innerResponse.status === 206) { + throw webidl.errors.exception({ + header: prefix, + message: 'Got 206 status' + }) + } - // 2. Set body to the forgiving-base64 decode of - // stringBody. - body = forgivingBase64(stringBody) + // 7. + if (innerResponse.headersList.contains('vary')) { + // 7.1. + const fieldValues = getFieldValues(innerResponse.headersList.get('vary')) - // 3. If body is failure, then return failure. - if (body === 'failure') { - return 'failure' + // 7.2. + for (const fieldValue of fieldValues) { + // 7.2.1 + if (fieldValue === '*') { + throw webidl.errors.exception({ + header: prefix, + message: 'Got * vary field value' + }) + } + } } - // 4. Remove the last 6 code points from mimeType. - mimeType = mimeType.slice(0, -6) + // 8. + if (innerResponse.body && (isDisturbed(innerResponse.body.stream) || innerResponse.body.stream.locked)) { + throw webidl.errors.exception({ + header: prefix, + message: 'Response body is locked or disturbed' + }) + } - // 5. Remove trailing U+0020 SPACE code points from mimeType, - // if any. - mimeType = mimeType.replace(/(\u0020)+$/, '') + // 9. + const clonedResponse = cloneResponse(innerResponse) - // 6. Remove the last U+003B (;) code point from mimeType. - mimeType = mimeType.slice(0, -1) - } + // 10. + const bodyReadPromise = createDeferredPromise() - // 12. If mimeType starts with U+003B (;), then prepend - // "text/plain" to mimeType. - if (mimeType.startsWith(';')) { - mimeType = 'text/plain' + mimeType - } + // 11. + if (innerResponse.body != null) { + // 11.1 + const stream = innerResponse.body.stream - // 13. Let mimeTypeRecord be the result of parsing - // mimeType. - let mimeTypeRecord = parseMIMEType(mimeType) + // 11.2 + const reader = stream.getReader() - // 14. If mimeTypeRecord is failure, then set - // mimeTypeRecord to text/plain;charset=US-ASCII. - if (mimeTypeRecord === 'failure') { - mimeTypeRecord = parseMIMEType('text/plain;charset=US-ASCII') - } + // 11.3 + readAllBytes(reader).then(bodyReadPromise.resolve, bodyReadPromise.reject) + } else { + bodyReadPromise.resolve(undefined) + } - // 15. Return a new data: URL struct whose MIME - // type is mimeTypeRecord and body is body. - // https://fetch.spec.whatwg.org/#data-url-struct - return { mimeType: mimeTypeRecord, body } -} + // 12. + /** @type {CacheBatchOperation[]} */ + const operations = [] -// https://url.spec.whatwg.org/#concept-url-serializer -/** - * @param {URL} url - * @param {boolean} excludeFragment - */ -function URLSerializer (url, excludeFragment = false) { - if (!excludeFragment) { - return url.href - } + // 13. + /** @type {CacheBatchOperation} */ + const operation = { + type: 'put', // 14. + request: innerRequest, // 15. + response: clonedResponse // 16. + } - const href = url.href - const hashLength = url.hash.length + // 17. + operations.push(operation) - return hashLength === 0 ? href : href.substring(0, href.length - hashLength) -} + // 19. + const bytes = await bodyReadPromise.promise -// https://infra.spec.whatwg.org/#collect-a-sequence-of-code-points -/** - * @param {(char: string) => boolean} condition - * @param {string} input - * @param {{ position: number }} position - */ -function collectASequenceOfCodePoints (condition, input, position) { - // 1. Let result be the empty string. - let result = '' + if (clonedResponse.body != null) { + clonedResponse.body.source = bytes + } - // 2. While position doesn’t point past the end of input and the - // code point at position within input meets the condition condition: - while (position.position < input.length && condition(input[position.position])) { - // 1. Append that code point to the end of result. - result += input[position.position] + // 19.1 + const cacheJobPromise = createDeferredPromise() - // 2. Advance position by 1. - position.position++ - } + // 19.2.1 + let errorData = null - // 3. Return result. - return result -} + // 19.2.2 + try { + this.#batchCacheOperations(operations) + } catch (e) { + errorData = e + } -/** - * A faster collectASequenceOfCodePoints that only works when comparing a single character. - * @param {string} char - * @param {string} input - * @param {{ position: number }} position - */ -function collectASequenceOfCodePointsFast (char, input, position) { - const idx = input.indexOf(char, position.position) - const start = position.position + // 19.2.3 + queueMicrotask(() => { + // 19.2.3.1 + if (errorData === null) { + cacheJobPromise.resolve() + } else { // 19.2.3.2 + cacheJobPromise.reject(errorData) + } + }) - if (idx === -1) { - position.position = input.length - return input.slice(start) + return cacheJobPromise.promise } - position.position = idx - return input.slice(start, position.position) -} - -// https://url.spec.whatwg.org/#string-percent-decode -/** @param {string} input */ -function stringPercentDecode (input) { - // 1. Let bytes be the UTF-8 encoding of input. - const bytes = encoder.encode(input) - - // 2. Return the percent-decoding of bytes. - return percentDecode(bytes) -} + async delete (request, options = {}) { + webidl.brandCheck(this, Cache) -// https://url.spec.whatwg.org/#percent-decode -/** @param {Uint8Array} input */ -function percentDecode (input) { - // 1. Let output be an empty byte sequence. - /** @type {number[]} */ - const output = [] + const prefix = 'Cache.delete' + webidl.argumentLengthCheck(arguments, 1, prefix) - // 2. For each byte byte in input: - for (let i = 0; i < input.length; i++) { - const byte = input[i] + request = webidl.converters.RequestInfo(request, prefix, 'request') + options = webidl.converters.CacheQueryOptions(options, prefix, 'options') - // 1. If byte is not 0x25 (%), then append byte to output. - if (byte !== 0x25) { - output.push(byte) + /** + * @type {Request} + */ + let r = null - // 2. Otherwise, if byte is 0x25 (%) and the next two bytes - // after byte in input are not in the ranges - // 0x30 (0) to 0x39 (9), 0x41 (A) to 0x46 (F), - // and 0x61 (a) to 0x66 (f), all inclusive, append byte - // to output. - } else if ( - byte === 0x25 && - !/^[0-9A-Fa-f]{2}$/i.test(String.fromCharCode(input[i + 1], input[i + 2])) - ) { - output.push(0x25) + if (request instanceof Request) { + r = request[kState] - // 3. Otherwise: + if (r.method !== 'GET' && !options.ignoreMethod) { + return false + } } else { - // 1. Let bytePoint be the two bytes after byte in input, - // decoded, and then interpreted as hexadecimal number. - const nextTwoBytes = String.fromCharCode(input[i + 1], input[i + 2]) - const bytePoint = Number.parseInt(nextTwoBytes, 16) - - // 2. Append a byte whose value is bytePoint to output. - output.push(bytePoint) + assert(typeof request === 'string') - // 3. Skip the next two bytes in input. - i += 2 + r = new Request(request)[kState] } - } - - // 3. Return output. - return Uint8Array.from(output) -} - -// https://mimesniff.spec.whatwg.org/#parse-a-mime-type -/** @param {string} input */ -function parseMIMEType (input) { - // 1. Remove any leading and trailing HTTP whitespace - // from input. - input = removeHTTPWhitespace(input, true, true) - // 2. Let position be a position variable for input, - // initially pointing at the start of input. - const position = { position: 0 } + /** @type {CacheBatchOperation[]} */ + const operations = [] - // 3. Let type be the result of collecting a sequence - // of code points that are not U+002F (/) from - // input, given position. - const type = collectASequenceOfCodePointsFast( - '/', - input, - position - ) + /** @type {CacheBatchOperation} */ + const operation = { + type: 'delete', + request: r, + options + } - // 4. If type is the empty string or does not solely - // contain HTTP token code points, then return failure. - // https://mimesniff.spec.whatwg.org/#http-token-code-point - if (type.length === 0 || !HTTP_TOKEN_CODEPOINTS.test(type)) { - return 'failure' - } + operations.push(operation) - // 5. If position is past the end of input, then return - // failure - if (position.position > input.length) { - return 'failure' - } + const cacheJobPromise = createDeferredPromise() - // 6. Advance position by 1. (This skips past U+002F (/).) - position.position++ + let errorData = null + let requestResponses - // 7. Let subtype be the result of collecting a sequence of - // code points that are not U+003B (;) from input, given - // position. - let subtype = collectASequenceOfCodePointsFast( - ';', - input, - position - ) + try { + requestResponses = this.#batchCacheOperations(operations) + } catch (e) { + errorData = e + } - // 8. Remove any trailing HTTP whitespace from subtype. - subtype = removeHTTPWhitespace(subtype, false, true) + queueMicrotask(() => { + if (errorData === null) { + cacheJobPromise.resolve(!!requestResponses?.length) + } else { + cacheJobPromise.reject(errorData) + } + }) - // 9. If subtype is the empty string or does not solely - // contain HTTP token code points, then return failure. - if (subtype.length === 0 || !HTTP_TOKEN_CODEPOINTS.test(subtype)) { - return 'failure' + return cacheJobPromise.promise } - const typeLowercase = type.toLowerCase() - const subtypeLowercase = subtype.toLowerCase() - - // 10. Let mimeType be a new MIME type record whose type - // is type, in ASCII lowercase, and subtype is subtype, - // in ASCII lowercase. - // https://mimesniff.spec.whatwg.org/#mime-type - const mimeType = { - type: typeLowercase, - subtype: subtypeLowercase, - /** @type {Map} */ - parameters: new Map(), - // https://mimesniff.spec.whatwg.org/#mime-type-essence - essence: `${typeLowercase}/${subtypeLowercase}` - } + /** + * @see https://w3c.github.io/ServiceWorker/#dom-cache-keys + * @param {any} request + * @param {import('../../types/cache').CacheQueryOptions} options + * @returns {Promise} + */ + async keys (request = undefined, options = {}) { + webidl.brandCheck(this, Cache) - // 11. While position is not past the end of input: - while (position.position < input.length) { - // 1. Advance position by 1. (This skips past U+003B (;).) - position.position++ + const prefix = 'Cache.keys' - // 2. Collect a sequence of code points that are HTTP - // whitespace from input given position. - collectASequenceOfCodePoints( - // https://fetch.spec.whatwg.org/#http-whitespace - char => HTTP_WHITESPACE_REGEX.test(char), - input, - position - ) + if (request !== undefined) request = webidl.converters.RequestInfo(request, prefix, 'request') + options = webidl.converters.CacheQueryOptions(options, prefix, 'options') - // 3. Let parameterName be the result of collecting a - // sequence of code points that are not U+003B (;) - // or U+003D (=) from input, given position. - let parameterName = collectASequenceOfCodePoints( - (char) => char !== ';' && char !== '=', - input, - position - ) + // 1. + let r = null - // 4. Set parameterName to parameterName, in ASCII - // lowercase. - parameterName = parameterName.toLowerCase() + // 2. + if (request !== undefined) { + // 2.1 + if (request instanceof Request) { + // 2.1.1 + r = request[kState] - // 5. If position is not past the end of input, then: - if (position.position < input.length) { - // 1. If the code point at position within input is - // U+003B (;), then continue. - if (input[position.position] === ';') { - continue + // 2.1.2 + if (r.method !== 'GET' && !options.ignoreMethod) { + return [] + } + } else if (typeof request === 'string') { // 2.2 + r = new Request(request)[kState] } - - // 2. Advance position by 1. (This skips past U+003D (=).) - position.position++ - } - - // 6. If position is past the end of input, then break. - if (position.position > input.length) { - break } - // 7. Let parameterValue be null. - let parameterValue = null - - // 8. If the code point at position within input is - // U+0022 ("), then: - if (input[position.position] === '"') { - // 1. Set parameterValue to the result of collecting - // an HTTP quoted string from input, given position - // and the extract-value flag. - parameterValue = collectAnHTTPQuotedString(input, position, true) - - // 2. Collect a sequence of code points that are not - // U+003B (;) from input, given position. - collectASequenceOfCodePointsFast( - ';', - input, - position - ) - - // 9. Otherwise: - } else { - // 1. Set parameterValue to the result of collecting - // a sequence of code points that are not U+003B (;) - // from input, given position. - parameterValue = collectASequenceOfCodePointsFast( - ';', - input, - position - ) + // 4. + const promise = createDeferredPromise() - // 2. Remove any trailing HTTP whitespace from parameterValue. - parameterValue = removeHTTPWhitespace(parameterValue, false, true) + // 5. + // 5.1 + const requests = [] - // 3. If parameterValue is the empty string, then continue. - if (parameterValue.length === 0) { - continue + // 5.2 + if (request === undefined) { + // 5.2.1 + for (const requestResponse of this.#relevantRequestResponseList) { + // 5.2.1.1 + requests.push(requestResponse[0]) } - } + } else { // 5.3 + // 5.3.1 + const requestResponses = this.#queryCache(r, options) - // 10. If all of the following are true - // - parameterName is not the empty string - // - parameterName solely contains HTTP token code points - // - parameterValue solely contains HTTP quoted-string token code points - // - mimeType’s parameters[parameterName] does not exist - // then set mimeType’s parameters[parameterName] to parameterValue. - if ( - parameterName.length !== 0 && - HTTP_TOKEN_CODEPOINTS.test(parameterName) && - (parameterValue.length === 0 || HTTP_QUOTED_STRING_TOKENS.test(parameterValue)) && - !mimeType.parameters.has(parameterName) - ) { - mimeType.parameters.set(parameterName, parameterValue) + // 5.3.2 + for (const requestResponse of requestResponses) { + // 5.3.2.1 + requests.push(requestResponse[0]) + } } - } - // 12. Return mimeType. - return mimeType -} + // 5.4 + queueMicrotask(() => { + // 5.4.1 + const requestList = [] -// https://infra.spec.whatwg.org/#forgiving-base64-decode -/** @param {string} data */ -function forgivingBase64 (data) { - // 1. Remove all ASCII whitespace from data. - data = data.replace(/[\u0009\u000A\u000C\u000D\u0020]/g, '') // eslint-disable-line + // 5.4.2 + for (const request of requests) { + const requestObject = fromInnerRequest( + request, + new AbortController().signal, + 'immutable' + ) + // 5.4.2.1 + requestList.push(requestObject) + } - // 2. If data’s code point length divides by 4 leaving - // no remainder, then: - if (data.length % 4 === 0) { - // 1. If data ends with one or two U+003D (=) code points, - // then remove them from data. - data = data.replace(/=?=$/, '') - } + // 5.4.3 + promise.resolve(Object.freeze(requestList)) + }) - // 3. If data’s code point length divides by 4 leaving - // a remainder of 1, then return failure. - if (data.length % 4 === 1) { - return 'failure' + return promise.promise } - // 4. If data contains a code point that is not one of - // U+002B (+) - // U+002F (/) - // ASCII alphanumeric - // then return failure. - if (/[^+/0-9A-Za-z]/.test(data)) { - return 'failure' - } - - const binary = atob(data) - const bytes = new Uint8Array(binary.length) - - for (let byte = 0; byte < binary.length; byte++) { - bytes[byte] = binary.charCodeAt(byte) - } + /** + * @see https://w3c.github.io/ServiceWorker/#batch-cache-operations-algorithm + * @param {CacheBatchOperation[]} operations + * @returns {requestResponseList} + */ + #batchCacheOperations (operations) { + // 1. + const cache = this.#relevantRequestResponseList - return bytes -} + // 2. + const backupCache = [...cache] -// https://fetch.spec.whatwg.org/#collect-an-http-quoted-string -// tests: https://fetch.spec.whatwg.org/#example-http-quoted-string -/** - * @param {string} input - * @param {{ position: number }} position - * @param {boolean?} extractValue - */ -function collectAnHTTPQuotedString (input, position, extractValue) { - // 1. Let positionStart be position. - const positionStart = position.position + // 3. + const addedItems = [] - // 2. Let value be the empty string. - let value = '' + // 4.1 + const resultList = [] - // 3. Assert: the code point at position within input - // is U+0022 ("). - assert(input[position.position] === '"') + try { + // 4.2 + for (const operation of operations) { + // 4.2.1 + if (operation.type !== 'delete' && operation.type !== 'put') { + throw webidl.errors.exception({ + header: 'Cache.#batchCacheOperations', + message: 'operation type does not match "delete" or "put"' + }) + } - // 4. Advance position by 1. - position.position++ + // 4.2.2 + if (operation.type === 'delete' && operation.response != null) { + throw webidl.errors.exception({ + header: 'Cache.#batchCacheOperations', + message: 'delete operation should not have an associated response' + }) + } - // 5. While true: - while (true) { - // 1. Append the result of collecting a sequence of code points - // that are not U+0022 (") or U+005C (\) from input, given - // position, to value. - value += collectASequenceOfCodePoints( - (char) => char !== '"' && char !== '\\', - input, - position - ) + // 4.2.3 + if (this.#queryCache(operation.request, operation.options, addedItems).length) { + throw new DOMException('???', 'InvalidStateError') + } - // 2. If position is past the end of input, then break. - if (position.position >= input.length) { - break - } + // 4.2.4 + let requestResponses - // 3. Let quoteOrBackslash be the code point at position within - // input. - const quoteOrBackslash = input[position.position] + // 4.2.5 + if (operation.type === 'delete') { + // 4.2.5.1 + requestResponses = this.#queryCache(operation.request, operation.options) - // 4. Advance position by 1. - position.position++ + // TODO: the spec is wrong, this is needed to pass WPTs + if (requestResponses.length === 0) { + return [] + } - // 5. If quoteOrBackslash is U+005C (\), then: - if (quoteOrBackslash === '\\') { - // 1. If position is past the end of input, then append - // U+005C (\) to value and break. - if (position.position >= input.length) { - value += '\\' - break - } + // 4.2.5.2 + for (const requestResponse of requestResponses) { + const idx = cache.indexOf(requestResponse) + assert(idx !== -1) - // 2. Append the code point at position within input to value. - value += input[position.position] + // 4.2.5.2.1 + cache.splice(idx, 1) + } + } else if (operation.type === 'put') { // 4.2.6 + // 4.2.6.1 + if (operation.response == null) { + throw webidl.errors.exception({ + header: 'Cache.#batchCacheOperations', + message: 'put operation should have an associated response' + }) + } - // 3. Advance position by 1. - position.position++ + // 4.2.6.2 + const r = operation.request - // 6. Otherwise: - } else { - // 1. Assert: quoteOrBackslash is U+0022 ("). - assert(quoteOrBackslash === '"') + // 4.2.6.3 + if (!urlIsHttpHttpsScheme(r.url)) { + throw webidl.errors.exception({ + header: 'Cache.#batchCacheOperations', + message: 'expected http or https scheme' + }) + } - // 2. Break. - break - } - } + // 4.2.6.4 + if (r.method !== 'GET') { + throw webidl.errors.exception({ + header: 'Cache.#batchCacheOperations', + message: 'not get method' + }) + } - // 6. If the extract-value flag is set, then return value. - if (extractValue) { - return value - } + // 4.2.6.5 + if (operation.options != null) { + throw webidl.errors.exception({ + header: 'Cache.#batchCacheOperations', + message: 'options must not be defined' + }) + } - // 7. Return the code points from positionStart to position, - // inclusive, within input. - return input.slice(positionStart, position.position) -} + // 4.2.6.6 + requestResponses = this.#queryCache(operation.request) -/** - * @see https://mimesniff.spec.whatwg.org/#serialize-a-mime-type - */ -function serializeAMimeType (mimeType) { - assert(mimeType !== 'failure') - const { parameters, essence } = mimeType + // 4.2.6.7 + for (const requestResponse of requestResponses) { + const idx = cache.indexOf(requestResponse) + assert(idx !== -1) - // 1. Let serialization be the concatenation of mimeType’s - // type, U+002F (/), and mimeType’s subtype. - let serialization = essence + // 4.2.6.7.1 + cache.splice(idx, 1) + } - // 2. For each name → value of mimeType’s parameters: - for (let [name, value] of parameters.entries()) { - // 1. Append U+003B (;) to serialization. - serialization += ';' + // 4.2.6.8 + cache.push([operation.request, operation.response]) - // 2. Append name to serialization. - serialization += name + // 4.2.6.10 + addedItems.push([operation.request, operation.response]) + } - // 3. Append U+003D (=) to serialization. - serialization += '=' + // 4.2.7 + resultList.push([operation.request, operation.response]) + } - // 4. If value does not solely contain HTTP token code - // points or value is the empty string, then: - if (!HTTP_TOKEN_CODEPOINTS.test(value)) { - // 1. Precede each occurence of U+0022 (") or - // U+005C (\) in value with U+005C (\). - value = value.replace(/(\\|")/g, '\\$1') + // 4.3 + return resultList + } catch (e) { // 5. + // 5.1 + this.#relevantRequestResponseList.length = 0 - // 2. Prepend U+0022 (") to value. - value = '"' + value + // 5.2 + this.#relevantRequestResponseList = backupCache - // 3. Append U+0022 (") to value. - value += '"' + // 5.3 + throw e } - - // 5. Append value to serialization. - serialization += value } - // 3. Return serialization. - return serialization -} + /** + * @see https://w3c.github.io/ServiceWorker/#query-cache + * @param {any} requestQuery + * @param {import('../../types/cache').CacheQueryOptions} options + * @param {requestResponseList} targetStorage + * @returns {requestResponseList} + */ + #queryCache (requestQuery, options, targetStorage) { + /** @type {requestResponseList} */ + const resultList = [] -/** - * @see https://fetch.spec.whatwg.org/#http-whitespace - * @param {string} char - */ -function isHTTPWhiteSpace (char) { - return char === '\r' || char === '\n' || char === '\t' || char === ' ' -} + const storage = targetStorage ?? this.#relevantRequestResponseList -/** - * @see https://fetch.spec.whatwg.org/#http-whitespace - * @param {string} str - */ -function removeHTTPWhitespace (str, leading = true, trailing = true) { - let lead = 0 - let trail = str.length - 1 + for (const requestResponse of storage) { + const [cachedRequest, cachedResponse] = requestResponse + if (this.#requestMatchesCachedItem(requestQuery, cachedRequest, cachedResponse, options)) { + resultList.push(requestResponse) + } + } - if (leading) { - for (; lead < str.length && isHTTPWhiteSpace(str[lead]); lead++); + return resultList } - if (trailing) { - for (; trail > 0 && isHTTPWhiteSpace(str[trail]); trail--); - } + /** + * @see https://w3c.github.io/ServiceWorker/#request-matches-cached-item-algorithm + * @param {any} requestQuery + * @param {any} request + * @param {any | null} response + * @param {import('../../types/cache').CacheQueryOptions | undefined} options + * @returns {boolean} + */ + #requestMatchesCachedItem (requestQuery, request, response = null, options) { + // if (options?.ignoreMethod === false && request.method === 'GET') { + // return false + // } - return str.slice(lead, trail + 1) -} + const queryURL = new URL(requestQuery.url) -/** - * @see https://infra.spec.whatwg.org/#ascii-whitespace - * @param {string} char - */ -function isASCIIWhitespace (char) { - return char === '\r' || char === '\n' || char === '\t' || char === '\f' || char === ' ' -} + const cachedURL = new URL(request.url) -/** - * @see https://infra.spec.whatwg.org/#strip-leading-and-trailing-ascii-whitespace - */ -function removeASCIIWhitespace (str, leading = true, trailing = true) { - let lead = 0 - let trail = str.length - 1 + if (options?.ignoreSearch) { + cachedURL.search = '' - if (leading) { - for (; lead < str.length && isASCIIWhitespace(str[lead]); lead++); - } + queryURL.search = '' + } - if (trailing) { - for (; trail > 0 && isASCIIWhitespace(str[trail]); trail--); - } + if (!urlEquals(queryURL, cachedURL, true)) { + return false + } - return str.slice(lead, trail + 1) -} + if ( + response == null || + options?.ignoreVary || + !response.headersList.contains('vary') + ) { + return true + } -module.exports = { - dataURLProcessor, - URLSerializer, - collectASequenceOfCodePoints, - collectASequenceOfCodePointsFast, - stringPercentDecode, - parseMIMEType, - collectAnHTTPQuotedString, - serializeAMimeType -} + const fieldValues = getFieldValues(response.headersList.get('vary')) + for (const fieldValue of fieldValues) { + if (fieldValue === '*') { + return false + } -/***/ }), + const requestValue = request.headersList.get(fieldValue) + const queryValue = requestQuery.headersList.get(fieldValue) -/***/ 7206: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // If one has the header and the other doesn't, or one has + // a different value than the other, return false + if (requestValue !== queryValue) { + return false + } + } -"use strict"; + return true + } + #internalMatchAll (request, options, maxResponses = Infinity) { + // 1. + let r = null -const { Blob, File: NativeFile } = __nccwpck_require__(181) -const { types } = __nccwpck_require__(9023) -const { kState } = __nccwpck_require__(2895) -const { isBlobLike } = __nccwpck_require__(1612) -const { webidl } = __nccwpck_require__(8201) -const { parseMIMEType, serializeAMimeType } = __nccwpck_require__(4955) -const { kEnumerableProperty } = __nccwpck_require__(5069) -const encoder = new TextEncoder() + // 2. + if (request !== undefined) { + if (request instanceof Request) { + // 2.1.1 + r = request[kState] -class File extends Blob { - constructor (fileBits, fileName, options = {}) { - // The File constructor is invoked with two or three parameters, depending - // on whether the optional dictionary parameter is used. When the File() - // constructor is invoked, user agents must run the following steps: - webidl.argumentLengthCheck(arguments, 2, { header: 'File constructor' }) + // 2.1.2 + if (r.method !== 'GET' && !options.ignoreMethod) { + return [] + } + } else if (typeof request === 'string') { + // 2.2.1 + r = new Request(request)[kState] + } + } - fileBits = webidl.converters['sequence'](fileBits) - fileName = webidl.converters.USVString(fileName) - options = webidl.converters.FilePropertyBag(options) + // 5. + // 5.1 + const responses = [] - // 1. Let bytes be the result of processing blob parts given fileBits and - // options. - // Note: Blob handles this for us + // 5.2 + if (request === undefined) { + // 5.2.1 + for (const requestResponse of this.#relevantRequestResponseList) { + responses.push(requestResponse[1]) + } + } else { // 5.3 + // 5.3.1 + const requestResponses = this.#queryCache(r, options) - // 2. Let n be the fileName argument to the constructor. - const n = fileName + // 5.3.2 + for (const requestResponse of requestResponses) { + responses.push(requestResponse[1]) + } + } - // 3. Process FilePropertyBag dictionary argument by running the following - // substeps: + // 5.4 + // We don't implement CORs so we don't need to loop over the responses, yay! - // 1. If the type member is provided and is not the empty string, let t - // be set to the type dictionary member. If t contains any characters - // outside the range U+0020 to U+007E, then set t to the empty string - // and return from these substeps. - // 2. Convert every character in t to ASCII lowercase. - let t = options.type - let d + // 5.5.1 + const responseList = [] - // eslint-disable-next-line no-labels - substep: { - if (t) { - t = parseMIMEType(t) + // 5.5.2 + for (const response of responses) { + // 5.5.2.1 + const responseObject = fromInnerResponse(response, 'immutable') - if (t === 'failure') { - t = '' - // eslint-disable-next-line no-labels - break substep - } + responseList.push(responseObject.clone()) - t = serializeAMimeType(t).toLowerCase() + if (responseList.length >= maxResponses) { + break } - - // 3. If the lastModified member is provided, let d be set to the - // lastModified dictionary member. If it is not provided, set d to the - // current date and time represented as the number of milliseconds since - // the Unix Epoch (which is the equivalent of Date.now() [ECMA-262]). - d = options.lastModified } - // 4. Return a new File object F such that: - // F refers to the bytes byte sequence. - // F.size is set to the number of total bytes in bytes. - // F.name is set to n. - // F.type is set to t. - // F.lastModified is set to d. - - super(processBlobParts(fileBits, options), { type: t }) - this[kState] = { - name: n, - lastModified: d, - type: t - } + // 6. + return Object.freeze(responseList) } +} - get name () { - webidl.brandCheck(this, File) +Object.defineProperties(Cache.prototype, { + [Symbol.toStringTag]: { + value: 'Cache', + configurable: true + }, + match: kEnumerableProperty, + matchAll: kEnumerableProperty, + add: kEnumerableProperty, + addAll: kEnumerableProperty, + put: kEnumerableProperty, + delete: kEnumerableProperty, + keys: kEnumerableProperty +}) - return this[kState].name +const cacheQueryOptionConverters = [ + { + key: 'ignoreSearch', + converter: webidl.converters.boolean, + defaultValue: () => false + }, + { + key: 'ignoreMethod', + converter: webidl.converters.boolean, + defaultValue: () => false + }, + { + key: 'ignoreVary', + converter: webidl.converters.boolean, + defaultValue: () => false } +] - get lastModified () { - webidl.brandCheck(this, File) +webidl.converters.CacheQueryOptions = webidl.dictionaryConverter(cacheQueryOptionConverters) - return this[kState].lastModified +webidl.converters.MultiCacheQueryOptions = webidl.dictionaryConverter([ + ...cacheQueryOptionConverters, + { + key: 'cacheName', + converter: webidl.converters.DOMString } +]) - get type () { - webidl.brandCheck(this, File) - - return this[kState].type - } -} +webidl.converters.Response = webidl.interfaceConverter(Response) -class FileLike { - constructor (blobLike, fileName, options = {}) { - // TODO: argument idl type check +webidl.converters['sequence'] = webidl.sequenceConverter( + webidl.converters.RequestInfo +) - // The File constructor is invoked with two or three parameters, depending - // on whether the optional dictionary parameter is used. When the File() - // constructor is invoked, user agents must run the following steps: +module.exports = { + Cache +} - // 1. Let bytes be the result of processing blob parts given fileBits and - // options. - // 2. Let n be the fileName argument to the constructor. - const n = fileName +/***/ }), - // 3. Process FilePropertyBag dictionary argument by running the following - // substeps: +/***/ 9603: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - // 1. If the type member is provided and is not the empty string, let t - // be set to the type dictionary member. If t contains any characters - // outside the range U+0020 to U+007E, then set t to the empty string - // and return from these substeps. - // TODO - const t = options.type - // 2. Convert every character in t to ASCII lowercase. - // TODO - // 3. If the lastModified member is provided, let d be set to the - // lastModified dictionary member. If it is not provided, set d to the - // current date and time represented as the number of milliseconds since - // the Unix Epoch (which is the equivalent of Date.now() [ECMA-262]). - const d = options.lastModified ?? Date.now() +const { kConstruct } = __nccwpck_require__(7415) +const { Cache } = __nccwpck_require__(6172) +const { webidl } = __nccwpck_require__(4859) +const { kEnumerableProperty } = __nccwpck_require__(7234) - // 4. Return a new File object F such that: - // F refers to the bytes byte sequence. - // F.size is set to the number of total bytes in bytes. - // F.name is set to n. - // F.type is set to t. - // F.lastModified is set to d. +class CacheStorage { + /** + * @see https://w3c.github.io/ServiceWorker/#dfn-relevant-name-to-cache-map + * @type {Map} + */ + async has (cacheName) { + webidl.brandCheck(this, CacheStorage) - return this[kState].blobLike.type - } + const prefix = 'CacheStorage.has' + webidl.argumentLengthCheck(arguments, 1, prefix) - get name () { - webidl.brandCheck(this, FileLike) + cacheName = webidl.converters.DOMString(cacheName, prefix, 'cacheName') - return this[kState].name + // 2.1.1 + // 2.2 + return this.#caches.has(cacheName) } - get lastModified () { - webidl.brandCheck(this, FileLike) - - return this[kState].lastModified - } + /** + * @see https://w3c.github.io/ServiceWorker/#dom-cachestorage-open + * @param {string} cacheName + * @returns {Promise} + */ + async open (cacheName) { + webidl.brandCheck(this, CacheStorage) - get [Symbol.toStringTag] () { - return 'File' - } -} + const prefix = 'CacheStorage.open' + webidl.argumentLengthCheck(arguments, 1, prefix) -Object.defineProperties(File.prototype, { - [Symbol.toStringTag]: { - value: 'File', - configurable: true - }, - name: kEnumerableProperty, - lastModified: kEnumerableProperty -}) + cacheName = webidl.converters.DOMString(cacheName, prefix, 'cacheName') -webidl.converters.Blob = webidl.interfaceConverter(Blob) + // 2.1 + if (this.#caches.has(cacheName)) { + // await caches.open('v1') !== await caches.open('v1') -webidl.converters.BlobPart = function (V, opts) { - if (webidl.util.Type(V) === 'Object') { - if (isBlobLike(V)) { - return webidl.converters.Blob(V, { strict: false }) - } + // 2.1.1 + const cache = this.#caches.get(cacheName) - if ( - ArrayBuffer.isView(V) || - types.isAnyArrayBuffer(V) - ) { - return webidl.converters.BufferSource(V, opts) + // 2.1.1.1 + return new Cache(kConstruct, cache) } - } - - return webidl.converters.USVString(V, opts) -} - -webidl.converters['sequence'] = webidl.sequenceConverter( - webidl.converters.BlobPart -) -// https://www.w3.org/TR/FileAPI/#dfn-FilePropertyBag -webidl.converters.FilePropertyBag = webidl.dictionaryConverter([ - { - key: 'lastModified', - converter: webidl.converters['long long'], - get defaultValue () { - return Date.now() - } - }, - { - key: 'type', - converter: webidl.converters.DOMString, - defaultValue: '' - }, - { - key: 'endings', - converter: (value) => { - value = webidl.converters.DOMString(value) - value = value.toLowerCase() + // 2.2 + const cache = [] - if (value !== 'native') { - value = 'transparent' - } + // 2.3 + this.#caches.set(cacheName, cache) - return value - }, - defaultValue: 'transparent' + // 2.4 + return new Cache(kConstruct, cache) } -]) -/** - * @see https://www.w3.org/TR/FileAPI/#process-blob-parts - * @param {(NodeJS.TypedArray|Blob|string)[]} parts - * @param {{ type: string, endings: string }} options - */ -function processBlobParts (parts, options) { - // 1. Let bytes be an empty sequence of bytes. - /** @type {NodeJS.TypedArray[]} */ - const bytes = [] + /** + * @see https://w3c.github.io/ServiceWorker/#cache-storage-delete + * @param {string} cacheName + * @returns {Promise} + */ + async delete (cacheName) { + webidl.brandCheck(this, CacheStorage) - // 2. For each element in parts: - for (const element of parts) { - // 1. If element is a USVString, run the following substeps: - if (typeof element === 'string') { - // 1. Let s be element. - let s = element + const prefix = 'CacheStorage.delete' + webidl.argumentLengthCheck(arguments, 1, prefix) - // 2. If the endings member of options is "native", set s - // to the result of converting line endings to native - // of element. - if (options.endings === 'native') { - s = convertLineEndingsNative(s) - } + cacheName = webidl.converters.DOMString(cacheName, prefix, 'cacheName') - // 3. Append the result of UTF-8 encoding s to bytes. - bytes.push(encoder.encode(s)) - } else if ( - types.isAnyArrayBuffer(element) || - types.isTypedArray(element) - ) { - // 2. If element is a BufferSource, get a copy of the - // bytes held by the buffer source, and append those - // bytes to bytes. - if (!element.buffer) { // ArrayBuffer - bytes.push(new Uint8Array(element)) - } else { - bytes.push( - new Uint8Array(element.buffer, element.byteOffset, element.byteLength) - ) - } - } else if (isBlobLike(element)) { - // 3. If element is a Blob, append the bytes it represents - // to bytes. - bytes.push(element) - } + return this.#caches.delete(cacheName) } - // 3. Return bytes. - return bytes -} + /** + * @see https://w3c.github.io/ServiceWorker/#cache-storage-keys + * @returns {Promise} + */ + async keys () { + webidl.brandCheck(this, CacheStorage) -/** - * @see https://www.w3.org/TR/FileAPI/#convert-line-endings-to-native - * @param {string} s - */ -function convertLineEndingsNative (s) { - // 1. Let native line ending be be the code point U+000A LF. - let nativeLineEnding = '\n' + // 2.1 + const keys = this.#caches.keys() - // 2. If the underlying platform’s conventions are to - // represent newlines as a carriage return and line feed - // sequence, set native line ending to the code point - // U+000D CR followed by the code point U+000A LF. - if (process.platform === 'win32') { - nativeLineEnding = '\r\n' + // 2.2 + return [...keys] } - - return s.replace(/\r?\n/g, nativeLineEnding) } -// If this function is moved to ./util.js, some tools (such as -// rollup) will warn about circular dependencies. See: -// https://github.com/nodejs/undici/issues/1629 -function isFileLike (object) { - return ( - (NativeFile && object instanceof NativeFile) || - object instanceof File || ( - object && - (typeof object.stream === 'function' || - typeof object.arrayBuffer === 'function') && - object[Symbol.toStringTag] === 'File' - ) - ) -} +Object.defineProperties(CacheStorage.prototype, { + [Symbol.toStringTag]: { + value: 'CacheStorage', + configurable: true + }, + match: kEnumerableProperty, + has: kEnumerableProperty, + open: kEnumerableProperty, + delete: kEnumerableProperty, + keys: kEnumerableProperty +}) -module.exports = { File, FileLike, isFileLike } +module.exports = { + CacheStorage +} /***/ }), -/***/ 322: +/***/ 7415: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; - - -const { isBlobLike, toUSVString, makeIterator } = __nccwpck_require__(1612) -const { kState } = __nccwpck_require__(2895) -const { File: UndiciFile, FileLike, isFileLike } = __nccwpck_require__(7206) -const { webidl } = __nccwpck_require__(8201) -const { Blob, File: NativeFile } = __nccwpck_require__(181) - -/** @type {globalThis['File']} */ -const File = NativeFile ?? UndiciFile - -// https://xhr.spec.whatwg.org/#formdata -class FormData { - constructor (form) { - if (form !== undefined) { - throw webidl.errors.conversionFailed({ - prefix: 'FormData constructor', - argument: 'Argument 1', - types: ['undefined'] - }) - } - - this[kState] = [] - } - append (name, value, filename = undefined) { - webidl.brandCheck(this, FormData) - webidl.argumentLengthCheck(arguments, 2, { header: 'FormData.append' }) +module.exports = { + kConstruct: (__nccwpck_require__(7417).kConstruct) +} - if (arguments.length === 3 && !isBlobLike(value)) { - throw new TypeError( - "Failed to execute 'append' on 'FormData': parameter 2 is not of type 'Blob'" - ) - } - // 1. Let value be value if given; otherwise blobValue. +/***/ }), - name = webidl.converters.USVString(name) - value = isBlobLike(value) - ? webidl.converters.Blob(value, { strict: false }) - : webidl.converters.USVString(value) - filename = arguments.length === 3 - ? webidl.converters.USVString(filename) - : undefined +/***/ 3399: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - // 2. Let entry be the result of creating an entry with - // name, value, and filename if given. - const entry = makeEntry(name, value, filename) - // 3. Append entry to this’s entry list. - this[kState].push(entry) - } - delete (name) { - webidl.brandCheck(this, FormData) +const assert = __nccwpck_require__(4589) +const { URLSerializer } = __nccwpck_require__(6406) +const { isValidHeaderName } = __nccwpck_require__(1046) - webidl.argumentLengthCheck(arguments, 1, { header: 'FormData.delete' }) +/** + * @see https://url.spec.whatwg.org/#concept-url-equals + * @param {URL} A + * @param {URL} B + * @param {boolean | undefined} excludeFragment + * @returns {boolean} + */ +function urlEquals (A, B, excludeFragment = false) { + const serializedA = URLSerializer(A, excludeFragment) - name = webidl.converters.USVString(name) + const serializedB = URLSerializer(B, excludeFragment) - // The delete(name) method steps are to remove all entries whose name - // is name from this’s entry list. - this[kState] = this[kState].filter(entry => entry.name !== name) - } + return serializedA === serializedB +} - get (name) { - webidl.brandCheck(this, FormData) +/** + * @see https://github.com/chromium/chromium/blob/694d20d134cb553d8d89e5500b9148012b1ba299/content/browser/cache_storage/cache_storage_cache.cc#L260-L262 + * @param {string} header + */ +function getFieldValues (header) { + assert(header !== null) - webidl.argumentLengthCheck(arguments, 1, { header: 'FormData.get' }) + const values = [] - name = webidl.converters.USVString(name) + for (let value of header.split(',')) { + value = value.trim() - // 1. If there is no entry whose name is name in this’s entry list, - // then return null. - const idx = this[kState].findIndex((entry) => entry.name === name) - if (idx === -1) { - return null + if (isValidHeaderName(value)) { + values.push(value) } - - // 2. Return the value of the first entry whose name is name from - // this’s entry list. - return this[kState][idx].value } - getAll (name) { - webidl.brandCheck(this, FormData) - - webidl.argumentLengthCheck(arguments, 1, { header: 'FormData.getAll' }) + return values +} - name = webidl.converters.USVString(name) +module.exports = { + urlEquals, + getFieldValues +} - // 1. If there is no entry whose name is name in this’s entry list, - // then return the empty list. - // 2. Return the values of all entries whose name is name, in order, - // from this’s entry list. - return this[kState] - .filter((entry) => entry.name === name) - .map((entry) => entry.value) - } - has (name) { - webidl.brandCheck(this, FormData) +/***/ }), - webidl.argumentLengthCheck(arguments, 1, { header: 'FormData.has' }) +/***/ 3114: +/***/ ((module) => { - name = webidl.converters.USVString(name) - // The has(name) method steps are to return true if there is an entry - // whose name is name in this’s entry list; otherwise false. - return this[kState].findIndex((entry) => entry.name === name) !== -1 - } - set (name, value, filename = undefined) { - webidl.brandCheck(this, FormData) +// https://wicg.github.io/cookie-store/#cookie-maximum-attribute-value-size +const maxAttributeValueSize = 1024 - webidl.argumentLengthCheck(arguments, 2, { header: 'FormData.set' }) +// https://wicg.github.io/cookie-store/#cookie-maximum-name-value-pair-size +const maxNameValuePairSize = 4096 - if (arguments.length === 3 && !isBlobLike(value)) { - throw new TypeError( - "Failed to execute 'set' on 'FormData': parameter 2 is not of type 'Blob'" - ) - } +module.exports = { + maxAttributeValueSize, + maxNameValuePairSize +} - // The set(name, value) and set(name, blobValue, filename) method steps - // are: - // 1. Let value be value if given; otherwise blobValue. +/***/ }), - name = webidl.converters.USVString(name) - value = isBlobLike(value) - ? webidl.converters.Blob(value, { strict: false }) - : webidl.converters.USVString(value) - filename = arguments.length === 3 - ? toUSVString(filename) - : undefined +/***/ 3191: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - // 2. Let entry be the result of creating an entry with name, value, and - // filename if given. - const entry = makeEntry(name, value, filename) - // 3. If there are entries in this’s entry list whose name is name, then - // replace the first such entry with entry and remove the others. - const idx = this[kState].findIndex((entry) => entry.name === name) - if (idx !== -1) { - this[kState] = [ - ...this[kState].slice(0, idx), - entry, - ...this[kState].slice(idx + 1).filter((entry) => entry.name !== name) - ] - } else { - // 4. Otherwise, append entry to this’s entry list. - this[kState].push(entry) - } - } - entries () { - webidl.brandCheck(this, FormData) +const { parseSetCookie } = __nccwpck_require__(7168) +const { stringify } = __nccwpck_require__(1127) +const { webidl } = __nccwpck_require__(4859) +const { Headers } = __nccwpck_require__(217) - return makeIterator( - () => this[kState].map(pair => [pair.name, pair.value]), - 'FormData', - 'key+value' - ) - } +/** + * @typedef {Object} Cookie + * @property {string} name + * @property {string} value + * @property {Date|number|undefined} expires + * @property {number|undefined} maxAge + * @property {string|undefined} domain + * @property {string|undefined} path + * @property {boolean|undefined} secure + * @property {boolean|undefined} httpOnly + * @property {'Strict'|'Lax'|'None'} sameSite + * @property {string[]} unparsed + */ - keys () { - webidl.brandCheck(this, FormData) +/** + * @param {Headers} headers + * @returns {Record} + */ +function getCookies (headers) { + webidl.argumentLengthCheck(arguments, 1, 'getCookies') - return makeIterator( - () => this[kState].map(pair => [pair.name, pair.value]), - 'FormData', - 'key' - ) - } + webidl.brandCheck(headers, Headers, { strict: false }) - values () { - webidl.brandCheck(this, FormData) + const cookie = headers.get('cookie') + const out = {} - return makeIterator( - () => this[kState].map(pair => [pair.name, pair.value]), - 'FormData', - 'value' - ) + if (!cookie) { + return out } - /** - * @param {(value: string, key: string, self: FormData) => void} callbackFn - * @param {unknown} thisArg - */ - forEach (callbackFn, thisArg = globalThis) { - webidl.brandCheck(this, FormData) - - webidl.argumentLengthCheck(arguments, 1, { header: 'FormData.forEach' }) - - if (typeof callbackFn !== 'function') { - throw new TypeError( - "Failed to execute 'forEach' on 'FormData': parameter 1 is not of type 'Function'." - ) - } + for (const piece of cookie.split(';')) { + const [name, ...value] = piece.split('=') - for (const [key, value] of this) { - callbackFn.apply(thisArg, [value, key, this]) - } + out[name.trim()] = value.join('=') } -} - -FormData.prototype[Symbol.iterator] = FormData.prototype.entries -Object.defineProperties(FormData.prototype, { - [Symbol.toStringTag]: { - value: 'FormData', - configurable: true - } -}) + return out +} /** - * @see https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#create-an-entry + * @param {Headers} headers * @param {string} name - * @param {string|Blob} value - * @param {?string} filename - * @returns + * @param {{ path?: string, domain?: string }|undefined} attributes + * @returns {void} */ -function makeEntry (name, value, filename) { - // 1. Set name to the result of converting name into a scalar value string. - // "To convert a string into a scalar value string, replace any surrogates - // with U+FFFD." - // see: https://nodejs.org/dist/latest-v18.x/docs/api/buffer.html#buftostringencoding-start-end - name = Buffer.from(name).toString('utf8') - - // 2. If value is a string, then set value to the result of converting - // value into a scalar value string. - if (typeof value === 'string') { - value = Buffer.from(value).toString('utf8') - } else { - // 3. Otherwise: - - // 1. If value is not a File object, then set value to a new File object, - // representing the same bytes, whose name attribute value is "blob" - if (!isFileLike(value)) { - value = value instanceof Blob - ? new File([value], 'blob', { type: value.type }) - : new FileLike(value, 'blob', { type: value.type }) - } +function deleteCookie (headers, name, attributes) { + webidl.brandCheck(headers, Headers, { strict: false }) - // 2. If filename is given, then set value to a new File object, - // representing the same bytes, whose name attribute is filename. - if (filename !== undefined) { - /** @type {FilePropertyBag} */ - const options = { - type: value.type, - lastModified: value.lastModified - } + const prefix = 'deleteCookie' + webidl.argumentLengthCheck(arguments, 2, prefix) - value = (NativeFile && value instanceof NativeFile) || value instanceof UndiciFile - ? new File([value], filename, options) - : new FileLike(value, filename, options) - } - } + name = webidl.converters.DOMString(name, prefix, 'name') + attributes = webidl.converters.DeleteCookieAttributes(attributes) - // 4. Return an entry whose name is name and whose value is value. - return { name, value } + // Matches behavior of + // https://github.com/denoland/deno_std/blob/63827b16330b82489a04614027c33b7904e08be5/http/cookie.ts#L278 + setCookie(headers, { + name, + value: '', + expires: new Date(0), + ...attributes + }) } -module.exports = { FormData } - - -/***/ }), - -/***/ 4407: -/***/ ((module) => { +/** + * @param {Headers} headers + * @returns {Cookie[]} + */ +function getSetCookies (headers) { + webidl.argumentLengthCheck(arguments, 1, 'getSetCookies') -"use strict"; + webidl.brandCheck(headers, Headers, { strict: false }) + const cookies = headers.getSetCookie() -// In case of breaking changes, increase the version -// number to avoid conflicts. -const globalOrigin = Symbol.for('undici.globalOrigin.1') + if (!cookies) { + return [] + } -function getGlobalOrigin () { - return globalThis[globalOrigin] + return cookies.map((pair) => parseSetCookie(pair)) } -function setGlobalOrigin (newOrigin) { - if (newOrigin === undefined) { - Object.defineProperty(globalThis, globalOrigin, { - value: undefined, - writable: true, - enumerable: false, - configurable: false - }) - - return - } +/** + * @param {Headers} headers + * @param {Cookie} cookie + * @returns {void} + */ +function setCookie (headers, cookie) { + webidl.argumentLengthCheck(arguments, 2, 'setCookie') - const parsedURL = new URL(newOrigin) + webidl.brandCheck(headers, Headers, { strict: false }) - if (parsedURL.protocol !== 'http:' && parsedURL.protocol !== 'https:') { - throw new TypeError(`Only http & https urls are allowed, received ${parsedURL.protocol}`) - } + cookie = webidl.converters.Cookie(cookie) - Object.defineProperty(globalThis, globalOrigin, { - value: parsedURL, - writable: true, - enumerable: false, - configurable: false - }) -} + const str = stringify(cookie) -module.exports = { - getGlobalOrigin, - setGlobalOrigin + if (str) { + headers.append('Set-Cookie', str) + } } +webidl.converters.DeleteCookieAttributes = webidl.dictionaryConverter([ + { + converter: webidl.nullableConverter(webidl.converters.DOMString), + key: 'path', + defaultValue: () => null + }, + { + converter: webidl.nullableConverter(webidl.converters.DOMString), + key: 'domain', + defaultValue: () => null + } +]) -/***/ }), +webidl.converters.Cookie = webidl.dictionaryConverter([ + { + converter: webidl.converters.DOMString, + key: 'name' + }, + { + converter: webidl.converters.DOMString, + key: 'value' + }, + { + converter: webidl.nullableConverter((value) => { + if (typeof value === 'number') { + return webidl.converters['unsigned long long'](value) + } -/***/ 3640: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + return new Date(value) + }), + key: 'expires', + defaultValue: () => null + }, + { + converter: webidl.nullableConverter(webidl.converters['long long']), + key: 'maxAge', + defaultValue: () => null + }, + { + converter: webidl.nullableConverter(webidl.converters.DOMString), + key: 'domain', + defaultValue: () => null + }, + { + converter: webidl.nullableConverter(webidl.converters.DOMString), + key: 'path', + defaultValue: () => null + }, + { + converter: webidl.nullableConverter(webidl.converters.boolean), + key: 'secure', + defaultValue: () => null + }, + { + converter: webidl.nullableConverter(webidl.converters.boolean), + key: 'httpOnly', + defaultValue: () => null + }, + { + converter: webidl.converters.USVString, + key: 'sameSite', + allowedValues: ['Strict', 'Lax', 'None'] + }, + { + converter: webidl.sequenceConverter(webidl.converters.DOMString), + key: 'unparsed', + defaultValue: () => new Array(0) + } +]) -"use strict"; -// https://github.com/Ethan-Arrowood/undici-fetch +module.exports = { + getCookies, + deleteCookie, + getSetCookies, + setCookie +} +/***/ }), -const { kHeadersList, kConstruct } = __nccwpck_require__(1028) -const { kGuard } = __nccwpck_require__(2895) -const { kEnumerableProperty } = __nccwpck_require__(5069) -const { - makeIterator, - isValidHeaderName, - isValidHeaderValue -} = __nccwpck_require__(1612) -const util = __nccwpck_require__(9023) -const { webidl } = __nccwpck_require__(8201) -const assert = __nccwpck_require__(2613) +/***/ 7168: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -const kHeadersMap = Symbol('headers map') -const kHeadersSortedMap = Symbol('headers map sorted') -/** - * @param {number} code - */ -function isHTTPWhiteSpaceCharCode (code) { - return code === 0x00a || code === 0x00d || code === 0x009 || code === 0x020 -} + +const { maxNameValuePairSize, maxAttributeValueSize } = __nccwpck_require__(3114) +const { isCTLExcludingHtab } = __nccwpck_require__(1127) +const { collectASequenceOfCodePointsFast } = __nccwpck_require__(6406) +const assert = __nccwpck_require__(4589) /** - * @see https://fetch.spec.whatwg.org/#concept-header-value-normalize - * @param {string} potentialValue + * @description Parses the field-value attributes of a set-cookie header string. + * @see https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4 + * @param {string} header + * @returns if the header is invalid, null will be returned */ -function headerValueNormalize (potentialValue) { - // To normalize a byte sequence potentialValue, remove - // any leading and trailing HTTP whitespace bytes from - // potentialValue. - let i = 0; let j = potentialValue.length - - while (j > i && isHTTPWhiteSpaceCharCode(potentialValue.charCodeAt(j - 1))) --j - while (j > i && isHTTPWhiteSpaceCharCode(potentialValue.charCodeAt(i))) ++i +function parseSetCookie (header) { + // 1. If the set-cookie-string contains a %x00-08 / %x0A-1F / %x7F + // character (CTL characters excluding HTAB): Abort these steps and + // ignore the set-cookie-string entirely. + if (isCTLExcludingHtab(header)) { + return null + } - return i === 0 && j === potentialValue.length ? potentialValue : potentialValue.substring(i, j) -} + let nameValuePair = '' + let unparsedAttributes = '' + let name = '' + let value = '' -function fill (headers, object) { - // To fill a Headers object headers with a given object object, run these steps: + // 2. If the set-cookie-string contains a %x3B (";") character: + if (header.includes(';')) { + // 1. The name-value-pair string consists of the characters up to, + // but not including, the first %x3B (";"), and the unparsed- + // attributes consist of the remainder of the set-cookie-string + // (including the %x3B (";") in question). + const position = { position: 0 } - // 1. If object is a sequence, then for each header in object: - // Note: webidl conversion to array has already been done. - if (Array.isArray(object)) { - for (let i = 0; i < object.length; ++i) { - const header = object[i] - // 1. If header does not contain exactly two items, then throw a TypeError. - if (header.length !== 2) { - throw webidl.errors.exception({ - header: 'Headers constructor', - message: `expected name/value pair to be length 2, found ${header.length}.` - }) - } + nameValuePair = collectASequenceOfCodePointsFast(';', header, position) + unparsedAttributes = header.slice(position.position) + } else { + // Otherwise: - // 2. Append (header’s first item, header’s second item) to headers. - appendHeader(headers, header[0], header[1]) - } - } else if (typeof object === 'object' && object !== null) { - // Note: null should throw + // 1. The name-value-pair string consists of all the characters + // contained in the set-cookie-string, and the unparsed- + // attributes is the empty string. + nameValuePair = header + } - // 2. Otherwise, object is a record, then for each key → value in object, - // append (key, value) to headers - const keys = Object.keys(object) - for (let i = 0; i < keys.length; ++i) { - appendHeader(headers, keys[i], object[keys[i]]) - } + // 3. If the name-value-pair string lacks a %x3D ("=") character, then + // the name string is empty, and the value string is the value of + // name-value-pair. + if (!nameValuePair.includes('=')) { + value = nameValuePair } else { - throw webidl.errors.conversionFailed({ - prefix: 'Headers constructor', - argument: 'Argument 1', - types: ['sequence>', 'record'] - }) + // Otherwise, the name string consists of the characters up to, but + // not including, the first %x3D ("=") character, and the (possibly + // empty) value string consists of the characters after the first + // %x3D ("=") character. + const position = { position: 0 } + name = collectASequenceOfCodePointsFast( + '=', + nameValuePair, + position + ) + value = nameValuePair.slice(position.position + 1) } -} -/** - * @see https://fetch.spec.whatwg.org/#concept-headers-append - */ -function appendHeader (headers, name, value) { - // 1. Normalize value. - value = headerValueNormalize(value) + // 4. Remove any leading or trailing WSP characters from the name + // string and the value string. + name = name.trim() + value = value.trim() - // 2. If name is not a header name or value is not a - // header value, then throw a TypeError. - if (!isValidHeaderName(name)) { - throw webidl.errors.invalidArgument({ - prefix: 'Headers.append', - value: name, - type: 'header name' - }) - } else if (!isValidHeaderValue(value)) { - throw webidl.errors.invalidArgument({ - prefix: 'Headers.append', - value, - type: 'header value' - }) + // 5. If the sum of the lengths of the name string and the value string + // is more than 4096 octets, abort these steps and ignore the set- + // cookie-string entirely. + if (name.length + value.length > maxNameValuePairSize) { + return null } - // 3. If headers’s guard is "immutable", then throw a TypeError. - // 4. Otherwise, if headers’s guard is "request" and name is a - // forbidden header name, return. - // Note: undici does not implement forbidden header names - if (headers[kGuard] === 'immutable') { - throw new TypeError('immutable') - } else if (headers[kGuard] === 'request-no-cors') { - // 5. Otherwise, if headers’s guard is "request-no-cors": - // TODO + // 6. The cookie-name is the name string, and the cookie-value is the + // value string. + return { + name, value, ...parseUnparsedAttributes(unparsedAttributes) } - - // 6. Otherwise, if headers’s guard is "response" and name is a - // forbidden response-header name, return. - - // 7. Append (name, value) to headers’s header list. - return headers[kHeadersList].append(name, value) - - // 8. If headers’s guard is "request-no-cors", then remove - // privileged no-CORS request headers from headers } -class HeadersList { - /** @type {[string, string][]|null} */ - cookies = null - - constructor (init) { - if (init instanceof HeadersList) { - this[kHeadersMap] = new Map(init[kHeadersMap]) - this[kHeadersSortedMap] = init[kHeadersSortedMap] - this.cookies = init.cookies === null ? null : [...init.cookies] - } else { - this[kHeadersMap] = new Map(init) - this[kHeadersSortedMap] = null - } +/** + * Parses the remaining attributes of a set-cookie header + * @see https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4 + * @param {string} unparsedAttributes + * @param {[Object.]={}} cookieAttributeList + */ +function parseUnparsedAttributes (unparsedAttributes, cookieAttributeList = {}) { + // 1. If the unparsed-attributes string is empty, skip the rest of + // these steps. + if (unparsedAttributes.length === 0) { + return cookieAttributeList } - // https://fetch.spec.whatwg.org/#header-list-contains - contains (name) { - // A header list list contains a header name name if list - // contains a header whose name is a byte-case-insensitive - // match for name. - name = name.toLowerCase() + // 2. Discard the first character of the unparsed-attributes (which + // will be a %x3B (";") character). + assert(unparsedAttributes[0] === ';') + unparsedAttributes = unparsedAttributes.slice(1) - return this[kHeadersMap].has(name) - } + let cookieAv = '' - clear () { - this[kHeadersMap].clear() - this[kHeadersSortedMap] = null - this.cookies = null + // 3. If the remaining unparsed-attributes contains a %x3B (";") + // character: + if (unparsedAttributes.includes(';')) { + // 1. Consume the characters of the unparsed-attributes up to, but + // not including, the first %x3B (";") character. + cookieAv = collectASequenceOfCodePointsFast( + ';', + unparsedAttributes, + { position: 0 } + ) + unparsedAttributes = unparsedAttributes.slice(cookieAv.length) + } else { + // Otherwise: + + // 1. Consume the remainder of the unparsed-attributes. + cookieAv = unparsedAttributes + unparsedAttributes = '' } - // https://fetch.spec.whatwg.org/#concept-header-list-append - append (name, value) { - this[kHeadersSortedMap] = null + // Let the cookie-av string be the characters consumed in this step. - // 1. If list contains name, then set name to the first such - // header’s name. - const lowercaseName = name.toLowerCase() - const exists = this[kHeadersMap].get(lowercaseName) + let attributeName = '' + let attributeValue = '' - // 2. Append (name, value) to list. - if (exists) { - const delimiter = lowercaseName === 'cookie' ? '; ' : ', ' - this[kHeadersMap].set(lowercaseName, { - name: exists.name, - value: `${exists.value}${delimiter}${value}` - }) - } else { - this[kHeadersMap].set(lowercaseName, { name, value }) - } + // 4. If the cookie-av string contains a %x3D ("=") character: + if (cookieAv.includes('=')) { + // 1. The (possibly empty) attribute-name string consists of the + // characters up to, but not including, the first %x3D ("=") + // character, and the (possibly empty) attribute-value string + // consists of the characters after the first %x3D ("=") + // character. + const position = { position: 0 } - if (lowercaseName === 'set-cookie') { - this.cookies ??= [] - this.cookies.push(value) - } - } + attributeName = collectASequenceOfCodePointsFast( + '=', + cookieAv, + position + ) + attributeValue = cookieAv.slice(position.position + 1) + } else { + // Otherwise: - // https://fetch.spec.whatwg.org/#concept-header-list-set - set (name, value) { - this[kHeadersSortedMap] = null - const lowercaseName = name.toLowerCase() + // 1. The attribute-name string consists of the entire cookie-av + // string, and the attribute-value string is empty. + attributeName = cookieAv + } - if (lowercaseName === 'set-cookie') { - this.cookies = [value] - } + // 5. Remove any leading or trailing WSP characters from the attribute- + // name string and the attribute-value string. + attributeName = attributeName.trim() + attributeValue = attributeValue.trim() - // 1. If list contains name, then set the value of - // the first such header to value and remove the - // others. - // 2. Otherwise, append header (name, value) to list. - this[kHeadersMap].set(lowercaseName, { name, value }) + // 6. If the attribute-value is longer than 1024 octets, ignore the + // cookie-av string and return to Step 1 of this algorithm. + if (attributeValue.length > maxAttributeValueSize) { + return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList) } - // https://fetch.spec.whatwg.org/#concept-header-list-delete - delete (name) { - this[kHeadersSortedMap] = null + // 7. Process the attribute-name and attribute-value according to the + // requirements in the following subsections. (Notice that + // attributes with unrecognized attribute-names are ignored.) + const attributeNameLowercase = attributeName.toLowerCase() - name = name.toLowerCase() + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.1 + // If the attribute-name case-insensitively matches the string + // "Expires", the user agent MUST process the cookie-av as follows. + if (attributeNameLowercase === 'expires') { + // 1. Let the expiry-time be the result of parsing the attribute-value + // as cookie-date (see Section 5.1.1). + const expiryTime = new Date(attributeValue) - if (name === 'set-cookie') { - this.cookies = null - } + // 2. If the attribute-value failed to parse as a cookie date, ignore + // the cookie-av. - this[kHeadersMap].delete(name) - } + cookieAttributeList.expires = expiryTime + } else if (attributeNameLowercase === 'max-age') { + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.2 + // If the attribute-name case-insensitively matches the string "Max- + // Age", the user agent MUST process the cookie-av as follows. - // https://fetch.spec.whatwg.org/#concept-header-list-get - get (name) { - const value = this[kHeadersMap].get(name.toLowerCase()) + // 1. If the first character of the attribute-value is not a DIGIT or a + // "-" character, ignore the cookie-av. + const charCode = attributeValue.charCodeAt(0) - // 1. If list does not contain name, then return null. - // 2. Return the values of all headers in list whose name - // is a byte-case-insensitive match for name, - // separated from each other by 0x2C 0x20, in order. - return value === undefined ? null : value.value - } + if ((charCode < 48 || charCode > 57) && attributeValue[0] !== '-') { + return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList) + } - * [Symbol.iterator] () { - // use the lowercased name - for (const [name, { value }] of this[kHeadersMap]) { - yield [name, value] + // 2. If the remainder of attribute-value contains a non-DIGIT + // character, ignore the cookie-av. + if (!/^\d+$/.test(attributeValue)) { + return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList) } - } - get entries () { - const headers = {} + // 3. Let delta-seconds be the attribute-value converted to an integer. + const deltaSeconds = Number(attributeValue) - if (this[kHeadersMap].size) { - for (const { name, value } of this[kHeadersMap].values()) { - headers[name] = value - } - } + // 4. Let cookie-age-limit be the maximum age of the cookie (which + // SHOULD be 400 days or less, see Section 4.1.2.2). - return headers - } -} + // 5. Set delta-seconds to the smaller of its present value and cookie- + // age-limit. + // deltaSeconds = Math.min(deltaSeconds * 1000, maxExpiresMs) -// https://fetch.spec.whatwg.org/#headers-class -class Headers { - constructor (init = undefined) { - if (init === kConstruct) { - return - } - this[kHeadersList] = new HeadersList() + // 6. If delta-seconds is less than or equal to zero (0), let expiry- + // time be the earliest representable date and time. Otherwise, let + // the expiry-time be the current date and time plus delta-seconds + // seconds. + // const expiryTime = deltaSeconds <= 0 ? Date.now() : Date.now() + deltaSeconds - // The new Headers(init) constructor steps are: + // 7. Append an attribute to the cookie-attribute-list with an + // attribute-name of Max-Age and an attribute-value of expiry-time. + cookieAttributeList.maxAge = deltaSeconds + } else if (attributeNameLowercase === 'domain') { + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.3 + // If the attribute-name case-insensitively matches the string "Domain", + // the user agent MUST process the cookie-av as follows. - // 1. Set this’s guard to "none". - this[kGuard] = 'none' + // 1. Let cookie-domain be the attribute-value. + let cookieDomain = attributeValue - // 2. If init is given, then fill this with init. - if (init !== undefined) { - init = webidl.converters.HeadersInit(init) - fill(this, init) + // 2. If cookie-domain starts with %x2E ("."), let cookie-domain be + // cookie-domain without its leading %x2E ("."). + if (cookieDomain[0] === '.') { + cookieDomain = cookieDomain.slice(1) } - } - // https://fetch.spec.whatwg.org/#dom-headers-append - append (name, value) { - webidl.brandCheck(this, Headers) + // 3. Convert the cookie-domain to lower case. + cookieDomain = cookieDomain.toLowerCase() + + // 4. Append an attribute to the cookie-attribute-list with an + // attribute-name of Domain and an attribute-value of cookie-domain. + cookieAttributeList.domain = cookieDomain + } else if (attributeNameLowercase === 'path') { + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.4 + // If the attribute-name case-insensitively matches the string "Path", + // the user agent MUST process the cookie-av as follows. - webidl.argumentLengthCheck(arguments, 2, { header: 'Headers.append' }) + // 1. If the attribute-value is empty or if the first character of the + // attribute-value is not %x2F ("/"): + let cookiePath = '' + if (attributeValue.length === 0 || attributeValue[0] !== '/') { + // 1. Let cookie-path be the default-path. + cookiePath = '/' + } else { + // Otherwise: - name = webidl.converters.ByteString(name) - value = webidl.converters.ByteString(value) + // 1. Let cookie-path be the attribute-value. + cookiePath = attributeValue + } - return appendHeader(this, name, value) - } + // 2. Append an attribute to the cookie-attribute-list with an + // attribute-name of Path and an attribute-value of cookie-path. + cookieAttributeList.path = cookiePath + } else if (attributeNameLowercase === 'secure') { + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.5 + // If the attribute-name case-insensitively matches the string "Secure", + // the user agent MUST append an attribute to the cookie-attribute-list + // with an attribute-name of Secure and an empty attribute-value. - // https://fetch.spec.whatwg.org/#dom-headers-delete - delete (name) { - webidl.brandCheck(this, Headers) + cookieAttributeList.secure = true + } else if (attributeNameLowercase === 'httponly') { + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.6 + // If the attribute-name case-insensitively matches the string + // "HttpOnly", the user agent MUST append an attribute to the cookie- + // attribute-list with an attribute-name of HttpOnly and an empty + // attribute-value. - webidl.argumentLengthCheck(arguments, 1, { header: 'Headers.delete' }) + cookieAttributeList.httpOnly = true + } else if (attributeNameLowercase === 'samesite') { + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.7 + // If the attribute-name case-insensitively matches the string + // "SameSite", the user agent MUST process the cookie-av as follows: - name = webidl.converters.ByteString(name) + // 1. Let enforcement be "Default". + let enforcement = 'Default' - // 1. If name is not a header name, then throw a TypeError. - if (!isValidHeaderName(name)) { - throw webidl.errors.invalidArgument({ - prefix: 'Headers.delete', - value: name, - type: 'header name' - }) + const attributeValueLowercase = attributeValue.toLowerCase() + // 2. If cookie-av's attribute-value is a case-insensitive match for + // "None", set enforcement to "None". + if (attributeValueLowercase.includes('none')) { + enforcement = 'None' } - // 2. If this’s guard is "immutable", then throw a TypeError. - // 3. Otherwise, if this’s guard is "request" and name is a - // forbidden header name, return. - // 4. Otherwise, if this’s guard is "request-no-cors", name - // is not a no-CORS-safelisted request-header name, and - // name is not a privileged no-CORS request-header name, - // return. - // 5. Otherwise, if this’s guard is "response" and name is - // a forbidden response-header name, return. - // Note: undici does not implement forbidden header names - if (this[kGuard] === 'immutable') { - throw new TypeError('immutable') - } else if (this[kGuard] === 'request-no-cors') { - // TODO + // 3. If cookie-av's attribute-value is a case-insensitive match for + // "Strict", set enforcement to "Strict". + if (attributeValueLowercase.includes('strict')) { + enforcement = 'Strict' } - // 6. If this’s header list does not contain name, then - // return. - if (!this[kHeadersList].contains(name)) { - return + // 4. If cookie-av's attribute-value is a case-insensitive match for + // "Lax", set enforcement to "Lax". + if (attributeValueLowercase.includes('lax')) { + enforcement = 'Lax' } - // 7. Delete name from this’s header list. - // 8. If this’s guard is "request-no-cors", then remove - // privileged no-CORS request headers from this. - this[kHeadersList].delete(name) + // 5. Append an attribute to the cookie-attribute-list with an + // attribute-name of "SameSite" and an attribute-value of + // enforcement. + cookieAttributeList.sameSite = enforcement + } else { + cookieAttributeList.unparsed ??= [] + + cookieAttributeList.unparsed.push(`${attributeName}=${attributeValue}`) } - // https://fetch.spec.whatwg.org/#dom-headers-get - get (name) { - webidl.brandCheck(this, Headers) + // 8. Return to Step 1 of this algorithm. + return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList) +} - webidl.argumentLengthCheck(arguments, 1, { header: 'Headers.get' }) +module.exports = { + parseSetCookie, + parseUnparsedAttributes +} - name = webidl.converters.ByteString(name) - // 1. If name is not a header name, then throw a TypeError. - if (!isValidHeaderName(name)) { - throw webidl.errors.invalidArgument({ - prefix: 'Headers.get', - value: name, - type: 'header name' - }) - } +/***/ }), - // 2. Return the result of getting name from this’s header - // list. - return this[kHeadersList].get(name) - } +/***/ 1127: +/***/ ((module) => { - // https://fetch.spec.whatwg.org/#dom-headers-has - has (name) { - webidl.brandCheck(this, Headers) - webidl.argumentLengthCheck(arguments, 1, { header: 'Headers.has' }) - name = webidl.converters.ByteString(name) +/** + * @param {string} value + * @returns {boolean} + */ +function isCTLExcludingHtab (value) { + for (let i = 0; i < value.length; ++i) { + const code = value.charCodeAt(i) - // 1. If name is not a header name, then throw a TypeError. - if (!isValidHeaderName(name)) { - throw webidl.errors.invalidArgument({ - prefix: 'Headers.has', - value: name, - type: 'header name' - }) + if ( + (code >= 0x00 && code <= 0x08) || + (code >= 0x0A && code <= 0x1F) || + code === 0x7F + ) { + return true } - - // 2. Return true if this’s header list contains name; - // otherwise false. - return this[kHeadersList].contains(name) } + return false +} - // https://fetch.spec.whatwg.org/#dom-headers-set - set (name, value) { - webidl.brandCheck(this, Headers) - - webidl.argumentLengthCheck(arguments, 2, { header: 'Headers.set' }) - - name = webidl.converters.ByteString(name) - value = webidl.converters.ByteString(value) - - // 1. Normalize value. - value = headerValueNormalize(value) +/** + CHAR = + token = 1* + separators = "(" | ")" | "<" | ">" | "@" + | "," | ";" | ":" | "\" | <"> + | "/" | "[" | "]" | "?" | "=" + | "{" | "}" | SP | HT + * @param {string} name + */ +function validateCookieName (name) { + for (let i = 0; i < name.length; ++i) { + const code = name.charCodeAt(i) - // 2. If name is not a header name or value is not a - // header value, then throw a TypeError. - if (!isValidHeaderName(name)) { - throw webidl.errors.invalidArgument({ - prefix: 'Headers.set', - value: name, - type: 'header name' - }) - } else if (!isValidHeaderValue(value)) { - throw webidl.errors.invalidArgument({ - prefix: 'Headers.set', - value, - type: 'header value' - }) + if ( + code < 0x21 || // exclude CTLs (0-31), SP and HT + code > 0x7E || // exclude non-ascii and DEL + code === 0x22 || // " + code === 0x28 || // ( + code === 0x29 || // ) + code === 0x3C || // < + code === 0x3E || // > + code === 0x40 || // @ + code === 0x2C || // , + code === 0x3B || // ; + code === 0x3A || // : + code === 0x5C || // \ + code === 0x2F || // / + code === 0x5B || // [ + code === 0x5D || // ] + code === 0x3F || // ? + code === 0x3D || // = + code === 0x7B || // { + code === 0x7D // } + ) { + throw new Error('Invalid cookie name') } + } +} - // 3. If this’s guard is "immutable", then throw a TypeError. - // 4. Otherwise, if this’s guard is "request" and name is a - // forbidden header name, return. - // 5. Otherwise, if this’s guard is "request-no-cors" and - // name/value is not a no-CORS-safelisted request-header, - // return. - // 6. Otherwise, if this’s guard is "response" and name is a - // forbidden response-header name, return. - // Note: undici does not implement forbidden header names - if (this[kGuard] === 'immutable') { - throw new TypeError('immutable') - } else if (this[kGuard] === 'request-no-cors') { - // TODO - } +/** + cookie-value = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE ) + cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E + ; US-ASCII characters excluding CTLs, + ; whitespace DQUOTE, comma, semicolon, + ; and backslash + * @param {string} value + */ +function validateCookieValue (value) { + let len = value.length + let i = 0 - // 7. Set (name, value) in this’s header list. - // 8. If this’s guard is "request-no-cors", then remove - // privileged no-CORS request headers from this - this[kHeadersList].set(name, value) + // if the value is wrapped in DQUOTE + if (value[0] === '"') { + if (len === 1 || value[len - 1] !== '"') { + throw new Error('Invalid cookie value') + } + --len + ++i } - // https://fetch.spec.whatwg.org/#dom-headers-getsetcookie - getSetCookie () { - webidl.brandCheck(this, Headers) + while (i < len) { + const code = value.charCodeAt(i++) - // 1. If this’s header list does not contain `Set-Cookie`, then return « ». - // 2. Return the values of all headers in this’s header list whose name is - // a byte-case-insensitive match for `Set-Cookie`, in order. + if ( + code < 0x21 || // exclude CTLs (0-31) + code > 0x7E || // non-ascii and DEL (127) + code === 0x22 || // " + code === 0x2C || // , + code === 0x3B || // ; + code === 0x5C // \ + ) { + throw new Error('Invalid cookie value') + } + } +} - const list = this[kHeadersList].cookies +/** + * path-value = + * @param {string} path + */ +function validateCookiePath (path) { + for (let i = 0; i < path.length; ++i) { + const code = path.charCodeAt(i) - if (list) { - return [...list] + if ( + code < 0x20 || // exclude CTLs (0-31) + code === 0x7F || // DEL + code === 0x3B // ; + ) { + throw new Error('Invalid cookie path') } - - return [] } +} - // https://fetch.spec.whatwg.org/#concept-header-list-sort-and-combine - get [kHeadersSortedMap] () { - if (this[kHeadersList][kHeadersSortedMap]) { - return this[kHeadersList][kHeadersSortedMap] - } +/** + * I have no idea why these values aren't allowed to be honest, + * but Deno tests these. - Khafra + * @param {string} domain + */ +function validateCookieDomain (domain) { + if ( + domain.startsWith('-') || + domain.endsWith('.') || + domain.endsWith('-') + ) { + throw new Error('Invalid cookie domain') + } +} - // 1. Let headers be an empty list of headers with the key being the name - // and value the value. - const headers = [] +const IMFDays = [ + 'Sun', 'Mon', 'Tue', 'Wed', + 'Thu', 'Fri', 'Sat' +] - // 2. Let names be the result of convert header names to a sorted-lowercase - // set with all the names of the headers in list. - const names = [...this[kHeadersList]].sort((a, b) => a[0] < b[0] ? -1 : 1) - const cookies = this[kHeadersList].cookies +const IMFMonths = [ + 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', + 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' +] - // 3. For each name of names: - for (let i = 0; i < names.length; ++i) { - const [name, value] = names[i] - // 1. If name is `set-cookie`, then: - if (name === 'set-cookie') { - // 1. Let values be a list of all values of headers in list whose name - // is a byte-case-insensitive match for name, in order. +const IMFPaddedNumbers = Array(61).fill(0).map((_, i) => i.toString().padStart(2, '0')) - // 2. For each value of values: - // 1. Append (name, value) to headers. - for (let j = 0; j < cookies.length; ++j) { - headers.push([name, cookies[j]]) - } - } else { - // 2. Otherwise: +/** + * @see https://www.rfc-editor.org/rfc/rfc7231#section-7.1.1.1 + * @param {number|Date} date + IMF-fixdate = day-name "," SP date1 SP time-of-day SP GMT + ; fixed length/zone/capitalization subset of the format + ; see Section 3.3 of [RFC5322] - // 1. Let value be the result of getting name from list. + day-name = %x4D.6F.6E ; "Mon", case-sensitive + / %x54.75.65 ; "Tue", case-sensitive + / %x57.65.64 ; "Wed", case-sensitive + / %x54.68.75 ; "Thu", case-sensitive + / %x46.72.69 ; "Fri", case-sensitive + / %x53.61.74 ; "Sat", case-sensitive + / %x53.75.6E ; "Sun", case-sensitive + date1 = day SP month SP year + ; e.g., 02 Jun 1982 - // 2. Assert: value is non-null. - assert(value !== null) + day = 2DIGIT + month = %x4A.61.6E ; "Jan", case-sensitive + / %x46.65.62 ; "Feb", case-sensitive + / %x4D.61.72 ; "Mar", case-sensitive + / %x41.70.72 ; "Apr", case-sensitive + / %x4D.61.79 ; "May", case-sensitive + / %x4A.75.6E ; "Jun", case-sensitive + / %x4A.75.6C ; "Jul", case-sensitive + / %x41.75.67 ; "Aug", case-sensitive + / %x53.65.70 ; "Sep", case-sensitive + / %x4F.63.74 ; "Oct", case-sensitive + / %x4E.6F.76 ; "Nov", case-sensitive + / %x44.65.63 ; "Dec", case-sensitive + year = 4DIGIT - // 3. Append (name, value) to headers. - headers.push([name, value]) - } - } + GMT = %x47.4D.54 ; "GMT", case-sensitive - this[kHeadersList][kHeadersSortedMap] = headers + time-of-day = hour ":" minute ":" second + ; 00:00:00 - 23:59:60 (leap second) - // 4. Return headers. - return headers + hour = 2DIGIT + minute = 2DIGIT + second = 2DIGIT + */ +function toIMFDate (date) { + if (typeof date === 'number') { + date = new Date(date) } - keys () { - webidl.brandCheck(this, Headers) - - if (this[kGuard] === 'immutable') { - const value = this[kHeadersSortedMap] - return makeIterator(() => value, 'Headers', - 'key') - } + return `${IMFDays[date.getUTCDay()]}, ${IMFPaddedNumbers[date.getUTCDate()]} ${IMFMonths[date.getUTCMonth()]} ${date.getUTCFullYear()} ${IMFPaddedNumbers[date.getUTCHours()]}:${IMFPaddedNumbers[date.getUTCMinutes()]}:${IMFPaddedNumbers[date.getUTCSeconds()]} GMT` +} - return makeIterator( - () => [...this[kHeadersSortedMap].values()], - 'Headers', - 'key' - ) +/** + max-age-av = "Max-Age=" non-zero-digit *DIGIT + ; In practice, both expires-av and max-age-av + ; are limited to dates representable by the + ; user agent. + * @param {number} maxAge + */ +function validateCookieMaxAge (maxAge) { + if (maxAge < 0) { + throw new Error('Invalid cookie max-age') } +} - values () { - webidl.brandCheck(this, Headers) - - if (this[kGuard] === 'immutable') { - const value = this[kHeadersSortedMap] - return makeIterator(() => value, 'Headers', - 'value') - } - - return makeIterator( - () => [...this[kHeadersSortedMap].values()], - 'Headers', - 'value' - ) +/** + * @see https://www.rfc-editor.org/rfc/rfc6265#section-4.1.1 + * @param {import('./index').Cookie} cookie + */ +function stringify (cookie) { + if (cookie.name.length === 0) { + return null } - entries () { - webidl.brandCheck(this, Headers) + validateCookieName(cookie.name) + validateCookieValue(cookie.value) - if (this[kGuard] === 'immutable') { - const value = this[kHeadersSortedMap] - return makeIterator(() => value, 'Headers', - 'key+value') - } + const out = [`${cookie.name}=${cookie.value}`] - return makeIterator( - () => [...this[kHeadersSortedMap].values()], - 'Headers', - 'key+value' - ) + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-cookie-prefixes-00#section-3.1 + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-cookie-prefixes-00#section-3.2 + if (cookie.name.startsWith('__Secure-')) { + cookie.secure = true } - /** - * @param {(value: string, key: string, self: Headers) => void} callbackFn - * @param {unknown} thisArg - */ - forEach (callbackFn, thisArg = globalThis) { - webidl.brandCheck(this, Headers) + if (cookie.name.startsWith('__Host-')) { + cookie.secure = true + cookie.domain = null + cookie.path = '/' + } - webidl.argumentLengthCheck(arguments, 1, { header: 'Headers.forEach' }) + if (cookie.secure) { + out.push('Secure') + } - if (typeof callbackFn !== 'function') { - throw new TypeError( - "Failed to execute 'forEach' on 'Headers': parameter 1 is not of type 'Function'." - ) - } + if (cookie.httpOnly) { + out.push('HttpOnly') + } - for (const [key, value] of this) { - callbackFn.apply(thisArg, [value, key, this]) - } + if (typeof cookie.maxAge === 'number') { + validateCookieMaxAge(cookie.maxAge) + out.push(`Max-Age=${cookie.maxAge}`) } - [Symbol.for('nodejs.util.inspect.custom')] () { - webidl.brandCheck(this, Headers) + if (cookie.domain) { + validateCookieDomain(cookie.domain) + out.push(`Domain=${cookie.domain}`) + } - return this[kHeadersList] + if (cookie.path) { + validateCookiePath(cookie.path) + out.push(`Path=${cookie.path}`) } -} -Headers.prototype[Symbol.iterator] = Headers.prototype.entries + if (cookie.expires && cookie.expires.toString() !== 'Invalid Date') { + out.push(`Expires=${toIMFDate(cookie.expires)}`) + } -Object.defineProperties(Headers.prototype, { - append: kEnumerableProperty, - delete: kEnumerableProperty, - get: kEnumerableProperty, - has: kEnumerableProperty, - set: kEnumerableProperty, - getSetCookie: kEnumerableProperty, - keys: kEnumerableProperty, - values: kEnumerableProperty, - entries: kEnumerableProperty, - forEach: kEnumerableProperty, - [Symbol.iterator]: { enumerable: false }, - [Symbol.toStringTag]: { - value: 'Headers', - configurable: true - }, - [util.inspect.custom]: { - enumerable: false + if (cookie.sameSite) { + out.push(`SameSite=${cookie.sameSite}`) } -}) -webidl.converters.HeadersInit = function (V) { - if (webidl.util.Type(V) === 'Object') { - if (V[Symbol.iterator]) { - return webidl.converters['sequence>'](V) + for (const part of cookie.unparsed) { + if (!part.includes('=')) { + throw new Error('Invalid unparsed') } - return webidl.converters['record'](V) + const [key, ...value] = part.split('=') + + out.push(`${key.trim()}=${value.join('=')}`) } - throw webidl.errors.conversionFailed({ - prefix: 'Headers constructor', - argument: 'Argument 1', - types: ['sequence>', 'record'] - }) + return out.join('; ') } module.exports = { - fill, - Headers, - HeadersList + isCTLExcludingHtab, + validateCookieName, + validateCookiePath, + validateCookieValue, + toIMFDate, + stringify } /***/ }), -/***/ 8130: +/***/ 3829: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -// https://github.com/Ethan-Arrowood/undici-fetch +const { Transform } = __nccwpck_require__(7075) +const { isASCIINumber, isValidLastEventId } = __nccwpck_require__(6505) +/** + * @type {number[]} BOM + */ +const BOM = [0xEF, 0xBB, 0xBF] +/** + * @type {10} LF + */ +const LF = 0x0A +/** + * @type {13} CR + */ +const CR = 0x0D +/** + * @type {58} COLON + */ +const COLON = 0x3A +/** + * @type {32} SPACE + */ +const SPACE = 0x20 -const { - Response, - makeNetworkError, - makeAppropriateNetworkError, - filterResponse, - makeResponse -} = __nccwpck_require__(5743) -const { Headers } = __nccwpck_require__(3640) -const { Request, makeRequest } = __nccwpck_require__(4555) -const zlib = __nccwpck_require__(3106) -const { - bytesMatch, - makePolicyContainer, - clonePolicyContainer, - requestBadPort, - TAOCheck, - appendRequestOriginHeader, - responseLocationURL, - requestCurrentURL, - setRequestReferrerPolicyOnRedirect, - tryUpgradeRequestToAPotentiallyTrustworthyURL, - createOpaqueTimingInfo, - appendFetchMetadata, - corsCheck, - crossOriginResourcePolicyCheck, - determineRequestsReferrer, - coarsenedSharedCurrentTime, - createDeferredPromise, - isBlobLike, - sameOrigin, - isCancelled, - isAborted, - isErrorLike, - fullyReadBody, - readableStreamClose, - isomorphicEncode, - urlIsLocal, - urlIsHttpHttpsScheme, - urlHasHttpsScheme -} = __nccwpck_require__(1612) -const { kState, kHeaders, kGuard, kRealm } = __nccwpck_require__(2895) -const assert = __nccwpck_require__(2613) -const { safelyExtractBody } = __nccwpck_require__(1056) -const { - redirectStatusSet, - nullBodyStatus, - safeMethodsSet, - requestBodyHeader, - subresourceSet, - DOMException -} = __nccwpck_require__(3283) -const { kHeadersList } = __nccwpck_require__(1028) -const EE = __nccwpck_require__(4434) -const { Readable, pipeline } = __nccwpck_require__(2203) -const { addAbortListener, isErrored, isReadable, nodeMajor, nodeMinor } = __nccwpck_require__(5069) -const { dataURLProcessor, serializeAMimeType } = __nccwpck_require__(4955) -const { TransformStream } = __nccwpck_require__(3774) -const { getGlobalDispatcher } = __nccwpck_require__(5334) -const { webidl } = __nccwpck_require__(8201) -const { STATUS_CODES } = __nccwpck_require__(8611) -const GET_OR_HEAD = ['GET', 'HEAD'] +/** + * @typedef {object} EventSourceStreamEvent + * @type {object} + * @property {string} [event] The event type. + * @property {string} [data] The data of the message. + * @property {string} [id] A unique ID for the event. + * @property {string} [retry] The reconnection time, in milliseconds. + */ -/** @type {import('buffer').resolveObjectURL} */ -let resolveObjectURL -let ReadableStream = globalThis.ReadableStream +/** + * @typedef eventSourceSettings + * @type {object} + * @property {string} lastEventId The last event ID received from the server. + * @property {string} origin The origin of the event source. + * @property {number} reconnectionTime The reconnection time, in milliseconds. + */ -class Fetch extends EE { - constructor (dispatcher) { - super() +class EventSourceStream extends Transform { + /** + * @type {eventSourceSettings} + */ + state = null - this.dispatcher = dispatcher - this.connection = null - this.dump = false - this.state = 'ongoing' - // 2 terminated listeners get added per request, - // but only 1 gets removed. If there are 20 redirects, - // 21 listeners will be added. - // See https://github.com/nodejs/undici/issues/1711 - // TODO (fix): Find and fix root cause for leaked listener. - this.setMaxListeners(21) - } + /** + * Leading byte-order-mark check. + * @type {boolean} + */ + checkBOM = true - terminate (reason) { - if (this.state !== 'ongoing') { - return - } + /** + * @type {boolean} + */ + crlfCheck = false - this.state = 'terminated' - this.connection?.destroy(reason) - this.emit('terminated', reason) - } + /** + * @type {boolean} + */ + eventEndCheck = false - // https://fetch.spec.whatwg.org/#fetch-controller-abort - abort (error) { - if (this.state !== 'ongoing') { - return - } + /** + * @type {Buffer} + */ + buffer = null - // 1. Set controller’s state to "aborted". - this.state = 'aborted' + pos = 0 - // 2. Let fallbackError be an "AbortError" DOMException. - // 3. Set error to fallbackError if it is not given. - if (!error) { - error = new DOMException('The operation was aborted.', 'AbortError') - } + event = { + data: undefined, + event: undefined, + id: undefined, + retry: undefined + } - // 4. Let serializedError be StructuredSerialize(error). - // If that threw an exception, catch it, and let - // serializedError be StructuredSerialize(fallbackError). + /** + * @param {object} options + * @param {eventSourceSettings} options.eventSourceSettings + * @param {Function} [options.push] + */ + constructor (options = {}) { + // Enable object mode as EventSourceStream emits objects of shape + // EventSourceStreamEvent + options.readableObjectMode = true - // 5. Set controller’s serialized abort reason to serializedError. - this.serializedAbortReason = error + super(options) - this.connection?.destroy(error) - this.emit('terminated', error) + this.state = options.eventSourceSettings || {} + if (options.push) { + this.push = options.push + } } -} -// https://fetch.spec.whatwg.org/#fetch-method -function fetch (input, init = {}) { - webidl.argumentLengthCheck(arguments, 1, { header: 'globalThis.fetch' }) + /** + * @param {Buffer} chunk + * @param {string} _encoding + * @param {Function} callback + * @returns {void} + */ + _transform (chunk, _encoding, callback) { + if (chunk.length === 0) { + callback() + return + } - // 1. Let p be a new promise. - const p = createDeferredPromise() + // Cache the chunk in the buffer, as the data might not be complete while + // processing it + // TODO: Investigate if there is a more performant way to handle + // incoming chunks + // see: https://github.com/nodejs/undici/issues/2630 + if (this.buffer) { + this.buffer = Buffer.concat([this.buffer, chunk]) + } else { + this.buffer = chunk + } - // 2. Let requestObject be the result of invoking the initial value of - // Request as constructor with input and init as arguments. If this throws - // an exception, reject p with it and return p. - let requestObject + // Strip leading byte-order-mark if we opened the stream and started + // the processing of the incoming data + if (this.checkBOM) { + switch (this.buffer.length) { + case 1: + // Check if the first byte is the same as the first byte of the BOM + if (this.buffer[0] === BOM[0]) { + // If it is, we need to wait for more data + callback() + return + } + // Set the checkBOM flag to false as we don't need to check for the + // BOM anymore + this.checkBOM = false - try { - requestObject = new Request(input, init) - } catch (e) { - p.reject(e) - return p.promise - } + // The buffer only contains one byte so we need to wait for more data + callback() + return + case 2: + // Check if the first two bytes are the same as the first two bytes + // of the BOM + if ( + this.buffer[0] === BOM[0] && + this.buffer[1] === BOM[1] + ) { + // If it is, we need to wait for more data, because the third byte + // is needed to determine if it is the BOM or not + callback() + return + } - // 3. Let request be requestObject’s request. - const request = requestObject[kState] + // Set the checkBOM flag to false as we don't need to check for the + // BOM anymore + this.checkBOM = false + break + case 3: + // Check if the first three bytes are the same as the first three + // bytes of the BOM + if ( + this.buffer[0] === BOM[0] && + this.buffer[1] === BOM[1] && + this.buffer[2] === BOM[2] + ) { + // If it is, we can drop the buffered data, as it is only the BOM + this.buffer = Buffer.alloc(0) + // Set the checkBOM flag to false as we don't need to check for the + // BOM anymore + this.checkBOM = false - // 4. If requestObject’s signal’s aborted flag is set, then: - if (requestObject.signal.aborted) { - // 1. Abort the fetch() call with p, request, null, and - // requestObject’s signal’s abort reason. - abortFetch(p, request, null, requestObject.signal.reason) + // Await more data + callback() + return + } + // If it is not the BOM, we can start processing the data + this.checkBOM = false + break + default: + // The buffer is longer than 3 bytes, so we can drop the BOM if it is + // present + if ( + this.buffer[0] === BOM[0] && + this.buffer[1] === BOM[1] && + this.buffer[2] === BOM[2] + ) { + // Remove the BOM from the buffer + this.buffer = this.buffer.subarray(3) + } - // 2. Return p. - return p.promise - } + // Set the checkBOM flag to false as we don't need to check for the + this.checkBOM = false + break + } + } - // 5. Let globalObject be request’s client’s global object. - const globalObject = request.client.globalObject + while (this.pos < this.buffer.length) { + // If the previous line ended with an end-of-line, we need to check + // if the next character is also an end-of-line. + if (this.eventEndCheck) { + // If the the current character is an end-of-line, then the event + // is finished and we can process it - // 6. If globalObject is a ServiceWorkerGlobalScope object, then set - // request’s service-workers mode to "none". - if (globalObject?.constructor?.name === 'ServiceWorkerGlobalScope') { - request.serviceWorkers = 'none' - } + // If the previous line ended with a carriage return, we need to + // check if the current character is a line feed and remove it + // from the buffer. + if (this.crlfCheck) { + // If the current character is a line feed, we can remove it + // from the buffer and reset the crlfCheck flag + if (this.buffer[this.pos] === LF) { + this.buffer = this.buffer.subarray(this.pos + 1) + this.pos = 0 + this.crlfCheck = false - // 7. Let responseObject be null. - let responseObject = null + // It is possible that the line feed is not the end of the + // event. We need to check if the next character is an + // end-of-line character to determine if the event is + // finished. We simply continue the loop to check the next + // character. - // 8. Let relevantRealm be this’s relevant Realm. - const relevantRealm = null + // As we removed the line feed from the buffer and set the + // crlfCheck flag to false, we basically don't make any + // distinction between a line feed and a carriage return. + continue + } + this.crlfCheck = false + } - // 9. Let locallyAborted be false. - let locallyAborted = false + if (this.buffer[this.pos] === LF || this.buffer[this.pos] === CR) { + // If the current character is a carriage return, we need to + // set the crlfCheck flag to true, as we need to check if the + // next character is a line feed so we can remove it from the + // buffer + if (this.buffer[this.pos] === CR) { + this.crlfCheck = true + } - // 10. Let controller be null. - let controller = null + this.buffer = this.buffer.subarray(this.pos + 1) + this.pos = 0 + if ( + this.event.data !== undefined || this.event.event || this.event.id || this.event.retry) { + this.processEvent(this.event) + } + this.clearEvent() + continue + } + // If the current character is not an end-of-line, then the event + // is not finished and we have to reset the eventEndCheck flag + this.eventEndCheck = false + continue + } - // 11. Add the following abort steps to requestObject’s signal: - addAbortListener( - requestObject.signal, - () => { - // 1. Set locallyAborted to true. - locallyAborted = true + // If the current character is an end-of-line, we can process the + // line + if (this.buffer[this.pos] === LF || this.buffer[this.pos] === CR) { + // If the current character is a carriage return, we need to + // set the crlfCheck flag to true, as we need to check if the + // next character is a line feed + if (this.buffer[this.pos] === CR) { + this.crlfCheck = true + } - // 2. Assert: controller is non-null. - assert(controller != null) + // In any case, we can process the line as we reached an + // end-of-line character + this.parseLine(this.buffer.subarray(0, this.pos), this.event) - // 3. Abort controller with requestObject’s signal’s abort reason. - controller.abort(requestObject.signal.reason) + // Remove the processed line from the buffer + this.buffer = this.buffer.subarray(this.pos + 1) + // Reset the position as we removed the processed line from the buffer + this.pos = 0 + // A line was processed and this could be the end of the event. We need + // to check if the next line is empty to determine if the event is + // finished. + this.eventEndCheck = true + continue + } - // 4. Abort the fetch() call with p, request, responseObject, - // and requestObject’s signal’s abort reason. - abortFetch(p, request, responseObject, requestObject.signal.reason) + this.pos++ } - ) - // 12. Let handleFetchDone given response response be to finalize and - // report timing with response, globalObject, and "fetch". - const handleFetchDone = (response) => - finalizeAndReportTiming(response, 'fetch') + callback() + } - // 13. Set controller to the result of calling fetch given request, - // with processResponseEndOfBody set to handleFetchDone, and processResponse - // given response being these substeps: + /** + * @param {Buffer} line + * @param {EventStreamEvent} event + */ + parseLine (line, event) { + // If the line is empty (a blank line) + // Dispatch the event, as defined below. + // This will be handled in the _transform method + if (line.length === 0) { + return + } - const processResponse = (response) => { - // 1. If locallyAborted is true, terminate these substeps. - if (locallyAborted) { - return Promise.resolve() + // If the line starts with a U+003A COLON character (:) + // Ignore the line. + const colonPosition = line.indexOf(COLON) + if (colonPosition === 0) { + return } - // 2. If response’s aborted flag is set, then: - if (response.aborted) { - // 1. Let deserializedError be the result of deserialize a serialized - // abort reason given controller’s serialized abort reason and - // relevantRealm. + let field = '' + let value = '' - // 2. Abort the fetch() call with p, request, responseObject, and - // deserializedError. + // If the line contains a U+003A COLON character (:) + if (colonPosition !== -1) { + // Collect the characters on the line before the first U+003A COLON + // character (:), and let field be that string. + // TODO: Investigate if there is a more performant way to extract the + // field + // see: https://github.com/nodejs/undici/issues/2630 + field = line.subarray(0, colonPosition).toString('utf8') - abortFetch(p, request, responseObject, controller.serializedAbortReason) - return Promise.resolve() + // Collect the characters on the line after the first U+003A COLON + // character (:), and let value be that string. + // If value starts with a U+0020 SPACE character, remove it from value. + let valueStart = colonPosition + 1 + if (line[valueStart] === SPACE) { + ++valueStart + } + // TODO: Investigate if there is a more performant way to extract the + // value + // see: https://github.com/nodejs/undici/issues/2630 + value = line.subarray(valueStart).toString('utf8') + + // Otherwise, the string is not empty but does not contain a U+003A COLON + // character (:) + } else { + // Process the field using the steps described below, using the whole + // line as the field name, and the empty string as the field value. + field = line.toString('utf8') + value = '' } - // 3. If response is a network error, then reject p with a TypeError - // and terminate these substeps. - if (response.type === 'error') { - p.reject( - Object.assign(new TypeError('fetch failed'), { cause: response.error }) - ) - return Promise.resolve() + // Modify the event with the field name and value. The value is also + // decoded as UTF-8 + switch (field) { + case 'data': + if (event[field] === undefined) { + event[field] = value + } else { + event[field] += `\n${value}` + } + break + case 'retry': + if (isASCIINumber(value)) { + event[field] = value + } + break + case 'id': + if (isValidLastEventId(value)) { + event[field] = value + } + break + case 'event': + if (value.length > 0) { + event[field] = value + } + break } + } - // 4. Set responseObject to the result of creating a Response object, - // given response, "immutable", and relevantRealm. - responseObject = new Response() - responseObject[kState] = response - responseObject[kRealm] = relevantRealm - responseObject[kHeaders][kHeadersList] = response.headersList - responseObject[kHeaders][kGuard] = 'immutable' - responseObject[kHeaders][kRealm] = relevantRealm + /** + * @param {EventSourceStreamEvent} event + */ + processEvent (event) { + if (event.retry && isASCIINumber(event.retry)) { + this.state.reconnectionTime = parseInt(event.retry, 10) + } - // 5. Resolve p with responseObject. - p.resolve(responseObject) + if (event.id && isValidLastEventId(event.id)) { + this.state.lastEventId = event.id + } + + // only dispatch event, when data is provided + if (event.data !== undefined) { + this.push({ + type: event.event || 'message', + options: { + data: event.data, + lastEventId: this.state.lastEventId, + origin: this.state.origin + } + }) + } } - controller = fetching({ - request, - processResponseEndOfBody: handleFetchDone, - processResponse, - dispatcher: init.dispatcher ?? getGlobalDispatcher() // undici - }) + clearEvent () { + this.event = { + data: undefined, + event: undefined, + id: undefined, + retry: undefined + } + } +} - // 14. Return p. - return p.promise +module.exports = { + EventSourceStream } -// https://fetch.spec.whatwg.org/#finalize-and-report-timing -function finalizeAndReportTiming (response, initiatorType = 'other') { - // 1. If response is an aborted network error, then return. - if (response.type === 'error' && response.aborted) { - return - } - // 2. If response’s URL list is null or empty, then return. - if (!response.urlList?.length) { - return - } +/***/ }), - // 3. Let originalURL be response’s URL list[0]. - const originalURL = response.urlList[0] +/***/ 7888: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - // 4. Let timingInfo be response’s timing info. - let timingInfo = response.timingInfo - // 5. Let cacheState be response’s cache state. - let cacheState = response.cacheState - // 6. If originalURL’s scheme is not an HTTP(S) scheme, then return. - if (!urlIsHttpHttpsScheme(originalURL)) { - return - } +const { pipeline } = __nccwpck_require__(7075) +const { fetching } = __nccwpck_require__(5780) +const { makeRequest } = __nccwpck_require__(5417) +const { webidl } = __nccwpck_require__(4859) +const { EventSourceStream } = __nccwpck_require__(3829) +const { parseMIMEType } = __nccwpck_require__(6406) +const { createFastMessageEvent } = __nccwpck_require__(8086) +const { isNetworkError } = __nccwpck_require__(4317) +const { delay } = __nccwpck_require__(6505) +const { kEnumerableProperty } = __nccwpck_require__(7234) +const { environmentSettingsObject } = __nccwpck_require__(1046) - // 7. If timingInfo is null, then return. - if (timingInfo === null) { - return - } +let experimentalWarned = false - // 8. If response’s timing allow passed flag is not set, then: - if (!response.timingAllowPassed) { - // 1. Set timingInfo to a the result of creating an opaque timing info for timingInfo. - timingInfo = createOpaqueTimingInfo({ - startTime: timingInfo.startTime - }) +/** + * A reconnection time, in milliseconds. This must initially be an implementation-defined value, + * probably in the region of a few seconds. + * + * In Comparison: + * - Chrome uses 3000ms. + * - Deno uses 5000ms. + * + * @type {3000} + */ +const defaultReconnectionTime = 3000 - // 2. Set cacheState to the empty string. - cacheState = '' - } +/** + * The readyState attribute represents the state of the connection. + * @enum + * @readonly + * @see https://html.spec.whatwg.org/multipage/server-sent-events.html#dom-eventsource-readystate-dev + */ - // 9. Set timingInfo’s end time to the coarsened shared current time - // given global’s relevant settings object’s cross-origin isolated - // capability. - // TODO: given global’s relevant settings object’s cross-origin isolated - // capability? - timingInfo.endTime = coarsenedSharedCurrentTime() +/** + * The connection has not yet been established, or it was closed and the user + * agent is reconnecting. + * @type {0} + */ +const CONNECTING = 0 - // 10. Set response’s timing info to timingInfo. - response.timingInfo = timingInfo +/** + * The user agent has an open connection and is dispatching events as it + * receives them. + * @type {1} + */ +const OPEN = 1 - // 11. Mark resource timing for timingInfo, originalURL, initiatorType, - // global, and cacheState. - markResourceTiming( - timingInfo, - originalURL, - initiatorType, - globalThis, - cacheState - ) -} +/** + * The connection is not open, and the user agent is not trying to reconnect. + * @type {2} + */ +const CLOSED = 2 -// https://w3c.github.io/resource-timing/#dfn-mark-resource-timing -function markResourceTiming (timingInfo, originalURL, initiatorType, globalThis, cacheState) { - if (nodeMajor > 18 || (nodeMajor === 18 && nodeMinor >= 2)) { - performance.markResourceTiming(timingInfo, originalURL.href, initiatorType, globalThis, cacheState) - } -} +/** + * Requests for the element will have their mode set to "cors" and their credentials mode set to "same-origin". + * @type {'anonymous'} + */ +const ANONYMOUS = 'anonymous' -// https://fetch.spec.whatwg.org/#abort-fetch -function abortFetch (p, request, responseObject, error) { - // Note: AbortSignal.reason was added in node v17.2.0 - // which would give us an undefined error to reject with. - // Remove this once node v16 is no longer supported. - if (!error) { - error = new DOMException('The operation was aborted.', 'AbortError') +/** + * Requests for the element will have their mode set to "cors" and their credentials mode set to "include". + * @type {'use-credentials'} + */ +const USE_CREDENTIALS = 'use-credentials' + +/** + * The EventSource interface is used to receive server-sent events. It + * connects to a server over HTTP and receives events in text/event-stream + * format without closing the connection. + * @extends {EventTarget} + * @see https://html.spec.whatwg.org/multipage/server-sent-events.html#server-sent-events + * @api public + */ +class EventSource extends EventTarget { + #events = { + open: null, + error: null, + message: null } - // 1. Reject promise with error. - p.reject(error) + #url = null + #withCredentials = false - // 2. If request’s body is not null and is readable, then cancel request’s - // body with error. - if (request.body != null && isReadable(request.body?.stream)) { - request.body.stream.cancel(error).catch((err) => { - if (err.code === 'ERR_INVALID_STATE') { - // Node bug? - return - } - throw err - }) - } + #readyState = CONNECTING - // 3. If responseObject is null, then return. - if (responseObject == null) { - return - } + #request = null + #controller = null - // 4. Let response be responseObject’s response. - const response = responseObject[kState] + #dispatcher - // 5. If response’s body is not null and is readable, then error response’s - // body with error. - if (response.body != null && isReadable(response.body?.stream)) { - response.body.stream.cancel(error).catch((err) => { - if (err.code === 'ERR_INVALID_STATE') { - // Node bug? - return - } - throw err - }) - } -} + /** + * @type {import('./eventsource-stream').eventSourceSettings} + */ + #state -// https://fetch.spec.whatwg.org/#fetching -function fetching ({ - request, - processRequestBodyChunkLength, - processRequestEndOfBody, - processResponse, - processResponseEndOfBody, - processResponseConsumeBody, - useParallelQueue = false, - dispatcher // undici -}) { - // 1. Let taskDestination be null. - let taskDestination = null + /** + * Creates a new EventSource object. + * @param {string} url + * @param {EventSourceInit} [eventSourceInitDict] + * @see https://html.spec.whatwg.org/multipage/server-sent-events.html#the-eventsource-interface + */ + constructor (url, eventSourceInitDict = {}) { + // 1. Let ev be a new EventSource object. + super() - // 2. Let crossOriginIsolatedCapability be false. - let crossOriginIsolatedCapability = false + webidl.util.markAsUncloneable(this) - // 3. If request’s client is non-null, then: - if (request.client != null) { - // 1. Set taskDestination to request’s client’s global object. - taskDestination = request.client.globalObject + const prefix = 'EventSource constructor' + webidl.argumentLengthCheck(arguments, 1, prefix) - // 2. Set crossOriginIsolatedCapability to request’s client’s cross-origin - // isolated capability. - crossOriginIsolatedCapability = - request.client.crossOriginIsolatedCapability - } + if (!experimentalWarned) { + experimentalWarned = true + process.emitWarning('EventSource is experimental, expect them to change at any time.', { + code: 'UNDICI-ES' + }) + } - // 4. If useParallelQueue is true, then set taskDestination to the result of - // starting a new parallel queue. - // TODO + url = webidl.converters.USVString(url, prefix, 'url') + eventSourceInitDict = webidl.converters.EventSourceInitDict(eventSourceInitDict, prefix, 'eventSourceInitDict') - // 5. Let timingInfo be a new fetch timing info whose start time and - // post-redirect start time are the coarsened shared current time given - // crossOriginIsolatedCapability. - const currenTime = coarsenedSharedCurrentTime(crossOriginIsolatedCapability) - const timingInfo = createOpaqueTimingInfo({ - startTime: currenTime - }) + this.#dispatcher = eventSourceInitDict.dispatcher + this.#state = { + lastEventId: '', + reconnectionTime: defaultReconnectionTime + } - // 6. Let fetchParams be a new fetch params whose - // request is request, - // timing info is timingInfo, - // process request body chunk length is processRequestBodyChunkLength, - // process request end-of-body is processRequestEndOfBody, - // process response is processResponse, - // process response consume body is processResponseConsumeBody, - // process response end-of-body is processResponseEndOfBody, - // task destination is taskDestination, - // and cross-origin isolated capability is crossOriginIsolatedCapability. - const fetchParams = { - controller: new Fetch(dispatcher), - request, - timingInfo, - processRequestBodyChunkLength, - processRequestEndOfBody, - processResponse, - processResponseConsumeBody, - processResponseEndOfBody, - taskDestination, - crossOriginIsolatedCapability - } + // 2. Let settings be ev's relevant settings object. + // https://html.spec.whatwg.org/multipage/webappapis.html#environment-settings-object + const settings = environmentSettingsObject - // 7. If request’s body is a byte sequence, then set request’s body to - // request’s body as a body. - // NOTE: Since fetching is only called from fetch, body should already be - // extracted. - assert(!request.body || request.body.stream) + let urlRecord - // 8. If request’s window is "client", then set request’s window to request’s - // client, if request’s client’s global object is a Window object; otherwise - // "no-window". - if (request.window === 'client') { - // TODO: What if request.client is null? - request.window = - request.client?.globalObject?.constructor?.name === 'Window' - ? request.client - : 'no-window' - } + try { + // 3. Let urlRecord be the result of encoding-parsing a URL given url, relative to settings. + urlRecord = new URL(url, settings.settingsObject.baseUrl) + this.#state.origin = urlRecord.origin + } catch (e) { + // 4. If urlRecord is failure, then throw a "SyntaxError" DOMException. + throw new DOMException(e, 'SyntaxError') + } - // 9. If request’s origin is "client", then set request’s origin to request’s - // client’s origin. - if (request.origin === 'client') { - // TODO: What if request.client is null? - request.origin = request.client?.origin - } + // 5. Set ev's url to urlRecord. + this.#url = urlRecord.href - // 10. If all of the following conditions are true: - // TODO + // 6. Let corsAttributeState be Anonymous. + let corsAttributeState = ANONYMOUS - // 11. If request’s policy container is "client", then: - if (request.policyContainer === 'client') { - // 1. If request’s client is non-null, then set request’s policy - // container to a clone of request’s client’s policy container. [HTML] - if (request.client != null) { - request.policyContainer = clonePolicyContainer( - request.client.policyContainer - ) - } else { - // 2. Otherwise, set request’s policy container to a new policy - // container. - request.policyContainer = makePolicyContainer() + // 7. If the value of eventSourceInitDict's withCredentials member is true, + // then set corsAttributeState to Use Credentials and set ev's + // withCredentials attribute to true. + if (eventSourceInitDict.withCredentials) { + corsAttributeState = USE_CREDENTIALS + this.#withCredentials = true } - } - // 12. If request’s header list does not contain `Accept`, then: - if (!request.headersList.contains('accept')) { - // 1. Let value be `*/*`. - const value = '*/*' + // 8. Let request be the result of creating a potential-CORS request given + // urlRecord, the empty string, and corsAttributeState. + const initRequest = { + redirect: 'follow', + keepalive: true, + // @see https://html.spec.whatwg.org/multipage/urls-and-fetching.html#cors-settings-attributes + mode: 'cors', + credentials: corsAttributeState === 'anonymous' + ? 'same-origin' + : 'omit', + referrer: 'no-referrer' + } - // 2. A user agent should set value to the first matching statement, if - // any, switching on request’s destination: - // "document" - // "frame" - // "iframe" - // `text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8` - // "image" - // `image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5` - // "style" - // `text/css,*/*;q=0.1` - // TODO + // 9. Set request's client to settings. + initRequest.client = environmentSettingsObject.settingsObject - // 3. Append `Accept`/value to request’s header list. - request.headersList.append('accept', value) - } + // 10. User agents may set (`Accept`, `text/event-stream`) in request's header list. + initRequest.headersList = [['accept', { name: 'accept', value: 'text/event-stream' }]] - // 13. If request’s header list does not contain `Accept-Language`, then - // user agents should append `Accept-Language`/an appropriate value to - // request’s header list. - if (!request.headersList.contains('accept-language')) { - request.headersList.append('accept-language', '*') - } + // 11. Set request's cache mode to "no-store". + initRequest.cache = 'no-store' - // 14. If request’s priority is null, then use request’s initiator and - // destination appropriately in setting request’s priority to a - // user-agent-defined object. - if (request.priority === null) { - // TODO - } + // 12. Set request's initiator type to "other". + initRequest.initiator = 'other' - // 15. If request is a subresource request, then: - if (subresourceSet.has(request.destination)) { - // TODO - } + initRequest.urlList = [new URL(this.#url)] - // 16. Run main fetch given fetchParams. - mainFetch(fetchParams) - .catch(err => { - fetchParams.controller.terminate(err) - }) + // 13. Set ev's request to request. + this.#request = makeRequest(initRequest) - // 17. Return fetchParam's controller - return fetchParams.controller -} + this.#connect() + } -// https://fetch.spec.whatwg.org/#concept-main-fetch -async function mainFetch (fetchParams, recursive = false) { - // 1. Let request be fetchParams’s request. - const request = fetchParams.request + /** + * Returns the state of this EventSource object's connection. It can have the + * values described below. + * @returns {0|1|2} + * @readonly + */ + get readyState () { + return this.#readyState + } - // 2. Let response be null. - let response = null + /** + * Returns the URL providing the event stream. + * @readonly + * @returns {string} + */ + get url () { + return this.#url + } - // 3. If request’s local-URLs-only flag is set and request’s current URL is - // not local, then set response to a network error. - if (request.localURLsOnly && !urlIsLocal(requestCurrentURL(request))) { - response = makeNetworkError('local URLs only') + /** + * Returns a boolean indicating whether the EventSource object was + * instantiated with CORS credentials set (true), or not (false, the default). + */ + get withCredentials () { + return this.#withCredentials } - // 4. Run report Content Security Policy violations for request. - // TODO + #connect () { + if (this.#readyState === CLOSED) return - // 5. Upgrade request to a potentially trustworthy URL, if appropriate. - tryUpgradeRequestToAPotentiallyTrustworthyURL(request) + this.#readyState = CONNECTING - // 6. If should request be blocked due to a bad port, should fetching request - // be blocked as mixed content, or should request be blocked by Content - // Security Policy returns blocked, then set response to a network error. - if (requestBadPort(request) === 'blocked') { - response = makeNetworkError('bad port') - } - // TODO: should fetching request be blocked as mixed content? - // TODO: should request be blocked by Content Security Policy? + const fetchParams = { + request: this.#request, + dispatcher: this.#dispatcher + } - // 7. If request’s referrer policy is the empty string, then set request’s - // referrer policy to request’s policy container’s referrer policy. - if (request.referrerPolicy === '') { - request.referrerPolicy = request.policyContainer.referrerPolicy - } + // 14. Let processEventSourceEndOfBody given response res be the following step: if res is not a network error, then reestablish the connection. + const processEventSourceEndOfBody = (response) => { + if (isNetworkError(response)) { + this.dispatchEvent(new Event('error')) + this.close() + } - // 8. If request’s referrer is not "no-referrer", then set request’s - // referrer to the result of invoking determine request’s referrer. - if (request.referrer !== 'no-referrer') { - request.referrer = determineRequestsReferrer(request) - } + this.#reconnect() + } - // 9. Set request’s current URL’s scheme to "https" if all of the following - // conditions are true: - // - request’s current URL’s scheme is "http" - // - request’s current URL’s host is a domain - // - Matching request’s current URL’s host per Known HSTS Host Domain Name - // Matching results in either a superdomain match with an asserted - // includeSubDomains directive or a congruent match (with or without an - // asserted includeSubDomains directive). [HSTS] - // TODO + // 15. Fetch request, with processResponseEndOfBody set to processEventSourceEndOfBody... + fetchParams.processResponseEndOfBody = processEventSourceEndOfBody - // 10. If recursive is false, then run the remaining steps in parallel. - // TODO + // and processResponse set to the following steps given response res: + fetchParams.processResponse = (response) => { + // 1. If res is an aborted network error, then fail the connection. - // 11. If response is null, then set response to the result of running - // the steps corresponding to the first matching statement: - if (response === null) { - response = await (async () => { - const currentURL = requestCurrentURL(request) + if (isNetworkError(response)) { + // 1. When a user agent is to fail the connection, the user agent + // must queue a task which, if the readyState attribute is set to a + // value other than CLOSED, sets the readyState attribute to CLOSED + // and fires an event named error at the EventSource object. Once the + // user agent has failed the connection, it does not attempt to + // reconnect. + if (response.aborted) { + this.close() + this.dispatchEvent(new Event('error')) + return + // 2. Otherwise, if res is a network error, then reestablish the + // connection, unless the user agent knows that to be futile, in + // which case the user agent may fail the connection. + } else { + this.#reconnect() + return + } + } + // 3. Otherwise, if res's status is not 200, or if res's `Content-Type` + // is not `text/event-stream`, then fail the connection. + const contentType = response.headersList.get('content-type', true) + const mimeType = contentType !== null ? parseMIMEType(contentType) : 'failure' + const contentTypeValid = mimeType !== 'failure' && mimeType.essence === 'text/event-stream' if ( - // - request’s current URL’s origin is same origin with request’s origin, - // and request’s response tainting is "basic" - (sameOrigin(currentURL, request.url) && request.responseTainting === 'basic') || - // request’s current URL’s scheme is "data" - (currentURL.protocol === 'data:') || - // - request’s mode is "navigate" or "websocket" - (request.mode === 'navigate' || request.mode === 'websocket') + response.status !== 200 || + contentTypeValid === false ) { - // 1. Set request’s response tainting to "basic". - request.responseTainting = 'basic' - - // 2. Return the result of running scheme fetch given fetchParams. - return await schemeFetch(fetchParams) + this.close() + this.dispatchEvent(new Event('error')) + return } - // request’s mode is "same-origin" - if (request.mode === 'same-origin') { - // 1. Return a network error. - return makeNetworkError('request mode cannot be "same-origin"') - } + // 4. Otherwise, announce the connection and interpret res's body + // line by line. - // request’s mode is "no-cors" - if (request.mode === 'no-cors') { - // 1. If request’s redirect mode is not "follow", then return a network - // error. - if (request.redirect !== 'follow') { - return makeNetworkError( - 'redirect mode cannot be "follow" for "no-cors" request' - ) + // When a user agent is to announce the connection, the user agent + // must queue a task which, if the readyState attribute is set to a + // value other than CLOSED, sets the readyState attribute to OPEN + // and fires an event named open at the EventSource object. + // @see https://html.spec.whatwg.org/multipage/server-sent-events.html#sse-processing-model + this.#readyState = OPEN + this.dispatchEvent(new Event('open')) + + // If redirected to a different origin, set the origin to the new origin. + this.#state.origin = response.urlList[response.urlList.length - 1].origin + + const eventSourceStream = new EventSourceStream({ + eventSourceSettings: this.#state, + push: (event) => { + this.dispatchEvent(createFastMessageEvent( + event.type, + event.options + )) } + }) - // 2. Set request’s response tainting to "opaque". - request.responseTainting = 'opaque' + pipeline(response.body.stream, + eventSourceStream, + (error) => { + if ( + error?.aborted === false + ) { + this.close() + this.dispatchEvent(new Event('error')) + } + }) + } - // 3. Return the result of running scheme fetch given fetchParams. - return await schemeFetch(fetchParams) - } + this.#controller = fetching(fetchParams) + } - // request’s current URL’s scheme is not an HTTP(S) scheme - if (!urlIsHttpHttpsScheme(requestCurrentURL(request))) { - // Return a network error. - return makeNetworkError('URL scheme must be a HTTP(S) scheme') - } + /** + * @see https://html.spec.whatwg.org/multipage/server-sent-events.html#sse-processing-model + * @returns {Promise} + */ + async #reconnect () { + // When a user agent is to reestablish the connection, the user agent must + // run the following steps. These steps are run in parallel, not as part of + // a task. (The tasks that it queues, of course, are run like normal tasks + // and not themselves in parallel.) - // - request’s use-CORS-preflight flag is set - // - request’s unsafe-request flag is set and either request’s method is - // not a CORS-safelisted method or CORS-unsafe request-header names with - // request’s header list is not empty - // 1. Set request’s response tainting to "cors". - // 2. Let corsWithPreflightResponse be the result of running HTTP fetch - // given fetchParams and true. - // 3. If corsWithPreflightResponse is a network error, then clear cache - // entries using request. - // 4. Return corsWithPreflightResponse. - // TODO + // 1. Queue a task to run the following steps: - // Otherwise - // 1. Set request’s response tainting to "cors". - request.responseTainting = 'cors' + // 1. If the readyState attribute is set to CLOSED, abort the task. + if (this.#readyState === CLOSED) return - // 2. Return the result of running HTTP fetch given fetchParams. - return await httpFetch(fetchParams) - })() - } + // 2. Set the readyState attribute to CONNECTING. + this.#readyState = CONNECTING - // 12. If recursive is true, then return response. - if (recursive) { - return response - } + // 3. Fire an event named error at the EventSource object. + this.dispatchEvent(new Event('error')) - // 13. If response is not a network error and response is not a filtered - // response, then: - if (response.status !== 0 && !response.internalResponse) { - // If request’s response tainting is "cors", then: - if (request.responseTainting === 'cors') { - // 1. Let headerNames be the result of extracting header list values - // given `Access-Control-Expose-Headers` and response’s header list. - // TODO - // 2. If request’s credentials mode is not "include" and headerNames - // contains `*`, then set response’s CORS-exposed header-name list to - // all unique header names in response’s header list. - // TODO - // 3. Otherwise, if headerNames is not null or failure, then set - // response’s CORS-exposed header-name list to headerNames. - // TODO - } + // 2. Wait a delay equal to the reconnection time of the event source. + await delay(this.#state.reconnectionTime) - // Set response to the following filtered response with response as its - // internal response, depending on request’s response tainting: - if (request.responseTainting === 'basic') { - response = filterResponse(response, 'basic') - } else if (request.responseTainting === 'cors') { - response = filterResponse(response, 'cors') - } else if (request.responseTainting === 'opaque') { - response = filterResponse(response, 'opaque') - } else { - assert(false) + // 5. Queue a task to run the following steps: + + // 1. If the EventSource object's readyState attribute is not set to + // CONNECTING, then return. + if (this.#readyState !== CONNECTING) return + + // 2. Let request be the EventSource object's request. + // 3. If the EventSource object's last event ID string is not the empty + // string, then: + // 1. Let lastEventIDValue be the EventSource object's last event ID + // string, encoded as UTF-8. + // 2. Set (`Last-Event-ID`, lastEventIDValue) in request's header + // list. + if (this.#state.lastEventId.length) { + this.#request.headersList.set('last-event-id', this.#state.lastEventId, true) } + + // 4. Fetch request and process the response obtained in this fashion, if any, as described earlier in this section. + this.#connect() } - // 14. Let internalResponse be response, if response is a network error, - // and response’s internal response otherwise. - let internalResponse = - response.status === 0 ? response : response.internalResponse + /** + * Closes the connection, if any, and sets the readyState attribute to + * CLOSED. + */ + close () { + webidl.brandCheck(this, EventSource) - // 15. If internalResponse’s URL list is empty, then set it to a clone of - // request’s URL list. - if (internalResponse.urlList.length === 0) { - internalResponse.urlList.push(...request.urlList) + if (this.#readyState === CLOSED) return + this.#readyState = CLOSED + this.#controller.abort() + this.#request = null } - // 16. If request’s timing allow failed flag is unset, then set - // internalResponse’s timing allow passed flag. - if (!request.timingAllowFailed) { - response.timingAllowPassed = true + get onopen () { + return this.#events.open } - // 17. If response is not a network error and any of the following returns - // blocked - // - should internalResponse to request be blocked as mixed content - // - should internalResponse to request be blocked by Content Security Policy - // - should internalResponse to request be blocked due to its MIME type - // - should internalResponse to request be blocked due to nosniff - // TODO + set onopen (fn) { + if (this.#events.open) { + this.removeEventListener('open', this.#events.open) + } - // 18. If response’s type is "opaque", internalResponse’s status is 206, - // internalResponse’s range-requested flag is set, and request’s header - // list does not contain `Range`, then set response and internalResponse - // to a network error. - if ( - response.type === 'opaque' && - internalResponse.status === 206 && - internalResponse.rangeRequested && - !request.headers.contains('range') - ) { - response = internalResponse = makeNetworkError() + if (typeof fn === 'function') { + this.#events.open = fn + this.addEventListener('open', fn) + } else { + this.#events.open = null + } } - // 19. If response is not a network error and either request’s method is - // `HEAD` or `CONNECT`, or internalResponse’s status is a null body status, - // set internalResponse’s body to null and disregard any enqueuing toward - // it (if any). - if ( - response.status !== 0 && - (request.method === 'HEAD' || - request.method === 'CONNECT' || - nullBodyStatus.includes(internalResponse.status)) - ) { - internalResponse.body = null - fetchParams.controller.dump = true + get onmessage () { + return this.#events.message } - // 20. If request’s integrity metadata is not the empty string, then: - if (request.integrity) { - // 1. Let processBodyError be this step: run fetch finale given fetchParams - // and a network error. - const processBodyError = (reason) => - fetchFinale(fetchParams, makeNetworkError(reason)) - - // 2. If request’s response tainting is "opaque", or response’s body is null, - // then run processBodyError and abort these steps. - if (request.responseTainting === 'opaque' || response.body == null) { - processBodyError(response.error) - return + set onmessage (fn) { + if (this.#events.message) { + this.removeEventListener('message', this.#events.message) } - // 3. Let processBody given bytes be these steps: - const processBody = (bytes) => { - // 1. If bytes do not match request’s integrity metadata, - // then run processBodyError and abort these steps. [SRI] - if (!bytesMatch(bytes, request.integrity)) { - processBodyError('integrity mismatch') - return - } + if (typeof fn === 'function') { + this.#events.message = fn + this.addEventListener('message', fn) + } else { + this.#events.message = null + } + } - // 2. Set response’s body to bytes as a body. - response.body = safelyExtractBody(bytes)[0] + get onerror () { + return this.#events.error + } - // 3. Run fetch finale given fetchParams and response. - fetchFinale(fetchParams, response) + set onerror (fn) { + if (this.#events.error) { + this.removeEventListener('error', this.#events.error) } - // 4. Fully read response’s body given processBody and processBodyError. - await fullyReadBody(response.body, processBody, processBodyError) - } else { - // 21. Otherwise, run fetch finale given fetchParams and response. - fetchFinale(fetchParams, response) + if (typeof fn === 'function') { + this.#events.error = fn + this.addEventListener('error', fn) + } else { + this.#events.error = null + } } } -// https://fetch.spec.whatwg.org/#concept-scheme-fetch -// given a fetch params fetchParams -function schemeFetch (fetchParams) { - // Note: since the connection is destroyed on redirect, which sets fetchParams to a - // cancelled state, we do not want this condition to trigger *unless* there have been - // no redirects. See https://github.com/nodejs/undici/issues/1776 - // 1. If fetchParams is canceled, then return the appropriate network error for fetchParams. - if (isCancelled(fetchParams) && fetchParams.request.redirectCount === 0) { - return Promise.resolve(makeAppropriateNetworkError(fetchParams)) +const constantsPropertyDescriptors = { + CONNECTING: { + __proto__: null, + configurable: false, + enumerable: true, + value: CONNECTING, + writable: false + }, + OPEN: { + __proto__: null, + configurable: false, + enumerable: true, + value: OPEN, + writable: false + }, + CLOSED: { + __proto__: null, + configurable: false, + enumerable: true, + value: CLOSED, + writable: false } +} - // 2. Let request be fetchParams’s request. - const { request } = fetchParams - - const { protocol: scheme } = requestCurrentURL(request) +Object.defineProperties(EventSource, constantsPropertyDescriptors) +Object.defineProperties(EventSource.prototype, constantsPropertyDescriptors) - // 3. Switch on request’s current URL’s scheme and run the associated steps: - switch (scheme) { - case 'about:': { - // If request’s current URL’s path is the string "blank", then return a new response - // whose status message is `OK`, header list is « (`Content-Type`, `text/html;charset=utf-8`) », - // and body is the empty byte sequence as a body. +Object.defineProperties(EventSource.prototype, { + close: kEnumerableProperty, + onerror: kEnumerableProperty, + onmessage: kEnumerableProperty, + onopen: kEnumerableProperty, + readyState: kEnumerableProperty, + url: kEnumerableProperty, + withCredentials: kEnumerableProperty +}) - // Otherwise, return a network error. - return Promise.resolve(makeNetworkError('about scheme is not supported')) - } - case 'blob:': { - if (!resolveObjectURL) { - resolveObjectURL = (__nccwpck_require__(181).resolveObjectURL) - } +webidl.converters.EventSourceInitDict = webidl.dictionaryConverter([ + { + key: 'withCredentials', + converter: webidl.converters.boolean, + defaultValue: () => false + }, + { + key: 'dispatcher', // undici only + converter: webidl.converters.any + } +]) - // 1. Let blobURLEntry be request’s current URL’s blob URL entry. - const blobURLEntry = requestCurrentURL(request) +module.exports = { + EventSource, + defaultReconnectionTime +} - // https://github.com/web-platform-tests/wpt/blob/7b0ebaccc62b566a1965396e5be7bb2bc06f841f/FileAPI/url/resources/fetch-tests.js#L52-L56 - // Buffer.resolveObjectURL does not ignore URL queries. - if (blobURLEntry.search.length !== 0) { - return Promise.resolve(makeNetworkError('NetworkError when attempting to fetch resource.')) - } - const blobURLEntryObject = resolveObjectURL(blobURLEntry.toString()) +/***/ }), - // 2. If request’s method is not `GET`, blobURLEntry is null, or blobURLEntry’s - // object is not a Blob object, then return a network error. - if (request.method !== 'GET' || !isBlobLike(blobURLEntryObject)) { - return Promise.resolve(makeNetworkError('invalid method')) - } +/***/ 6505: +/***/ ((module) => { - // 3. Let bodyWithType be the result of safely extracting blobURLEntry’s object. - const bodyWithType = safelyExtractBody(blobURLEntryObject) - // 4. Let body be bodyWithType’s body. - const body = bodyWithType[0] - // 5. Let length be body’s length, serialized and isomorphic encoded. - const length = isomorphicEncode(`${body.length}`) +/** + * Checks if the given value is a valid LastEventId. + * @param {string} value + * @returns {boolean} + */ +function isValidLastEventId (value) { + // LastEventId should not contain U+0000 NULL + return value.indexOf('\u0000') === -1 +} - // 6. Let type be bodyWithType’s type if it is non-null; otherwise the empty byte sequence. - const type = bodyWithType[1] ?? '' +/** + * Checks if the given value is a base 10 digit. + * @param {string} value + * @returns {boolean} + */ +function isASCIINumber (value) { + if (value.length === 0) return false + for (let i = 0; i < value.length; i++) { + if (value.charCodeAt(i) < 0x30 || value.charCodeAt(i) > 0x39) return false + } + return true +} - // 7. Return a new response whose status message is `OK`, header list is - // « (`Content-Length`, length), (`Content-Type`, type) », and body is body. - const response = makeResponse({ - statusText: 'OK', - headersList: [ - ['content-length', { name: 'Content-Length', value: length }], - ['content-type', { name: 'Content-Type', value: type }] - ] - }) +// https://github.com/nodejs/undici/issues/2664 +function delay (ms) { + return new Promise((resolve) => { + setTimeout(resolve, ms).unref() + }) +} - response.body = body +module.exports = { + isValidLastEventId, + isASCIINumber, + delay +} - return Promise.resolve(response) - } - case 'data:': { - // 1. Let dataURLStruct be the result of running the - // data: URL processor on request’s current URL. - const currentURL = requestCurrentURL(request) - const dataURLStruct = dataURLProcessor(currentURL) - // 2. If dataURLStruct is failure, then return a - // network error. - if (dataURLStruct === 'failure') { - return Promise.resolve(makeNetworkError('failed to fetch the data URL')) - } +/***/ }), - // 3. Let mimeType be dataURLStruct’s MIME type, serialized. - const mimeType = serializeAMimeType(dataURLStruct.mimeType) +/***/ 8106: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - // 4. Return a response whose status message is `OK`, - // header list is « (`Content-Type`, mimeType) », - // and body is dataURLStruct’s body as a body. - return Promise.resolve(makeResponse({ - statusText: 'OK', - headersList: [ - ['content-type', { name: 'Content-Type', value: mimeType }] - ], - body: safelyExtractBody(dataURLStruct.body)[0] - })) - } - case 'file:': { - // For now, unfortunate as it is, file URLs are left as an exercise for the reader. - // When in doubt, return a network error. - return Promise.resolve(makeNetworkError('not implemented... yet...')) - } - case 'http:': - case 'https:': { - // Return the result of running HTTP fetch given fetchParams. - return httpFetch(fetchParams) - .catch((err) => makeNetworkError(err)) - } - default: { - return Promise.resolve(makeNetworkError('unknown scheme')) - } - } -} -// https://fetch.spec.whatwg.org/#finalize-response -function finalizeResponse (fetchParams, response) { - // 1. Set fetchParams’s request’s done flag. - fetchParams.request.done = true +const util = __nccwpck_require__(7234) +const { + ReadableStreamFrom, + isBlobLike, + isReadableStreamLike, + readableStreamClose, + createDeferredPromise, + fullyReadBody, + extractMimeType, + utf8DecodeBytes +} = __nccwpck_require__(1046) +const { FormData } = __nccwpck_require__(9411) +const { kState } = __nccwpck_require__(1445) +const { webidl } = __nccwpck_require__(4859) +const { Blob } = __nccwpck_require__(4573) +const assert = __nccwpck_require__(4589) +const { isErrored, isDisturbed } = __nccwpck_require__(7075) +const { isArrayBuffer } = __nccwpck_require__(3429) +const { serializeAMimeType } = __nccwpck_require__(6406) +const { multipartFormDataParser } = __nccwpck_require__(8622) +let random - // 2, If fetchParams’s process response done is not null, then queue a fetch - // task to run fetchParams’s process response done given response, with - // fetchParams’s task destination. - if (fetchParams.processResponseDone != null) { - queueMicrotask(() => fetchParams.processResponseDone(response)) - } +try { + const crypto = __nccwpck_require__(7598) + random = (max) => crypto.randomInt(0, max) +} catch { + random = (max) => Math.floor(Math.random(max)) } -// https://fetch.spec.whatwg.org/#fetch-finale -function fetchFinale (fetchParams, response) { - // 1. If response is a network error, then: - if (response.type === 'error') { - // 1. Set response’s URL list to « fetchParams’s request’s URL list[0] ». - response.urlList = [fetchParams.request.urlList[0]] - - // 2. Set response’s timing info to the result of creating an opaque timing - // info for fetchParams’s timing info. - response.timingInfo = createOpaqueTimingInfo({ - startTime: fetchParams.timingInfo.startTime - }) - } +const textEncoder = new TextEncoder() +function noop () {} - // 2. Let processResponseEndOfBody be the following steps: - const processResponseEndOfBody = () => { - // 1. Set fetchParams’s request’s done flag. - fetchParams.request.done = true +const hasFinalizationRegistry = globalThis.FinalizationRegistry && process.version.indexOf('v18') !== 0 +let streamRegistry - // If fetchParams’s process response end-of-body is not null, - // then queue a fetch task to run fetchParams’s process response - // end-of-body given response with fetchParams’s task destination. - if (fetchParams.processResponseEndOfBody != null) { - queueMicrotask(() => fetchParams.processResponseEndOfBody(response)) +if (hasFinalizationRegistry) { + streamRegistry = new FinalizationRegistry((weakRef) => { + const stream = weakRef.deref() + if (stream && !stream.locked && !isDisturbed(stream) && !isErrored(stream)) { + stream.cancel('Response object has been garbage collected').catch(noop) } - } + }) +} - // 3. If fetchParams’s process response is non-null, then queue a fetch task - // to run fetchParams’s process response given response, with fetchParams’s - // task destination. - if (fetchParams.processResponse != null) { - queueMicrotask(() => fetchParams.processResponse(response)) - } +// https://fetch.spec.whatwg.org/#concept-bodyinit-extract +function extractBody (object, keepalive = false) { + // 1. Let stream be null. + let stream = null - // 4. If response’s body is null, then run processResponseEndOfBody. - if (response.body == null) { - processResponseEndOfBody() + // 2. If object is a ReadableStream object, then set stream to object. + if (object instanceof ReadableStream) { + stream = object + } else if (isBlobLike(object)) { + // 3. Otherwise, if object is a Blob object, set stream to the + // result of running object’s get stream. + stream = object.stream() } else { - // 5. Otherwise: - - // 1. Let transformStream be a new a TransformStream. + // 4. Otherwise, set stream to a new ReadableStream object, and set + // up stream with byte reading support. + stream = new ReadableStream({ + async pull (controller) { + const buffer = typeof source === 'string' ? textEncoder.encode(source) : source - // 2. Let identityTransformAlgorithm be an algorithm which, given chunk, - // enqueues chunk in transformStream. - const identityTransformAlgorithm = (chunk, controller) => { - controller.enqueue(chunk) - } + if (buffer.byteLength) { + controller.enqueue(buffer) + } - // 3. Set up transformStream with transformAlgorithm set to identityTransformAlgorithm - // and flushAlgorithm set to processResponseEndOfBody. - const transformStream = new TransformStream({ + queueMicrotask(() => readableStreamClose(controller)) + }, start () {}, - transform: identityTransformAlgorithm, - flush: processResponseEndOfBody - }, { - size () { - return 1 - } - }, { - size () { - return 1 - } + type: 'bytes' }) - - // 4. Set response’s body to the result of piping response’s body through transformStream. - response.body = { stream: response.body.stream.pipeThrough(transformStream) } } - // 6. If fetchParams’s process response consume body is non-null, then: - if (fetchParams.processResponseConsumeBody != null) { - // 1. Let processBody given nullOrBytes be this step: run fetchParams’s - // process response consume body given response and nullOrBytes. - const processBody = (nullOrBytes) => fetchParams.processResponseConsumeBody(response, nullOrBytes) + // 5. Assert: stream is a ReadableStream object. + assert(isReadableStreamLike(stream)) - // 2. Let processBodyError be this step: run fetchParams’s process - // response consume body given response and failure. - const processBodyError = (failure) => fetchParams.processResponseConsumeBody(response, failure) + // 6. Let action be null. + let action = null - // 3. If response’s body is null, then queue a fetch task to run processBody - // given null, with fetchParams’s task destination. - if (response.body == null) { - queueMicrotask(() => processBody(null)) - } else { - // 4. Otherwise, fully read response’s body given processBody, processBodyError, - // and fetchParams’s task destination. - return fullyReadBody(response.body, processBody, processBodyError) - } - return Promise.resolve() - } -} + // 7. Let source be null. + let source = null -// https://fetch.spec.whatwg.org/#http-fetch -async function httpFetch (fetchParams) { - // 1. Let request be fetchParams’s request. - const request = fetchParams.request + // 8. Let length be null. + let length = null - // 2. Let response be null. - let response = null + // 9. Let type be null. + let type = null - // 3. Let actualResponse be null. - let actualResponse = null + // 10. Switch on object: + if (typeof object === 'string') { + // Set source to the UTF-8 encoding of object. + // Note: setting source to a Uint8Array here breaks some mocking assumptions. + source = object - // 4. Let timingInfo be fetchParams’s timing info. - const timingInfo = fetchParams.timingInfo + // Set type to `text/plain;charset=UTF-8`. + type = 'text/plain;charset=UTF-8' + } else if (object instanceof URLSearchParams) { + // URLSearchParams - // 5. If request’s service-workers mode is "all", then: - if (request.serviceWorkers === 'all') { - // TODO - } + // spec says to run application/x-www-form-urlencoded on body.list + // this is implemented in Node.js as apart of an URLSearchParams instance toString method + // See: https://github.com/nodejs/node/blob/e46c680bf2b211bbd52cf959ca17ee98c7f657f5/lib/internal/url.js#L490 + // and https://github.com/nodejs/node/blob/e46c680bf2b211bbd52cf959ca17ee98c7f657f5/lib/internal/url.js#L1100 - // 6. If response is null, then: - if (response === null) { - // 1. If makeCORSPreflight is true and one of these conditions is true: - // TODO + // Set source to the result of running the application/x-www-form-urlencoded serializer with object’s list. + source = object.toString() - // 2. If request’s redirect mode is "follow", then set request’s - // service-workers mode to "none". - if (request.redirect === 'follow') { - request.serviceWorkers = 'none' - } + // Set type to `application/x-www-form-urlencoded;charset=UTF-8`. + type = 'application/x-www-form-urlencoded;charset=UTF-8' + } else if (isArrayBuffer(object)) { + // BufferSource/ArrayBuffer - // 3. Set response and actualResponse to the result of running - // HTTP-network-or-cache fetch given fetchParams. - actualResponse = response = await httpNetworkOrCacheFetch(fetchParams) + // Set source to a copy of the bytes held by object. + source = new Uint8Array(object.slice()) + } else if (ArrayBuffer.isView(object)) { + // BufferSource/ArrayBufferView - // 4. If request’s response tainting is "cors" and a CORS check - // for request and response returns failure, then return a network error. - if ( - request.responseTainting === 'cors' && - corsCheck(request, response) === 'failure' - ) { - return makeNetworkError('cors failure') - } + // Set source to a copy of the bytes held by object. + source = new Uint8Array(object.buffer.slice(object.byteOffset, object.byteOffset + object.byteLength)) + } else if (util.isFormDataLike(object)) { + const boundary = `----formdata-undici-0${`${random(1e11)}`.padStart(11, '0')}` + const prefix = `--${boundary}\r\nContent-Disposition: form-data` - // 5. If the TAO check for request and response returns failure, then set - // request’s timing allow failed flag. - if (TAOCheck(request, response) === 'failure') { - request.timingAllowFailed = true - } - } + /*! formdata-polyfill. MIT License. Jimmy Wärting */ + const escape = (str) => + str.replace(/\n/g, '%0A').replace(/\r/g, '%0D').replace(/"/g, '%22') + const normalizeLinefeeds = (value) => value.replace(/\r?\n|\r/g, '\r\n') - // 7. If either request’s response tainting or response’s type - // is "opaque", and the cross-origin resource policy check with - // request’s origin, request’s client, request’s destination, - // and actualResponse returns blocked, then return a network error. - if ( - (request.responseTainting === 'opaque' || response.type === 'opaque') && - crossOriginResourcePolicyCheck( - request.origin, - request.client, - request.destination, - actualResponse - ) === 'blocked' - ) { - return makeNetworkError('blocked') - } + // Set action to this step: run the multipart/form-data + // encoding algorithm, with object’s entry list and UTF-8. + // - This ensures that the body is immutable and can't be changed afterwords + // - That the content-length is calculated in advance. + // - And that all parts are pre-encoded and ready to be sent. - // 8. If actualResponse’s status is a redirect status, then: - if (redirectStatusSet.has(actualResponse.status)) { - // 1. If actualResponse’s status is not 303, request’s body is not null, - // and the connection uses HTTP/2, then user agents may, and are even - // encouraged to, transmit an RST_STREAM frame. - // See, https://github.com/whatwg/fetch/issues/1288 - if (request.redirect !== 'manual') { - fetchParams.controller.connection.destroy() + const blobParts = [] + const rn = new Uint8Array([13, 10]) // '\r\n' + length = 0 + let hasUnknownSizeValue = false + + for (const [name, value] of object) { + if (typeof value === 'string') { + const chunk = textEncoder.encode(prefix + + `; name="${escape(normalizeLinefeeds(name))}"` + + `\r\n\r\n${normalizeLinefeeds(value)}\r\n`) + blobParts.push(chunk) + length += chunk.byteLength + } else { + const chunk = textEncoder.encode(`${prefix}; name="${escape(normalizeLinefeeds(name))}"` + + (value.name ? `; filename="${escape(value.name)}"` : '') + '\r\n' + + `Content-Type: ${ + value.type || 'application/octet-stream' + }\r\n\r\n`) + blobParts.push(chunk, value, rn) + if (typeof value.size === 'number') { + length += chunk.byteLength + value.size + rn.byteLength + } else { + hasUnknownSizeValue = true + } + } } - // 2. Switch on request’s redirect mode: - if (request.redirect === 'error') { - // Set response to a network error. - response = makeNetworkError('unexpected redirect') - } else if (request.redirect === 'manual') { - // Set response to an opaque-redirect filtered response whose internal - // response is actualResponse. - // NOTE(spec): On the web this would return an `opaqueredirect` response, - // but that doesn't make sense server side. - // See https://github.com/nodejs/undici/issues/1193. - response = actualResponse - } else if (request.redirect === 'follow') { - // Set response to the result of running HTTP-redirect fetch given - // fetchParams and response. - response = await httpRedirectFetch(fetchParams, response) - } else { - assert(false) + // CRLF is appended to the body to function with legacy servers and match other implementations. + // https://github.com/curl/curl/blob/3434c6b46e682452973972e8313613dfa58cd690/lib/mime.c#L1029-L1030 + // https://github.com/form-data/form-data/issues/63 + const chunk = textEncoder.encode(`--${boundary}--\r\n`) + blobParts.push(chunk) + length += chunk.byteLength + if (hasUnknownSizeValue) { + length = null } - } - // 9. Set response’s timing info to timingInfo. - response.timingInfo = timingInfo + // Set source to object. + source = object - // 10. Return response. - return response -} + action = async function * () { + for (const part of blobParts) { + if (part.stream) { + yield * part.stream() + } else { + yield part + } + } + } -// https://fetch.spec.whatwg.org/#http-redirect-fetch -function httpRedirectFetch (fetchParams, response) { - // 1. Let request be fetchParams’s request. - const request = fetchParams.request + // Set type to `multipart/form-data; boundary=`, + // followed by the multipart/form-data boundary string generated + // by the multipart/form-data encoding algorithm. + type = `multipart/form-data; boundary=${boundary}` + } else if (isBlobLike(object)) { + // Blob - // 2. Let actualResponse be response, if response is not a filtered response, - // and response’s internal response otherwise. - const actualResponse = response.internalResponse - ? response.internalResponse - : response + // Set source to object. + source = object - // 3. Let locationURL be actualResponse’s location URL given request’s current - // URL’s fragment. - let locationURL + // Set length to object’s size. + length = object.size - try { - locationURL = responseLocationURL( - actualResponse, - requestCurrentURL(request).hash - ) + // If object’s type attribute is not the empty byte sequence, set + // type to its value. + if (object.type) { + type = object.type + } + } else if (typeof object[Symbol.asyncIterator] === 'function') { + // If keepalive is true, then throw a TypeError. + if (keepalive) { + throw new TypeError('keepalive') + } - // 4. If locationURL is null, then return response. - if (locationURL == null) { - return response + // If object is disturbed or locked, then throw a TypeError. + if (util.isDisturbed(object) || object.locked) { + throw new TypeError( + 'Response body object should not be disturbed or locked' + ) } - } catch (err) { - // 5. If locationURL is failure, then return a network error. - return Promise.resolve(makeNetworkError(err)) + + stream = + object instanceof ReadableStream ? object : ReadableStreamFrom(object) } - // 6. If locationURL’s scheme is not an HTTP(S) scheme, then return a network - // error. - if (!urlIsHttpHttpsScheme(locationURL)) { - return Promise.resolve(makeNetworkError('URL scheme must be a HTTP(S) scheme')) + // 11. If source is a byte sequence, then set action to a + // step that returns source and length to source’s length. + if (typeof source === 'string' || util.isBuffer(source)) { + length = Buffer.byteLength(source) } - // 7. If request’s redirect count is 20, then return a network error. - if (request.redirectCount === 20) { - return Promise.resolve(makeNetworkError('redirect count exceeded')) + // 12. If action is non-null, then run these steps in in parallel: + if (action != null) { + // Run action. + let iterator + stream = new ReadableStream({ + async start () { + iterator = action(object)[Symbol.asyncIterator]() + }, + async pull (controller) { + const { value, done } = await iterator.next() + if (done) { + // When running action is done, close stream. + queueMicrotask(() => { + controller.close() + controller.byobRequest?.respond(0) + }) + } else { + // Whenever one or more bytes are available and stream is not errored, + // enqueue a Uint8Array wrapping an ArrayBuffer containing the available + // bytes into stream. + if (!isErrored(stream)) { + const buffer = new Uint8Array(value) + if (buffer.byteLength) { + controller.enqueue(buffer) + } + } + } + return controller.desiredSize > 0 + }, + async cancel (reason) { + await iterator.return() + }, + type: 'bytes' + }) } - // 8. Increase request’s redirect count by 1. - request.redirectCount += 1 + // 13. Let body be a body whose stream is stream, source is source, + // and length is length. + const body = { stream, source, length } - // 9. If request’s mode is "cors", locationURL includes credentials, and - // request’s origin is not same origin with locationURL’s origin, then return - // a network error. - if ( - request.mode === 'cors' && - (locationURL.username || locationURL.password) && - !sameOrigin(request, locationURL) - ) { - return Promise.resolve(makeNetworkError('cross origin not allowed for request mode "cors"')) - } + // 14. Return (body, type). + return [body, type] +} - // 10. If request’s response tainting is "cors" and locationURL includes - // credentials, then return a network error. - if ( - request.responseTainting === 'cors' && - (locationURL.username || locationURL.password) - ) { - return Promise.resolve(makeNetworkError( - 'URL cannot contain credentials for request mode "cors"' - )) - } +// https://fetch.spec.whatwg.org/#bodyinit-safely-extract +function safelyExtractBody (object, keepalive = false) { + // To safely extract a body and a `Content-Type` value from + // a byte sequence or BodyInit object object, run these steps: - // 11. If actualResponse’s status is not 303, request’s body is non-null, - // and request’s body’s source is null, then return a network error. - if ( - actualResponse.status !== 303 && - request.body != null && - request.body.source == null - ) { - return Promise.resolve(makeNetworkError()) + // 1. If object is a ReadableStream object, then: + if (object instanceof ReadableStream) { + // Assert: object is neither disturbed nor locked. + // istanbul ignore next + assert(!util.isDisturbed(object), 'The body has already been consumed.') + // istanbul ignore next + assert(!object.locked, 'The stream is locked.') } - // 12. If one of the following is true - // - actualResponse’s status is 301 or 302 and request’s method is `POST` - // - actualResponse’s status is 303 and request’s method is not `GET` or `HEAD` - if ( - ([301, 302].includes(actualResponse.status) && request.method === 'POST') || - (actualResponse.status === 303 && - !GET_OR_HEAD.includes(request.method)) - ) { - // then: - // 1. Set request’s method to `GET` and request’s body to null. - request.method = 'GET' - request.body = null + // 2. Return the results of extracting object. + return extractBody(object, keepalive) +} - // 2. For each headerName of request-body-header name, delete headerName from - // request’s header list. - for (const headerName of requestBodyHeader) { - request.headersList.delete(headerName) - } - } +function cloneBody (instance, body) { + // To clone a body body, run these steps: - // 13. If request’s current URL’s origin is not same origin with locationURL’s - // origin, then for each headerName of CORS non-wildcard request-header name, - // delete headerName from request’s header list. - if (!sameOrigin(requestCurrentURL(request), locationURL)) { - // https://fetch.spec.whatwg.org/#cors-non-wildcard-request-header-name - request.headersList.delete('authorization') + // https://fetch.spec.whatwg.org/#concept-body-clone - // https://fetch.spec.whatwg.org/#authentication-entries - request.headersList.delete('proxy-authorization', true) + // 1. Let « out1, out2 » be the result of teeing body’s stream. + const [out1, out2] = body.stream.tee() - // "Cookie" and "Host" are forbidden request-headers, which undici doesn't implement. - request.headersList.delete('cookie') - request.headersList.delete('host') - } + // 2. Set body’s stream to out1. + body.stream = out1 - // 14. If request’s body is non-null, then set request’s body to the first return - // value of safely extracting request’s body’s source. - if (request.body != null) { - assert(request.body.source != null) - request.body = safelyExtractBody(request.body.source)[0] + // 3. Return a body whose stream is out2 and other members are copied from body. + return { + stream: out2, + length: body.length, + source: body.source } +} - // 15. Let timingInfo be fetchParams’s timing info. - const timingInfo = fetchParams.timingInfo - - // 16. Set timingInfo’s redirect end time and post-redirect start time to the - // coarsened shared current time given fetchParams’s cross-origin isolated - // capability. - timingInfo.redirectEndTime = timingInfo.postRedirectStartTime = - coarsenedSharedCurrentTime(fetchParams.crossOriginIsolatedCapability) - - // 17. If timingInfo’s redirect start time is 0, then set timingInfo’s - // redirect start time to timingInfo’s start time. - if (timingInfo.redirectStartTime === 0) { - timingInfo.redirectStartTime = timingInfo.startTime +function throwIfAborted (state) { + if (state.aborted) { + throw new DOMException('The operation was aborted.', 'AbortError') } - - // 18. Append locationURL to request’s URL list. - request.urlList.push(locationURL) - - // 19. Invoke set request’s referrer policy on redirect on request and - // actualResponse. - setRequestReferrerPolicyOnRedirect(request, actualResponse) - - // 20. Return the result of running main fetch given fetchParams and true. - return mainFetch(fetchParams, true) } -// https://fetch.spec.whatwg.org/#http-network-or-cache-fetch -async function httpNetworkOrCacheFetch ( - fetchParams, - isAuthenticationFetch = false, - isNewConnectionFetch = false -) { - // 1. Let request be fetchParams’s request. - const request = fetchParams.request - - // 2. Let httpFetchParams be null. - let httpFetchParams = null - - // 3. Let httpRequest be null. - let httpRequest = null - - // 4. Let response be null. - let response = null +function bodyMixinMethods (instance) { + const methods = { + blob () { + // The blob() method steps are to return the result of + // running consume body with this and the following step + // given a byte sequence bytes: return a Blob whose + // contents are bytes and whose type attribute is this’s + // MIME type. + return consumeBody(this, (bytes) => { + let mimeType = bodyMimeType(this) - // 5. Let storedResponse be null. - // TODO: cache + if (mimeType === null) { + mimeType = '' + } else if (mimeType) { + mimeType = serializeAMimeType(mimeType) + } - // 6. Let httpCache be null. - const httpCache = null + // Return a Blob whose contents are bytes and type attribute + // is mimeType. + return new Blob([bytes], { type: mimeType }) + }, instance) + }, - // 7. Let the revalidatingFlag be unset. - const revalidatingFlag = false + arrayBuffer () { + // The arrayBuffer() method steps are to return the result + // of running consume body with this and the following step + // given a byte sequence bytes: return a new ArrayBuffer + // whose contents are bytes. + return consumeBody(this, (bytes) => { + return new Uint8Array(bytes).buffer + }, instance) + }, - // 8. Run these steps, but abort when the ongoing fetch is terminated: + text () { + // The text() method steps are to return the result of running + // consume body with this and UTF-8 decode. + return consumeBody(this, utf8DecodeBytes, instance) + }, - // 1. If request’s window is "no-window" and request’s redirect mode is - // "error", then set httpFetchParams to fetchParams and httpRequest to - // request. - if (request.window === 'no-window' && request.redirect === 'error') { - httpFetchParams = fetchParams - httpRequest = request - } else { - // Otherwise: + json () { + // The json() method steps are to return the result of running + // consume body with this and parse JSON from bytes. + return consumeBody(this, parseJSONFromBytes, instance) + }, - // 1. Set httpRequest to a clone of request. - httpRequest = makeRequest(request) + formData () { + // The formData() method steps are to return the result of running + // consume body with this and the following step given a byte sequence bytes: + return consumeBody(this, (value) => { + // 1. Let mimeType be the result of get the MIME type with this. + const mimeType = bodyMimeType(this) - // 2. Set httpFetchParams to a copy of fetchParams. - httpFetchParams = { ...fetchParams } + // 2. If mimeType is non-null, then switch on mimeType’s essence and run + // the corresponding steps: + if (mimeType !== null) { + switch (mimeType.essence) { + case 'multipart/form-data': { + // 1. ... [long step] + const parsed = multipartFormDataParser(value, mimeType) - // 3. Set httpFetchParams’s request to httpRequest. - httpFetchParams.request = httpRequest - } + // 2. If that fails for some reason, then throw a TypeError. + if (parsed === 'failure') { + throw new TypeError('Failed to parse body as FormData.') + } - // 3. Let includeCredentials be true if one of - const includeCredentials = - request.credentials === 'include' || - (request.credentials === 'same-origin' && - request.responseTainting === 'basic') + // 3. Return a new FormData object, appending each entry, + // resulting from the parsing operation, to its entry list. + const fd = new FormData() + fd[kState] = parsed - // 4. Let contentLength be httpRequest’s body’s length, if httpRequest’s - // body is non-null; otherwise null. - const contentLength = httpRequest.body ? httpRequest.body.length : null + return fd + } + case 'application/x-www-form-urlencoded': { + // 1. Let entries be the result of parsing bytes. + const entries = new URLSearchParams(value.toString()) - // 5. Let contentLengthHeaderValue be null. - let contentLengthHeaderValue = null + // 2. If entries is failure, then throw a TypeError. - // 6. If httpRequest’s body is null and httpRequest’s method is `POST` or - // `PUT`, then set contentLengthHeaderValue to `0`. - if ( - httpRequest.body == null && - ['POST', 'PUT'].includes(httpRequest.method) - ) { - contentLengthHeaderValue = '0' - } + // 3. Return a new FormData object whose entry list is entries. + const fd = new FormData() - // 7. If contentLength is non-null, then set contentLengthHeaderValue to - // contentLength, serialized and isomorphic encoded. - if (contentLength != null) { - contentLengthHeaderValue = isomorphicEncode(`${contentLength}`) - } + for (const [name, value] of entries) { + fd.append(name, value) + } - // 8. If contentLengthHeaderValue is non-null, then append - // `Content-Length`/contentLengthHeaderValue to httpRequest’s header - // list. - if (contentLengthHeaderValue != null) { - httpRequest.headersList.append('content-length', contentLengthHeaderValue) - } + return fd + } + } + } - // 9. If contentLengthHeaderValue is non-null, then append (`Content-Length`, - // contentLengthHeaderValue) to httpRequest’s header list. + // 3. Throw a TypeError. + throw new TypeError( + 'Content-Type was not one of "multipart/form-data" or "application/x-www-form-urlencoded".' + ) + }, instance) + }, - // 10. If contentLength is non-null and httpRequest’s keepalive is true, - // then: - if (contentLength != null && httpRequest.keepalive) { - // NOTE: keepalive is a noop outside of browser context. + bytes () { + // The bytes() method steps are to return the result of running consume body + // with this and the following step given a byte sequence bytes: return the + // result of creating a Uint8Array from bytes in this’s relevant realm. + return consumeBody(this, (bytes) => { + return new Uint8Array(bytes) + }, instance) + } } - // 11. If httpRequest’s referrer is a URL, then append - // `Referer`/httpRequest’s referrer, serialized and isomorphic encoded, - // to httpRequest’s header list. - if (httpRequest.referrer instanceof URL) { - httpRequest.headersList.append('referer', isomorphicEncode(httpRequest.referrer.href)) - } + return methods +} - // 12. Append a request `Origin` header for httpRequest. - appendRequestOriginHeader(httpRequest) +function mixinBody (prototype) { + Object.assign(prototype.prototype, bodyMixinMethods(prototype)) +} - // 13. Append the Fetch metadata headers for httpRequest. [FETCH-METADATA] - appendFetchMetadata(httpRequest) +/** + * @see https://fetch.spec.whatwg.org/#concept-body-consume-body + * @param {Response|Request} object + * @param {(value: unknown) => unknown} convertBytesToJSValue + * @param {Response|Request} instance + */ +async function consumeBody (object, convertBytesToJSValue, instance) { + webidl.brandCheck(object, instance) - // 14. If httpRequest’s header list does not contain `User-Agent`, then - // user agents should append `User-Agent`/default `User-Agent` value to - // httpRequest’s header list. - if (!httpRequest.headersList.contains('user-agent')) { - httpRequest.headersList.append('user-agent', typeof esbuildDetection === 'undefined' ? 'undici' : 'node') + // 1. If object is unusable, then return a promise rejected + // with a TypeError. + if (bodyUnusable(object)) { + throw new TypeError('Body is unusable: Body has already been read') } - // 15. If httpRequest’s cache mode is "default" and httpRequest’s header - // list contains `If-Modified-Since`, `If-None-Match`, - // `If-Unmodified-Since`, `If-Match`, or `If-Range`, then set - // httpRequest’s cache mode to "no-store". - if ( - httpRequest.cache === 'default' && - (httpRequest.headersList.contains('if-modified-since') || - httpRequest.headersList.contains('if-none-match') || - httpRequest.headersList.contains('if-unmodified-since') || - httpRequest.headersList.contains('if-match') || - httpRequest.headersList.contains('if-range')) - ) { - httpRequest.cache = 'no-store' - } + throwIfAborted(object[kState]) - // 16. If httpRequest’s cache mode is "no-cache", httpRequest’s prevent - // no-cache cache-control header modification flag is unset, and - // httpRequest’s header list does not contain `Cache-Control`, then append - // `Cache-Control`/`max-age=0` to httpRequest’s header list. - if ( - httpRequest.cache === 'no-cache' && - !httpRequest.preventNoCacheCacheControlHeaderModification && - !httpRequest.headersList.contains('cache-control') - ) { - httpRequest.headersList.append('cache-control', 'max-age=0') - } + // 2. Let promise be a new promise. + const promise = createDeferredPromise() - // 17. If httpRequest’s cache mode is "no-store" or "reload", then: - if (httpRequest.cache === 'no-store' || httpRequest.cache === 'reload') { - // 1. If httpRequest’s header list does not contain `Pragma`, then append - // `Pragma`/`no-cache` to httpRequest’s header list. - if (!httpRequest.headersList.contains('pragma')) { - httpRequest.headersList.append('pragma', 'no-cache') - } + // 3. Let errorSteps given error be to reject promise with error. + const errorSteps = (error) => promise.reject(error) - // 2. If httpRequest’s header list does not contain `Cache-Control`, - // then append `Cache-Control`/`no-cache` to httpRequest’s header list. - if (!httpRequest.headersList.contains('cache-control')) { - httpRequest.headersList.append('cache-control', 'no-cache') + // 4. Let successSteps given a byte sequence data be to resolve + // promise with the result of running convertBytesToJSValue + // with data. If that threw an exception, then run errorSteps + // with that exception. + const successSteps = (data) => { + try { + promise.resolve(convertBytesToJSValue(data)) + } catch (e) { + errorSteps(e) } } - // 18. If httpRequest’s header list contains `Range`, then append - // `Accept-Encoding`/`identity` to httpRequest’s header list. - if (httpRequest.headersList.contains('range')) { - httpRequest.headersList.append('accept-encoding', 'identity') + // 5. If object’s body is null, then run successSteps with an + // empty byte sequence. + if (object[kState].body == null) { + successSteps(Buffer.allocUnsafe(0)) + return promise.promise } - // 19. Modify httpRequest’s header list per HTTP. Do not append a given - // header if httpRequest’s header list contains that header’s name. - // TODO: https://github.com/whatwg/fetch/issues/1285#issuecomment-896560129 - if (!httpRequest.headersList.contains('accept-encoding')) { - if (urlHasHttpsScheme(requestCurrentURL(httpRequest))) { - httpRequest.headersList.append('accept-encoding', 'br, gzip, deflate') - } else { - httpRequest.headersList.append('accept-encoding', 'gzip, deflate') - } - } + // 6. Otherwise, fully read object’s body given successSteps, + // errorSteps, and object’s relevant global object. + await fullyReadBody(object[kState].body, successSteps, errorSteps) - httpRequest.headersList.delete('host') + // 7. Return promise. + return promise.promise +} - // 20. If includeCredentials is true, then: - if (includeCredentials) { - // 1. If the user agent is not configured to block cookies for httpRequest - // (see section 7 of [COOKIES]), then: - // TODO: credentials - // 2. If httpRequest’s header list does not contain `Authorization`, then: - // TODO: credentials - } +// https://fetch.spec.whatwg.org/#body-unusable +function bodyUnusable (object) { + const body = object[kState].body - // 21. If there’s a proxy-authentication entry, use it as appropriate. - // TODO: proxy-authentication + // An object including the Body interface mixin is + // said to be unusable if its body is non-null and + // its body’s stream is disturbed or locked. + return body != null && (body.stream.locked || util.isDisturbed(body.stream)) +} - // 22. Set httpCache to the result of determining the HTTP cache - // partition, given httpRequest. - // TODO: cache +/** + * @see https://infra.spec.whatwg.org/#parse-json-bytes-to-a-javascript-value + * @param {Uint8Array} bytes + */ +function parseJSONFromBytes (bytes) { + return JSON.parse(utf8DecodeBytes(bytes)) +} - // 23. If httpCache is null, then set httpRequest’s cache mode to - // "no-store". - if (httpCache == null) { - httpRequest.cache = 'no-store' - } +/** + * @see https://fetch.spec.whatwg.org/#concept-body-mime-type + * @param {import('./response').Response|import('./request').Request} requestOrResponse + */ +function bodyMimeType (requestOrResponse) { + // 1. Let headers be null. + // 2. If requestOrResponse is a Request object, then set headers to requestOrResponse’s request’s header list. + // 3. Otherwise, set headers to requestOrResponse’s response’s header list. + /** @type {import('./headers').HeadersList} */ + const headers = requestOrResponse[kState].headersList - // 24. If httpRequest’s cache mode is neither "no-store" nor "reload", - // then: - if (httpRequest.mode !== 'no-store' && httpRequest.mode !== 'reload') { - // TODO: cache + // 4. Let mimeType be the result of extracting a MIME type from headers. + const mimeType = extractMimeType(headers) + + // 5. If mimeType is failure, then return null. + if (mimeType === 'failure') { + return null } - // 9. If aborted, then return the appropriate network error for fetchParams. - // TODO + // 6. Return mimeType. + return mimeType +} - // 10. If response is null, then: - if (response == null) { - // 1. If httpRequest’s cache mode is "only-if-cached", then return a - // network error. - if (httpRequest.mode === 'only-if-cached') { - return makeNetworkError('only if cached') - } +module.exports = { + extractBody, + safelyExtractBody, + cloneBody, + mixinBody, + streamRegistry, + hasFinalizationRegistry, + bodyUnusable +} - // 2. Let forwardResponse be the result of running HTTP-network fetch - // given httpFetchParams, includeCredentials, and isNewConnectionFetch. - const forwardResponse = await httpNetworkFetch( - httpFetchParams, - includeCredentials, - isNewConnectionFetch - ) - // 3. If httpRequest’s method is unsafe and forwardResponse’s status is - // in the range 200 to 399, inclusive, invalidate appropriate stored - // responses in httpCache, as per the "Invalidation" chapter of HTTP - // Caching, and set storedResponse to null. [HTTP-CACHING] - if ( - !safeMethodsSet.has(httpRequest.method) && - forwardResponse.status >= 200 && - forwardResponse.status <= 399 - ) { - // TODO: cache - } +/***/ }), - // 4. If the revalidatingFlag is set and forwardResponse’s status is 304, - // then: - if (revalidatingFlag && forwardResponse.status === 304) { - // TODO: cache - } +/***/ 6169: +/***/ ((module) => { - // 5. If response is null, then: - if (response == null) { - // 1. Set response to forwardResponse. - response = forwardResponse - // 2. Store httpRequest and forwardResponse in httpCache, as per the - // "Storing Responses in Caches" chapter of HTTP Caching. [HTTP-CACHING] - // TODO: cache - } - } - // 11. Set response’s URL list to a clone of httpRequest’s URL list. - response.urlList = [...httpRequest.urlList] +const corsSafeListedMethods = /** @type {const} */ (['GET', 'HEAD', 'POST']) +const corsSafeListedMethodsSet = new Set(corsSafeListedMethods) - // 12. If httpRequest’s header list contains `Range`, then set response’s - // range-requested flag. - if (httpRequest.headersList.contains('range')) { - response.rangeRequested = true - } +const nullBodyStatus = /** @type {const} */ ([101, 204, 205, 304]) - // 13. Set response’s request-includes-credentials to includeCredentials. - response.requestIncludesCredentials = includeCredentials - - // 14. If response’s status is 401, httpRequest’s response tainting is not - // "cors", includeCredentials is true, and request’s window is an environment - // settings object, then: - // TODO +const redirectStatus = /** @type {const} */ ([301, 302, 303, 307, 308]) +const redirectStatusSet = new Set(redirectStatus) - // 15. If response’s status is 407, then: - if (response.status === 407) { - // 1. If request’s window is "no-window", then return a network error. - if (request.window === 'no-window') { - return makeNetworkError() - } +/** + * @see https://fetch.spec.whatwg.org/#block-bad-port + */ +const badPorts = /** @type {const} */ ([ + '1', '7', '9', '11', '13', '15', '17', '19', '20', '21', '22', '23', '25', '37', '42', '43', '53', '69', '77', '79', + '87', '95', '101', '102', '103', '104', '109', '110', '111', '113', '115', '117', '119', '123', '135', '137', + '139', '143', '161', '179', '389', '427', '465', '512', '513', '514', '515', '526', '530', '531', '532', + '540', '548', '554', '556', '563', '587', '601', '636', '989', '990', '993', '995', '1719', '1720', '1723', + '2049', '3659', '4045', '4190', '5060', '5061', '6000', '6566', '6665', '6666', '6667', '6668', '6669', '6679', + '6697', '10080' +]) +const badPortsSet = new Set(badPorts) - // 2. ??? +/** + * @see https://w3c.github.io/webappsec-referrer-policy/#referrer-policies + */ +const referrerPolicy = /** @type {const} */ ([ + '', + 'no-referrer', + 'no-referrer-when-downgrade', + 'same-origin', + 'origin', + 'strict-origin', + 'origin-when-cross-origin', + 'strict-origin-when-cross-origin', + 'unsafe-url' +]) +const referrerPolicySet = new Set(referrerPolicy) - // 3. If fetchParams is canceled, then return the appropriate network error for fetchParams. - if (isCancelled(fetchParams)) { - return makeAppropriateNetworkError(fetchParams) - } +const requestRedirect = /** @type {const} */ (['follow', 'manual', 'error']) - // 4. Prompt the end user as appropriate in request’s window and store - // the result as a proxy-authentication entry. [HTTP-AUTH] - // TODO: Invoke some kind of callback? +const safeMethods = /** @type {const} */ (['GET', 'HEAD', 'OPTIONS', 'TRACE']) +const safeMethodsSet = new Set(safeMethods) - // 5. Set response to the result of running HTTP-network-or-cache fetch given - // fetchParams. - // TODO - return makeNetworkError('proxy authentication required') - } +const requestMode = /** @type {const} */ (['navigate', 'same-origin', 'no-cors', 'cors']) - // 16. If all of the following are true - if ( - // response’s status is 421 - response.status === 421 && - // isNewConnectionFetch is false - !isNewConnectionFetch && - // request’s body is null, or request’s body is non-null and request’s body’s source is non-null - (request.body == null || request.body.source != null) - ) { - // then: +const requestCredentials = /** @type {const} */ (['omit', 'same-origin', 'include']) - // 1. If fetchParams is canceled, then return the appropriate network error for fetchParams. - if (isCancelled(fetchParams)) { - return makeAppropriateNetworkError(fetchParams) - } +const requestCache = /** @type {const} */ ([ + 'default', + 'no-store', + 'reload', + 'no-cache', + 'force-cache', + 'only-if-cached' +]) - // 2. Set response to the result of running HTTP-network-or-cache - // fetch given fetchParams, isAuthenticationFetch, and true. +/** + * @see https://fetch.spec.whatwg.org/#request-body-header-name + */ +const requestBodyHeader = /** @type {const} */ ([ + 'content-encoding', + 'content-language', + 'content-location', + 'content-type', + // See https://github.com/nodejs/undici/issues/2021 + // 'Content-Length' is a forbidden header name, which is typically + // removed in the Headers implementation. However, undici doesn't + // filter out headers, so we add it here. + 'content-length' +]) - // TODO (spec): The spec doesn't specify this but we need to cancel - // the active response before we can start a new one. - // https://github.com/whatwg/fetch/issues/1293 - fetchParams.controller.connection.destroy() +/** + * @see https://fetch.spec.whatwg.org/#enumdef-requestduplex + */ +const requestDuplex = /** @type {const} */ ([ + 'half' +]) - response = await httpNetworkOrCacheFetch( - fetchParams, - isAuthenticationFetch, - true - ) - } +/** + * @see http://fetch.spec.whatwg.org/#forbidden-method + */ +const forbiddenMethods = /** @type {const} */ (['CONNECT', 'TRACE', 'TRACK']) +const forbiddenMethodsSet = new Set(forbiddenMethods) - // 17. If isAuthenticationFetch is true, then create an authentication entry - if (isAuthenticationFetch) { - // TODO - } +const subresource = /** @type {const} */ ([ + 'audio', + 'audioworklet', + 'font', + 'image', + 'manifest', + 'paintworklet', + 'script', + 'style', + 'track', + 'video', + 'xslt', + '' +]) +const subresourceSet = new Set(subresource) - // 18. Return response. - return response +module.exports = { + subresource, + forbiddenMethods, + requestBodyHeader, + referrerPolicy, + requestRedirect, + requestMode, + requestCredentials, + requestCache, + redirectStatus, + corsSafeListedMethods, + nullBodyStatus, + safeMethods, + badPorts, + requestDuplex, + subresourceSet, + badPortsSet, + redirectStatusSet, + corsSafeListedMethodsSet, + safeMethodsSet, + forbiddenMethodsSet, + referrerPolicySet } -// https://fetch.spec.whatwg.org/#http-network-fetch -async function httpNetworkFetch ( - fetchParams, - includeCredentials = false, - forceNewConnection = false -) { - assert(!fetchParams.controller.connection || fetchParams.controller.connection.destroyed) - - fetchParams.controller.connection = { - abort: null, - destroyed: false, - destroy (err) { - if (!this.destroyed) { - this.destroyed = true - this.abort?.(err ?? new DOMException('The operation was aborted.', 'AbortError')) - } - } - } - - // 1. Let request be fetchParams’s request. - const request = fetchParams.request - - // 2. Let response be null. - let response = null - - // 3. Let timingInfo be fetchParams’s timing info. - const timingInfo = fetchParams.timingInfo - - // 4. Let httpCache be the result of determining the HTTP cache partition, - // given request. - // TODO: cache - const httpCache = null - // 5. If httpCache is null, then set request’s cache mode to "no-store". - if (httpCache == null) { - request.cache = 'no-store' - } +/***/ }), - // 6. Let networkPartitionKey be the result of determining the network - // partition key given request. - // TODO +/***/ 6406: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - // 7. Let newConnection be "yes" if forceNewConnection is true; otherwise - // "no". - const newConnection = forceNewConnection ? 'yes' : 'no' // eslint-disable-line no-unused-vars - // 8. Switch on request’s mode: - if (request.mode === 'websocket') { - // Let connection be the result of obtaining a WebSocket connection, - // given request’s current URL. - // TODO - } else { - // Let connection be the result of obtaining a connection, given - // networkPartitionKey, request’s current URL’s origin, - // includeCredentials, and forceNewConnection. - // TODO - } - // 9. Run these steps, but abort when the ongoing fetch is terminated: +const assert = __nccwpck_require__(4589) - // 1. If connection is failure, then return a network error. +const encoder = new TextEncoder() - // 2. Set timingInfo’s final connection timing info to the result of - // calling clamp and coarsen connection timing info with connection’s - // timing info, timingInfo’s post-redirect start time, and fetchParams’s - // cross-origin isolated capability. +/** + * @see https://mimesniff.spec.whatwg.org/#http-token-code-point + */ +const HTTP_TOKEN_CODEPOINTS = /^[!#$%&'*+\-.^_|~A-Za-z0-9]+$/ +const HTTP_WHITESPACE_REGEX = /[\u000A\u000D\u0009\u0020]/ // eslint-disable-line +const ASCII_WHITESPACE_REPLACE_REGEX = /[\u0009\u000A\u000C\u000D\u0020]/g // eslint-disable-line +/** + * @see https://mimesniff.spec.whatwg.org/#http-quoted-string-token-code-point + */ +const HTTP_QUOTED_STRING_TOKENS = /^[\u0009\u0020-\u007E\u0080-\u00FF]+$/ // eslint-disable-line - // 3. If connection is not an HTTP/2 connection, request’s body is non-null, - // and request’s body’s source is null, then append (`Transfer-Encoding`, - // `chunked`) to request’s header list. +// https://fetch.spec.whatwg.org/#data-url-processor +/** @param {URL} dataURL */ +function dataURLProcessor (dataURL) { + // 1. Assert: dataURL’s scheme is "data". + assert(dataURL.protocol === 'data:') - // 4. Set timingInfo’s final network-request start time to the coarsened - // shared current time given fetchParams’s cross-origin isolated - // capability. + // 2. Let input be the result of running the URL + // serializer on dataURL with exclude fragment + // set to true. + let input = URLSerializer(dataURL, true) - // 5. Set response to the result of making an HTTP request over connection - // using request with the following caveats: + // 3. Remove the leading "data:" string from input. + input = input.slice(5) - // - Follow the relevant requirements from HTTP. [HTTP] [HTTP-SEMANTICS] - // [HTTP-COND] [HTTP-CACHING] [HTTP-AUTH] + // 4. Let position point at the start of input. + const position = { position: 0 } - // - If request’s body is non-null, and request’s body’s source is null, - // then the user agent may have a buffer of up to 64 kibibytes and store - // a part of request’s body in that buffer. If the user agent reads from - // request’s body beyond that buffer’s size and the user agent needs to - // resend request, then instead return a network error. + // 5. Let mimeType be the result of collecting a + // sequence of code points that are not equal + // to U+002C (,), given position. + let mimeType = collectASequenceOfCodePointsFast( + ',', + input, + position + ) - // - Set timingInfo’s final network-response start time to the coarsened - // shared current time given fetchParams’s cross-origin isolated capability, - // immediately after the user agent’s HTTP parser receives the first byte - // of the response (e.g., frame header bytes for HTTP/2 or response status - // line for HTTP/1.x). + // 6. Strip leading and trailing ASCII whitespace + // from mimeType. + // Undici implementation note: we need to store the + // length because if the mimetype has spaces removed, + // the wrong amount will be sliced from the input in + // step #9 + const mimeTypeLength = mimeType.length + mimeType = removeASCIIWhitespace(mimeType, true, true) - // - Wait until all the headers are transmitted. + // 7. If position is past the end of input, then + // return failure + if (position.position >= input.length) { + return 'failure' + } - // - Any responses whose status is in the range 100 to 199, inclusive, - // and is not 101, are to be ignored, except for the purposes of setting - // timingInfo’s final network-response start time above. + // 8. Advance position by 1. + position.position++ - // - If request’s header list contains `Transfer-Encoding`/`chunked` and - // response is transferred via HTTP/1.0 or older, then return a network - // error. + // 9. Let encodedBody be the remainder of input. + const encodedBody = input.slice(mimeTypeLength + 1) - // - If the HTTP request results in a TLS client certificate dialog, then: + // 10. Let body be the percent-decoding of encodedBody. + let body = stringPercentDecode(encodedBody) - // 1. If request’s window is an environment settings object, make the - // dialog available in request’s window. + // 11. If mimeType ends with U+003B (;), followed by + // zero or more U+0020 SPACE, followed by an ASCII + // case-insensitive match for "base64", then: + if (/;(\u0020){0,}base64$/i.test(mimeType)) { + // 1. Let stringBody be the isomorphic decode of body. + const stringBody = isomorphicDecode(body) - // 2. Otherwise, return a network error. + // 2. Set body to the forgiving-base64 decode of + // stringBody. + body = forgivingBase64(stringBody) - // To transmit request’s body body, run these steps: - let requestBody = null - // 1. If body is null and fetchParams’s process request end-of-body is - // non-null, then queue a fetch task given fetchParams’s process request - // end-of-body and fetchParams’s task destination. - if (request.body == null && fetchParams.processRequestEndOfBody) { - queueMicrotask(() => fetchParams.processRequestEndOfBody()) - } else if (request.body != null) { - // 2. Otherwise, if body is non-null: + // 3. If body is failure, then return failure. + if (body === 'failure') { + return 'failure' + } - // 1. Let processBodyChunk given bytes be these steps: - const processBodyChunk = async function * (bytes) { - // 1. If the ongoing fetch is terminated, then abort these steps. - if (isCancelled(fetchParams)) { - return - } + // 4. Remove the last 6 code points from mimeType. + mimeType = mimeType.slice(0, -6) - // 2. Run this step in parallel: transmit bytes. - yield bytes + // 5. Remove trailing U+0020 SPACE code points from mimeType, + // if any. + mimeType = mimeType.replace(/(\u0020)+$/, '') - // 3. If fetchParams’s process request body is non-null, then run - // fetchParams’s process request body given bytes’s length. - fetchParams.processRequestBodyChunkLength?.(bytes.byteLength) - } + // 6. Remove the last U+003B (;) code point from mimeType. + mimeType = mimeType.slice(0, -1) + } - // 2. Let processEndOfBody be these steps: - const processEndOfBody = () => { - // 1. If fetchParams is canceled, then abort these steps. - if (isCancelled(fetchParams)) { - return - } + // 12. If mimeType starts with U+003B (;), then prepend + // "text/plain" to mimeType. + if (mimeType.startsWith(';')) { + mimeType = 'text/plain' + mimeType + } - // 2. If fetchParams’s process request end-of-body is non-null, - // then run fetchParams’s process request end-of-body. - if (fetchParams.processRequestEndOfBody) { - fetchParams.processRequestEndOfBody() - } - } + // 13. Let mimeTypeRecord be the result of parsing + // mimeType. + let mimeTypeRecord = parseMIMEType(mimeType) - // 3. Let processBodyError given e be these steps: - const processBodyError = (e) => { - // 1. If fetchParams is canceled, then abort these steps. - if (isCancelled(fetchParams)) { - return - } + // 14. If mimeTypeRecord is failure, then set + // mimeTypeRecord to text/plain;charset=US-ASCII. + if (mimeTypeRecord === 'failure') { + mimeTypeRecord = parseMIMEType('text/plain;charset=US-ASCII') + } - // 2. If e is an "AbortError" DOMException, then abort fetchParams’s controller. - if (e.name === 'AbortError') { - fetchParams.controller.abort() - } else { - fetchParams.controller.terminate(e) - } - } + // 15. Return a new data: URL struct whose MIME + // type is mimeTypeRecord and body is body. + // https://fetch.spec.whatwg.org/#data-url-struct + return { mimeType: mimeTypeRecord, body } +} - // 4. Incrementally read request’s body given processBodyChunk, processEndOfBody, - // processBodyError, and fetchParams’s task destination. - requestBody = (async function * () { - try { - for await (const bytes of request.body.stream) { - yield * processBodyChunk(bytes) - } - processEndOfBody() - } catch (err) { - processBodyError(err) - } - })() +// https://url.spec.whatwg.org/#concept-url-serializer +/** + * @param {URL} url + * @param {boolean} excludeFragment + */ +function URLSerializer (url, excludeFragment = false) { + if (!excludeFragment) { + return url.href } - try { - // socket is only provided for websockets - const { body, status, statusText, headersList, socket } = await dispatch({ body: requestBody }) + const href = url.href + const hashLength = url.hash.length - if (socket) { - response = makeResponse({ status, statusText, headersList, socket }) - } else { - const iterator = body[Symbol.asyncIterator]() - fetchParams.controller.next = () => iterator.next() + const serialized = hashLength === 0 ? href : href.substring(0, href.length - hashLength) - response = makeResponse({ status, statusText, headersList }) - } - } catch (err) { - // 10. If aborted, then: - if (err.name === 'AbortError') { - // 1. If connection uses HTTP/2, then transmit an RST_STREAM frame. - fetchParams.controller.connection.destroy() + if (!hashLength && href.endsWith('#')) { + return serialized.slice(0, -1) + } - // 2. Return the appropriate network error for fetchParams. - return makeAppropriateNetworkError(fetchParams, err) - } + return serialized +} - return makeNetworkError(err) - } +// https://infra.spec.whatwg.org/#collect-a-sequence-of-code-points +/** + * @param {(char: string) => boolean} condition + * @param {string} input + * @param {{ position: number }} position + */ +function collectASequenceOfCodePoints (condition, input, position) { + // 1. Let result be the empty string. + let result = '' - // 11. Let pullAlgorithm be an action that resumes the ongoing fetch - // if it is suspended. - const pullAlgorithm = () => { - fetchParams.controller.resume() - } + // 2. While position doesn’t point past the end of input and the + // code point at position within input meets the condition condition: + while (position.position < input.length && condition(input[position.position])) { + // 1. Append that code point to the end of result. + result += input[position.position] - // 12. Let cancelAlgorithm be an algorithm that aborts fetchParams’s - // controller with reason, given reason. - const cancelAlgorithm = (reason) => { - fetchParams.controller.abort(reason) + // 2. Advance position by 1. + position.position++ } - // 13. Let highWaterMark be a non-negative, non-NaN number, chosen by - // the user agent. - // TODO + // 3. Return result. + return result +} - // 14. Let sizeAlgorithm be an algorithm that accepts a chunk object - // and returns a non-negative, non-NaN, non-infinite number, chosen by the user agent. - // TODO +/** + * A faster collectASequenceOfCodePoints that only works when comparing a single character. + * @param {string} char + * @param {string} input + * @param {{ position: number }} position + */ +function collectASequenceOfCodePointsFast (char, input, position) { + const idx = input.indexOf(char, position.position) + const start = position.position - // 15. Let stream be a new ReadableStream. - // 16. Set up stream with pullAlgorithm set to pullAlgorithm, - // cancelAlgorithm set to cancelAlgorithm, highWaterMark set to - // highWaterMark, and sizeAlgorithm set to sizeAlgorithm. - if (!ReadableStream) { - ReadableStream = (__nccwpck_require__(3774).ReadableStream) + if (idx === -1) { + position.position = input.length + return input.slice(start) } - const stream = new ReadableStream( - { - async start (controller) { - fetchParams.controller.controller = controller - }, - async pull (controller) { - await pullAlgorithm(controller) - }, - async cancel (reason) { - await cancelAlgorithm(reason) - } - }, - { - highWaterMark: 0, - size () { - return 1 - } - } - ) - - // 17. Run these steps, but abort when the ongoing fetch is terminated: + position.position = idx + return input.slice(start, position.position) +} - // 1. Set response’s body to a new body whose stream is stream. - response.body = { stream } +// https://url.spec.whatwg.org/#string-percent-decode +/** @param {string} input */ +function stringPercentDecode (input) { + // 1. Let bytes be the UTF-8 encoding of input. + const bytes = encoder.encode(input) - // 2. If response is not a network error and request’s cache mode is - // not "no-store", then update response in httpCache for request. - // TODO + // 2. Return the percent-decoding of bytes. + return percentDecode(bytes) +} - // 3. If includeCredentials is true and the user agent is not configured - // to block cookies for request (see section 7 of [COOKIES]), then run the - // "set-cookie-string" parsing algorithm (see section 5.2 of [COOKIES]) on - // the value of each header whose name is a byte-case-insensitive match for - // `Set-Cookie` in response’s header list, if any, and request’s current URL. - // TODO - - // 18. If aborted, then: - // TODO - - // 19. Run these steps in parallel: - - // 1. Run these steps, but abort when fetchParams is canceled: - fetchParams.controller.on('terminated', onAborted) - fetchParams.controller.resume = async () => { - // 1. While true - while (true) { - // 1-3. See onData... +/** + * @param {number} byte + */ +function isHexCharByte (byte) { + // 0-9 A-F a-f + return (byte >= 0x30 && byte <= 0x39) || (byte >= 0x41 && byte <= 0x46) || (byte >= 0x61 && byte <= 0x66) +} - // 4. Set bytes to the result of handling content codings given - // codings and bytes. - let bytes - let isFailure - try { - const { done, value } = await fetchParams.controller.next() +/** + * @param {number} byte + */ +function hexByteToNumber (byte) { + return ( + // 0-9 + byte >= 0x30 && byte <= 0x39 + ? (byte - 48) + // Convert to uppercase + // ((byte & 0xDF) - 65) + 10 + : ((byte & 0xDF) - 55) + ) +} - if (isAborted(fetchParams)) { - break - } +// https://url.spec.whatwg.org/#percent-decode +/** @param {Uint8Array} input */ +function percentDecode (input) { + const length = input.length + // 1. Let output be an empty byte sequence. + /** @type {Uint8Array} */ + const output = new Uint8Array(length) + let j = 0 + // 2. For each byte byte in input: + for (let i = 0; i < length; ++i) { + const byte = input[i] - bytes = done ? undefined : value - } catch (err) { - if (fetchParams.controller.ended && !timingInfo.encodedBodySize) { - // zlib doesn't like empty streams. - bytes = undefined - } else { - bytes = err + // 1. If byte is not 0x25 (%), then append byte to output. + if (byte !== 0x25) { + output[j++] = byte - // err may be propagated from the result of calling readablestream.cancel, - // which might not be an error. https://github.com/nodejs/undici/issues/2009 - isFailure = true - } - } + // 2. Otherwise, if byte is 0x25 (%) and the next two bytes + // after byte in input are not in the ranges + // 0x30 (0) to 0x39 (9), 0x41 (A) to 0x46 (F), + // and 0x61 (a) to 0x66 (f), all inclusive, append byte + // to output. + } else if ( + byte === 0x25 && + !(isHexCharByte(input[i + 1]) && isHexCharByte(input[i + 2])) + ) { + output[j++] = 0x25 - if (bytes === undefined) { - // 2. Otherwise, if the bytes transmission for response’s message - // body is done normally and stream is readable, then close - // stream, finalize response for fetchParams and response, and - // abort these in-parallel steps. - readableStreamClose(fetchParams.controller.controller) + // 3. Otherwise: + } else { + // 1. Let bytePoint be the two bytes after byte in input, + // decoded, and then interpreted as hexadecimal number. + // 2. Append a byte whose value is bytePoint to output. + output[j++] = (hexByteToNumber(input[i + 1]) << 4) | hexByteToNumber(input[i + 2]) - finalizeResponse(fetchParams, response) + // 3. Skip the next two bytes in input. + i += 2 + } + } - return - } + // 3. Return output. + return length === j ? output : output.subarray(0, j) +} - // 5. Increase timingInfo’s decoded body size by bytes’s length. - timingInfo.decodedBodySize += bytes?.byteLength ?? 0 +// https://mimesniff.spec.whatwg.org/#parse-a-mime-type +/** @param {string} input */ +function parseMIMEType (input) { + // 1. Remove any leading and trailing HTTP whitespace + // from input. + input = removeHTTPWhitespace(input, true, true) - // 6. If bytes is failure, then terminate fetchParams’s controller. - if (isFailure) { - fetchParams.controller.terminate(bytes) - return - } + // 2. Let position be a position variable for input, + // initially pointing at the start of input. + const position = { position: 0 } - // 7. Enqueue a Uint8Array wrapping an ArrayBuffer containing bytes - // into stream. - fetchParams.controller.controller.enqueue(new Uint8Array(bytes)) + // 3. Let type be the result of collecting a sequence + // of code points that are not U+002F (/) from + // input, given position. + const type = collectASequenceOfCodePointsFast( + '/', + input, + position + ) - // 8. If stream is errored, then terminate the ongoing fetch. - if (isErrored(stream)) { - fetchParams.controller.terminate() - return - } + // 4. If type is the empty string or does not solely + // contain HTTP token code points, then return failure. + // https://mimesniff.spec.whatwg.org/#http-token-code-point + if (type.length === 0 || !HTTP_TOKEN_CODEPOINTS.test(type)) { + return 'failure' + } - // 9. If stream doesn’t need more data ask the user agent to suspend - // the ongoing fetch. - if (!fetchParams.controller.controller.desiredSize) { - return - } - } + // 5. If position is past the end of input, then return + // failure + if (position.position > input.length) { + return 'failure' } - // 2. If aborted, then: - function onAborted (reason) { - // 2. If fetchParams is aborted, then: - if (isAborted(fetchParams)) { - // 1. Set response’s aborted flag. - response.aborted = true + // 6. Advance position by 1. (This skips past U+002F (/).) + position.position++ - // 2. If stream is readable, then error stream with the result of - // deserialize a serialized abort reason given fetchParams’s - // controller’s serialized abort reason and an - // implementation-defined realm. - if (isReadable(stream)) { - fetchParams.controller.controller.error( - fetchParams.controller.serializedAbortReason - ) - } - } else { - // 3. Otherwise, if stream is readable, error stream with a TypeError. - if (isReadable(stream)) { - fetchParams.controller.controller.error(new TypeError('terminated', { - cause: isErrorLike(reason) ? reason : undefined - })) - } - } + // 7. Let subtype be the result of collecting a sequence of + // code points that are not U+003B (;) from input, given + // position. + let subtype = collectASequenceOfCodePointsFast( + ';', + input, + position + ) - // 4. If connection uses HTTP/2, then transmit an RST_STREAM frame. - // 5. Otherwise, the user agent should close connection unless it would be bad for performance to do so. - fetchParams.controller.connection.destroy() + // 8. Remove any trailing HTTP whitespace from subtype. + subtype = removeHTTPWhitespace(subtype, false, true) + + // 9. If subtype is the empty string or does not solely + // contain HTTP token code points, then return failure. + if (subtype.length === 0 || !HTTP_TOKEN_CODEPOINTS.test(subtype)) { + return 'failure' } - // 20. Return response. - return response + const typeLowercase = type.toLowerCase() + const subtypeLowercase = subtype.toLowerCase() - async function dispatch ({ body }) { - const url = requestCurrentURL(request) - /** @type {import('../..').Agent} */ - const agent = fetchParams.controller.dispatcher + // 10. Let mimeType be a new MIME type record whose type + // is type, in ASCII lowercase, and subtype is subtype, + // in ASCII lowercase. + // https://mimesniff.spec.whatwg.org/#mime-type + const mimeType = { + type: typeLowercase, + subtype: subtypeLowercase, + /** @type {Map} */ + parameters: new Map(), + // https://mimesniff.spec.whatwg.org/#mime-type-essence + essence: `${typeLowercase}/${subtypeLowercase}` + } - return new Promise((resolve, reject) => agent.dispatch( - { - path: url.pathname + url.search, - origin: url.origin, - method: request.method, - body: fetchParams.controller.dispatcher.isMockActive ? request.body && (request.body.source || request.body.stream) : body, - headers: request.headersList.entries, - maxRedirections: 0, - upgrade: request.mode === 'websocket' ? 'websocket' : undefined - }, - { - body: null, - abort: null, + // 11. While position is not past the end of input: + while (position.position < input.length) { + // 1. Advance position by 1. (This skips past U+003B (;).) + position.position++ - onConnect (abort) { - // TODO (fix): Do we need connection here? - const { connection } = fetchParams.controller + // 2. Collect a sequence of code points that are HTTP + // whitespace from input given position. + collectASequenceOfCodePoints( + // https://fetch.spec.whatwg.org/#http-whitespace + char => HTTP_WHITESPACE_REGEX.test(char), + input, + position + ) - if (connection.destroyed) { - abort(new DOMException('The operation was aborted.', 'AbortError')) - } else { - fetchParams.controller.on('terminated', abort) - this.abort = connection.abort = abort - } - }, + // 3. Let parameterName be the result of collecting a + // sequence of code points that are not U+003B (;) + // or U+003D (=) from input, given position. + let parameterName = collectASequenceOfCodePoints( + (char) => char !== ';' && char !== '=', + input, + position + ) - onHeaders (status, headersList, resume, statusText) { - if (status < 200) { - return - } + // 4. Set parameterName to parameterName, in ASCII + // lowercase. + parameterName = parameterName.toLowerCase() - let codings = [] - let location = '' + // 5. If position is not past the end of input, then: + if (position.position < input.length) { + // 1. If the code point at position within input is + // U+003B (;), then continue. + if (input[position.position] === ';') { + continue + } - const headers = new Headers() - - // For H2, the headers are a plain JS object - // We distinguish between them and iterate accordingly - if (Array.isArray(headersList)) { - for (let n = 0; n < headersList.length; n += 2) { - const key = headersList[n + 0].toString('latin1') - const val = headersList[n + 1].toString('latin1') - if (key.toLowerCase() === 'content-encoding') { - // https://www.rfc-editor.org/rfc/rfc7231#section-3.1.2.1 - // "All content-coding values are case-insensitive..." - codings = val.toLowerCase().split(',').map((x) => x.trim()) - } else if (key.toLowerCase() === 'location') { - location = val - } + // 2. Advance position by 1. (This skips past U+003D (=).) + position.position++ + } - headers[kHeadersList].append(key, val) - } - } else { - const keys = Object.keys(headersList) - for (const key of keys) { - const val = headersList[key] - if (key.toLowerCase() === 'content-encoding') { - // https://www.rfc-editor.org/rfc/rfc7231#section-3.1.2.1 - // "All content-coding values are case-insensitive..." - codings = val.toLowerCase().split(',').map((x) => x.trim()).reverse() - } else if (key.toLowerCase() === 'location') { - location = val - } + // 6. If position is past the end of input, then break. + if (position.position > input.length) { + break + } - headers[kHeadersList].append(key, val) - } - } + // 7. Let parameterValue be null. + let parameterValue = null - this.body = new Readable({ read: resume }) + // 8. If the code point at position within input is + // U+0022 ("), then: + if (input[position.position] === '"') { + // 1. Set parameterValue to the result of collecting + // an HTTP quoted string from input, given position + // and the extract-value flag. + parameterValue = collectAnHTTPQuotedString(input, position, true) - const decoders = [] + // 2. Collect a sequence of code points that are not + // U+003B (;) from input, given position. + collectASequenceOfCodePointsFast( + ';', + input, + position + ) - const willFollow = request.redirect === 'follow' && - location && - redirectStatusSet.has(status) + // 9. Otherwise: + } else { + // 1. Set parameterValue to the result of collecting + // a sequence of code points that are not U+003B (;) + // from input, given position. + parameterValue = collectASequenceOfCodePointsFast( + ';', + input, + position + ) - // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding - if (request.method !== 'HEAD' && request.method !== 'CONNECT' && !nullBodyStatus.includes(status) && !willFollow) { - for (const coding of codings) { - // https://www.rfc-editor.org/rfc/rfc9112.html#section-7.2 - if (coding === 'x-gzip' || coding === 'gzip') { - decoders.push(zlib.createGunzip({ - // Be less strict when decoding compressed responses, since sometimes - // servers send slightly invalid responses that are still accepted - // by common browsers. - // Always using Z_SYNC_FLUSH is what cURL does. - flush: zlib.constants.Z_SYNC_FLUSH, - finishFlush: zlib.constants.Z_SYNC_FLUSH - })) - } else if (coding === 'deflate') { - decoders.push(zlib.createInflate()) - } else if (coding === 'br') { - decoders.push(zlib.createBrotliDecompress()) - } else { - decoders.length = 0 - break - } - } - } + // 2. Remove any trailing HTTP whitespace from parameterValue. + parameterValue = removeHTTPWhitespace(parameterValue, false, true) - resolve({ - status, - statusText, - headersList: headers[kHeadersList], - body: decoders.length - ? pipeline(this.body, ...decoders, () => { }) - : this.body.on('error', () => {}) - }) + // 3. If parameterValue is the empty string, then continue. + if (parameterValue.length === 0) { + continue + } + } - return true - }, + // 10. If all of the following are true + // - parameterName is not the empty string + // - parameterName solely contains HTTP token code points + // - parameterValue solely contains HTTP quoted-string token code points + // - mimeType’s parameters[parameterName] does not exist + // then set mimeType’s parameters[parameterName] to parameterValue. + if ( + parameterName.length !== 0 && + HTTP_TOKEN_CODEPOINTS.test(parameterName) && + (parameterValue.length === 0 || HTTP_QUOTED_STRING_TOKENS.test(parameterValue)) && + !mimeType.parameters.has(parameterName) + ) { + mimeType.parameters.set(parameterName, parameterValue) + } + } - onData (chunk) { - if (fetchParams.controller.dump) { - return - } + // 12. Return mimeType. + return mimeType +} - // 1. If one or more bytes have been transmitted from response’s - // message body, then: +// https://infra.spec.whatwg.org/#forgiving-base64-decode +/** @param {string} data */ +function forgivingBase64 (data) { + // 1. Remove all ASCII whitespace from data. + data = data.replace(ASCII_WHITESPACE_REPLACE_REGEX, '') // eslint-disable-line - // 1. Let bytes be the transmitted bytes. - const bytes = chunk + let dataLength = data.length + // 2. If data’s code point length divides by 4 leaving + // no remainder, then: + if (dataLength % 4 === 0) { + // 1. If data ends with one or two U+003D (=) code points, + // then remove them from data. + if (data.charCodeAt(dataLength - 1) === 0x003D) { + --dataLength + if (data.charCodeAt(dataLength - 1) === 0x003D) { + --dataLength + } + } + } - // 2. Let codings be the result of extracting header list values - // given `Content-Encoding` and response’s header list. - // See pullAlgorithm. + // 3. If data’s code point length divides by 4 leaving + // a remainder of 1, then return failure. + if (dataLength % 4 === 1) { + return 'failure' + } - // 3. Increase timingInfo’s encoded body size by bytes’s length. - timingInfo.encodedBodySize += bytes.byteLength + // 4. If data contains a code point that is not one of + // U+002B (+) + // U+002F (/) + // ASCII alphanumeric + // then return failure. + if (/[^+/0-9A-Za-z]/.test(data.length === dataLength ? data : data.substring(0, dataLength))) { + return 'failure' + } - // 4. See pullAlgorithm... + const buffer = Buffer.from(data, 'base64') + return new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength) +} - return this.body.push(bytes) - }, +// https://fetch.spec.whatwg.org/#collect-an-http-quoted-string +// tests: https://fetch.spec.whatwg.org/#example-http-quoted-string +/** + * @param {string} input + * @param {{ position: number }} position + * @param {boolean?} extractValue + */ +function collectAnHTTPQuotedString (input, position, extractValue) { + // 1. Let positionStart be position. + const positionStart = position.position - onComplete () { - if (this.abort) { - fetchParams.controller.off('terminated', this.abort) - } + // 2. Let value be the empty string. + let value = '' - fetchParams.controller.ended = true + // 3. Assert: the code point at position within input + // is U+0022 ("). + assert(input[position.position] === '"') - this.body.push(null) - }, + // 4. Advance position by 1. + position.position++ - onError (error) { - if (this.abort) { - fetchParams.controller.off('terminated', this.abort) - } + // 5. While true: + while (true) { + // 1. Append the result of collecting a sequence of code points + // that are not U+0022 (") or U+005C (\) from input, given + // position, to value. + value += collectASequenceOfCodePoints( + (char) => char !== '"' && char !== '\\', + input, + position + ) - this.body?.destroy(error) + // 2. If position is past the end of input, then break. + if (position.position >= input.length) { + break + } - fetchParams.controller.terminate(error) + // 3. Let quoteOrBackslash be the code point at position within + // input. + const quoteOrBackslash = input[position.position] - reject(error) - }, + // 4. Advance position by 1. + position.position++ - onUpgrade (status, headersList, socket) { - if (status !== 101) { - return - } + // 5. If quoteOrBackslash is U+005C (\), then: + if (quoteOrBackslash === '\\') { + // 1. If position is past the end of input, then append + // U+005C (\) to value and break. + if (position.position >= input.length) { + value += '\\' + break + } - const headers = new Headers() + // 2. Append the code point at position within input to value. + value += input[position.position] - for (let n = 0; n < headersList.length; n += 2) { - const key = headersList[n + 0].toString('latin1') - const val = headersList[n + 1].toString('latin1') + // 3. Advance position by 1. + position.position++ - headers[kHeadersList].append(key, val) - } + // 6. Otherwise: + } else { + // 1. Assert: quoteOrBackslash is U+0022 ("). + assert(quoteOrBackslash === '"') - resolve({ - status, - statusText: STATUS_CODES[status], - headersList: headers[kHeadersList], - socket - }) + // 2. Break. + break + } + } - return true - } - } - )) + // 6. If the extract-value flag is set, then return value. + if (extractValue) { + return value } -} -module.exports = { - fetch, - Fetch, - fetching, - finalizeAndReportTiming + // 7. Return the code points from positionStart to position, + // inclusive, within input. + return input.slice(positionStart, position.position) } +/** + * @see https://mimesniff.spec.whatwg.org/#serialize-a-mime-type + */ +function serializeAMimeType (mimeType) { + assert(mimeType !== 'failure') + const { parameters, essence } = mimeType -/***/ }), - -/***/ 4555: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -"use strict"; -/* globals AbortController */ - + // 1. Let serialization be the concatenation of mimeType’s + // type, U+002F (/), and mimeType’s subtype. + let serialization = essence + // 2. For each name → value of mimeType’s parameters: + for (let [name, value] of parameters.entries()) { + // 1. Append U+003B (;) to serialization. + serialization += ';' -const { extractBody, mixinBody, cloneBody } = __nccwpck_require__(1056) -const { Headers, fill: fillHeaders, HeadersList } = __nccwpck_require__(3640) -const { FinalizationRegistry } = __nccwpck_require__(199)() -const util = __nccwpck_require__(5069) -const { - isValidHTTPToken, - sameOrigin, - normalizeMethod, - makePolicyContainer, - normalizeMethodRecord -} = __nccwpck_require__(1612) -const { - forbiddenMethodsSet, - corsSafeListedMethodsSet, - referrerPolicy, - requestRedirect, - requestMode, - requestCredentials, - requestCache, - requestDuplex -} = __nccwpck_require__(3283) -const { kEnumerableProperty } = util -const { kHeaders, kSignal, kState, kGuard, kRealm } = __nccwpck_require__(2895) -const { webidl } = __nccwpck_require__(8201) -const { getGlobalOrigin } = __nccwpck_require__(4407) -const { URLSerializer } = __nccwpck_require__(4955) -const { kHeadersList, kConstruct } = __nccwpck_require__(1028) -const assert = __nccwpck_require__(2613) -const { getMaxListeners, setMaxListeners, getEventListeners, defaultMaxListeners } = __nccwpck_require__(4434) + // 2. Append name to serialization. + serialization += name -let TransformStream = globalThis.TransformStream + // 3. Append U+003D (=) to serialization. + serialization += '=' -const kAbortController = Symbol('abortController') + // 4. If value does not solely contain HTTP token code + // points or value is the empty string, then: + if (!HTTP_TOKEN_CODEPOINTS.test(value)) { + // 1. Precede each occurrence of U+0022 (") or + // U+005C (\) in value with U+005C (\). + value = value.replace(/(\\|")/g, '\\$1') -const requestFinalizer = new FinalizationRegistry(({ signal, abort }) => { - signal.removeEventListener('abort', abort) -}) + // 2. Prepend U+0022 (") to value. + value = '"' + value -// https://fetch.spec.whatwg.org/#request-class -class Request { - // https://fetch.spec.whatwg.org/#dom-request - constructor (input, init = {}) { - if (input === kConstruct) { - return + // 3. Append U+0022 (") to value. + value += '"' } - webidl.argumentLengthCheck(arguments, 1, { header: 'Request constructor' }) + // 5. Append value to serialization. + serialization += value + } - input = webidl.converters.RequestInfo(input) - init = webidl.converters.RequestInit(init) + // 3. Return serialization. + return serialization +} - // https://html.spec.whatwg.org/multipage/webappapis.html#environment-settings-object - this[kRealm] = { - settingsObject: { - baseUrl: getGlobalOrigin(), - get origin () { - return this.baseUrl?.origin - }, - policyContainer: makePolicyContainer() - } - } +/** + * @see https://fetch.spec.whatwg.org/#http-whitespace + * @param {number} char + */ +function isHTTPWhiteSpace (char) { + // "\r\n\t " + return char === 0x00d || char === 0x00a || char === 0x009 || char === 0x020 +} - // 1. Let request be null. - let request = null +/** + * @see https://fetch.spec.whatwg.org/#http-whitespace + * @param {string} str + * @param {boolean} [leading=true] + * @param {boolean} [trailing=true] + */ +function removeHTTPWhitespace (str, leading = true, trailing = true) { + return removeChars(str, leading, trailing, isHTTPWhiteSpace) +} - // 2. Let fallbackMode be null. - let fallbackMode = null +/** + * @see https://infra.spec.whatwg.org/#ascii-whitespace + * @param {number} char + */ +function isASCIIWhitespace (char) { + // "\r\n\t\f " + return char === 0x00d || char === 0x00a || char === 0x009 || char === 0x00c || char === 0x020 +} - // 3. Let baseURL be this’s relevant settings object’s API base URL. - const baseUrl = this[kRealm].settingsObject.baseUrl +/** + * @see https://infra.spec.whatwg.org/#strip-leading-and-trailing-ascii-whitespace + * @param {string} str + * @param {boolean} [leading=true] + * @param {boolean} [trailing=true] + */ +function removeASCIIWhitespace (str, leading = true, trailing = true) { + return removeChars(str, leading, trailing, isASCIIWhitespace) +} - // 4. Let signal be null. - let signal = null +/** + * @param {string} str + * @param {boolean} leading + * @param {boolean} trailing + * @param {(charCode: number) => boolean} predicate + * @returns + */ +function removeChars (str, leading, trailing, predicate) { + let lead = 0 + let trail = str.length - 1 - // 5. If input is a string, then: - if (typeof input === 'string') { - // 1. Let parsedURL be the result of parsing input with baseURL. - // 2. If parsedURL is failure, then throw a TypeError. - let parsedURL - try { - parsedURL = new URL(input, baseUrl) - } catch (err) { - throw new TypeError('Failed to parse URL from ' + input, { cause: err }) - } + if (leading) { + while (lead < str.length && predicate(str.charCodeAt(lead))) lead++ + } - // 3. If parsedURL includes credentials, then throw a TypeError. - if (parsedURL.username || parsedURL.password) { - throw new TypeError( - 'Request cannot be constructed from a URL that includes credentials: ' + - input - ) - } + if (trailing) { + while (trail > 0 && predicate(str.charCodeAt(trail))) trail-- + } - // 4. Set request to a new request whose URL is parsedURL. - request = makeRequest({ urlList: [parsedURL] }) + return lead === 0 && trail === str.length - 1 ? str : str.slice(lead, trail + 1) +} - // 5. Set fallbackMode to "cors". - fallbackMode = 'cors' - } else { - // 6. Otherwise: +/** + * @see https://infra.spec.whatwg.org/#isomorphic-decode + * @param {Uint8Array} input + * @returns {string} + */ +function isomorphicDecode (input) { + // 1. To isomorphic decode a byte sequence input, return a string whose code point + // length is equal to input’s length and whose code points have the same values + // as the values of input’s bytes, in the same order. + const length = input.length + if ((2 << 15) - 1 > length) { + return String.fromCharCode.apply(null, input) + } + let result = ''; let i = 0 + let addition = (2 << 15) - 1 + while (i < length) { + if (i + addition > length) { + addition = length - i + } + result += String.fromCharCode.apply(null, input.subarray(i, i += addition)) + } + return result +} - // 7. Assert: input is a Request object. - assert(input instanceof Request) +/** + * @see https://mimesniff.spec.whatwg.org/#minimize-a-supported-mime-type + * @param {Exclude, 'failure'>} mimeType + */ +function minimizeSupportedMimeType (mimeType) { + switch (mimeType.essence) { + case 'application/ecmascript': + case 'application/javascript': + case 'application/x-ecmascript': + case 'application/x-javascript': + case 'text/ecmascript': + case 'text/javascript': + case 'text/javascript1.0': + case 'text/javascript1.1': + case 'text/javascript1.2': + case 'text/javascript1.3': + case 'text/javascript1.4': + case 'text/javascript1.5': + case 'text/jscript': + case 'text/livescript': + case 'text/x-ecmascript': + case 'text/x-javascript': + // 1. If mimeType is a JavaScript MIME type, then return "text/javascript". + return 'text/javascript' + case 'application/json': + case 'text/json': + // 2. If mimeType is a JSON MIME type, then return "application/json". + return 'application/json' + case 'image/svg+xml': + // 3. If mimeType’s essence is "image/svg+xml", then return "image/svg+xml". + return 'image/svg+xml' + case 'text/xml': + case 'application/xml': + // 4. If mimeType is an XML MIME type, then return "application/xml". + return 'application/xml' + } - // 8. Set request to input’s request. - request = input[kState] + // 2. If mimeType is a JSON MIME type, then return "application/json". + if (mimeType.subtype.endsWith('+json')) { + return 'application/json' + } - // 9. Set signal to input’s signal. - signal = input[kSignal] - } + // 4. If mimeType is an XML MIME type, then return "application/xml". + if (mimeType.subtype.endsWith('+xml')) { + return 'application/xml' + } - // 7. Let origin be this’s relevant settings object’s origin. - const origin = this[kRealm].settingsObject.origin + // 5. If mimeType is supported by the user agent, then return mimeType’s essence. + // Technically, node doesn't support any mimetypes. - // 8. Let window be "client". - let window = 'client' + // 6. Return the empty string. + return '' +} - // 9. If request’s window is an environment settings object and its origin - // is same origin with origin, then set window to request’s window. - if ( - request.window?.constructor?.name === 'EnvironmentSettingsObject' && - sameOrigin(request.window, origin) - ) { - window = request.window - } +module.exports = { + dataURLProcessor, + URLSerializer, + collectASequenceOfCodePoints, + collectASequenceOfCodePointsFast, + stringPercentDecode, + parseMIMEType, + collectAnHTTPQuotedString, + serializeAMimeType, + removeChars, + removeHTTPWhitespace, + minimizeSupportedMimeType, + HTTP_TOKEN_CODEPOINTS, + isomorphicDecode +} - // 10. If init["window"] exists and is non-null, then throw a TypeError. - if (init.window != null) { - throw new TypeError(`'window' option '${window}' must be null`) - } - // 11. If init["window"] exists, then set window to "no-window". - if ('window' in init) { - window = 'no-window' - } +/***/ }), - // 12. Set request to a new request with the following properties: - request = makeRequest({ - // URL request’s URL. - // undici implementation note: this is set as the first item in request's urlList in makeRequest - // method request’s method. - method: request.method, - // header list A copy of request’s header list. - // undici implementation note: headersList is cloned in makeRequest - headersList: request.headersList, - // unsafe-request flag Set. - unsafeRequest: request.unsafeRequest, - // client This’s relevant settings object. - client: this[kRealm].settingsObject, - // window window. - window, - // priority request’s priority. - priority: request.priority, - // origin request’s origin. The propagation of the origin is only significant for navigation requests - // being handled by a service worker. In this scenario a request can have an origin that is different - // from the current client. - origin: request.origin, - // referrer request’s referrer. - referrer: request.referrer, - // referrer policy request’s referrer policy. - referrerPolicy: request.referrerPolicy, - // mode request’s mode. - mode: request.mode, - // credentials mode request’s credentials mode. - credentials: request.credentials, - // cache mode request’s cache mode. - cache: request.cache, - // redirect mode request’s redirect mode. - redirect: request.redirect, - // integrity metadata request’s integrity metadata. - integrity: request.integrity, - // keepalive request’s keepalive. - keepalive: request.keepalive, - // reload-navigation flag request’s reload-navigation flag. - reloadNavigation: request.reloadNavigation, - // history-navigation flag request’s history-navigation flag. - historyNavigation: request.historyNavigation, - // URL list A clone of request’s URL list. - urlList: [...request.urlList] - }) +/***/ 3823: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - const initHasKey = Object.keys(init).length !== 0 - // 13. If init is not empty, then: - if (initHasKey) { - // 1. If request’s mode is "navigate", then set it to "same-origin". - if (request.mode === 'navigate') { - request.mode = 'same-origin' - } - // 2. Unset request’s reload-navigation flag. - request.reloadNavigation = false +const { kConnected, kSize } = __nccwpck_require__(7417) - // 3. Unset request’s history-navigation flag. - request.historyNavigation = false +class CompatWeakRef { + constructor (value) { + this.value = value + } - // 4. Set request’s origin to "client". - request.origin = 'client' + deref () { + return this.value[kConnected] === 0 && this.value[kSize] === 0 + ? undefined + : this.value + } +} - // 5. Set request’s referrer to "client" - request.referrer = 'client' +class CompatFinalizer { + constructor (finalizer) { + this.finalizer = finalizer + } - // 6. Set request’s referrer policy to the empty string. - request.referrerPolicy = '' + register (dispatcher, key) { + if (dispatcher.on) { + dispatcher.on('disconnect', () => { + if (dispatcher[kConnected] === 0 && dispatcher[kSize] === 0) { + this.finalizer(key) + } + }) + } + } - // 7. Set request’s URL to request’s current URL. - request.url = request.urlList[request.urlList.length - 1] + unregister (key) {} +} - // 8. Set request’s URL list to « request’s URL ». - request.urlList = [request.url] +module.exports = function () { + // FIXME: remove workaround when the Node bug is backported to v18 + // https://github.com/nodejs/node/issues/49344#issuecomment-1741776308 + if (process.env.NODE_V8_COVERAGE && process.version.startsWith('v18')) { + process._rawDebug('Using compatibility WeakRef and FinalizationRegistry') + return { + WeakRef: CompatWeakRef, + FinalizationRegistry: CompatFinalizer } + } + return { WeakRef, FinalizationRegistry } +} - // 14. If init["referrer"] exists, then: - if (init.referrer !== undefined) { - // 1. Let referrer be init["referrer"]. - const referrer = init.referrer - // 2. If referrer is the empty string, then set request’s referrer to "no-referrer". - if (referrer === '') { - request.referrer = 'no-referrer' - } else { - // 1. Let parsedReferrer be the result of parsing referrer with - // baseURL. - // 2. If parsedReferrer is failure, then throw a TypeError. - let parsedReferrer - try { - parsedReferrer = new URL(referrer, baseUrl) - } catch (err) { - throw new TypeError(`Referrer "${referrer}" is not a valid URL.`, { cause: err }) - } +/***/ }), - // 3. If one of the following is true - // - parsedReferrer’s scheme is "about" and path is the string "client" - // - parsedReferrer’s origin is not same origin with origin - // then set request’s referrer to "client". - if ( - (parsedReferrer.protocol === 'about:' && parsedReferrer.hostname === 'client') || - (origin && !sameOrigin(parsedReferrer, this[kRealm].settingsObject.baseUrl)) - ) { - request.referrer = 'client' - } else { - // 4. Otherwise, set request’s referrer to parsedReferrer. - request.referrer = parsedReferrer - } - } - } +/***/ 3148: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - // 15. If init["referrerPolicy"] exists, then set request’s referrer policy - // to it. - if (init.referrerPolicy !== undefined) { - request.referrerPolicy = init.referrerPolicy - } - // 16. Let mode be init["mode"] if it exists, and fallbackMode otherwise. - let mode - if (init.mode !== undefined) { - mode = init.mode - } else { - mode = fallbackMode - } - // 17. If mode is "navigate", then throw a TypeError. - if (mode === 'navigate') { - throw webidl.errors.exception({ - header: 'Request constructor', - message: 'invalid request mode navigate.' - }) - } +const { Blob, File } = __nccwpck_require__(4573) +const { kState } = __nccwpck_require__(1445) +const { webidl } = __nccwpck_require__(4859) - // 18. If mode is non-null, set request’s mode to mode. - if (mode != null) { - request.mode = mode - } +// TODO(@KhafraDev): remove +class FileLike { + constructor (blobLike, fileName, options = {}) { + // TODO: argument idl type check - // 19. If init["credentials"] exists, then set request’s credentials mode - // to it. - if (init.credentials !== undefined) { - request.credentials = init.credentials - } + // The File constructor is invoked with two or three parameters, depending + // on whether the optional dictionary parameter is used. When the File() + // constructor is invoked, user agents must run the following steps: - // 18. If init["cache"] exists, then set request’s cache mode to it. - if (init.cache !== undefined) { - request.cache = init.cache - } + // 1. Let bytes be the result of processing blob parts given fileBits and + // options. - // 21. If request’s cache mode is "only-if-cached" and request’s mode is - // not "same-origin", then throw a TypeError. - if (request.cache === 'only-if-cached' && request.mode !== 'same-origin') { - throw new TypeError( - "'only-if-cached' can be set only with 'same-origin' mode" - ) - } + // 2. Let n be the fileName argument to the constructor. + const n = fileName - // 22. If init["redirect"] exists, then set request’s redirect mode to it. - if (init.redirect !== undefined) { - request.redirect = init.redirect - } + // 3. Process FilePropertyBag dictionary argument by running the following + // substeps: - // 23. If init["integrity"] exists, then set request’s integrity metadata to it. - if (init.integrity != null) { - request.integrity = String(init.integrity) - } + // 1. If the type member is provided and is not the empty string, let t + // be set to the type dictionary member. If t contains any characters + // outside the range U+0020 to U+007E, then set t to the empty string + // and return from these substeps. + // TODO + const t = options.type - // 24. If init["keepalive"] exists, then set request’s keepalive to it. - if (init.keepalive !== undefined) { - request.keepalive = Boolean(init.keepalive) + // 2. Convert every character in t to ASCII lowercase. + // TODO + + // 3. If the lastModified member is provided, let d be set to the + // lastModified dictionary member. If it is not provided, set d to the + // current date and time represented as the number of milliseconds since + // the Unix Epoch (which is the equivalent of Date.now() [ECMA-262]). + const d = options.lastModified ?? Date.now() + + // 4. Return a new File object F such that: + // F refers to the bytes byte sequence. + // F.size is set to the number of total bytes in bytes. + // F.name is set to n. + // F.type is set to t. + // F.lastModified is set to d. + + this[kState] = { + blobLike, + name: n, + type: t, + lastModified: d } + } - // 25. If init["method"] exists, then: - if (init.method !== undefined) { - // 1. Let method be init["method"]. - let method = init.method + stream (...args) { + webidl.brandCheck(this, FileLike) - // 2. If method is not a method or method is a forbidden method, then - // throw a TypeError. - if (!isValidHTTPToken(method)) { - throw new TypeError(`'${method}' is not a valid HTTP method.`) - } + return this[kState].blobLike.stream(...args) + } - if (forbiddenMethodsSet.has(method.toUpperCase())) { - throw new TypeError(`'${method}' HTTP method is unsupported.`) - } + arrayBuffer (...args) { + webidl.brandCheck(this, FileLike) - // 3. Normalize method. - method = normalizeMethodRecord[method] ?? normalizeMethod(method) + return this[kState].blobLike.arrayBuffer(...args) + } - // 4. Set request’s method to method. - request.method = method - } + slice (...args) { + webidl.brandCheck(this, FileLike) - // 26. If init["signal"] exists, then set signal to it. - if (init.signal !== undefined) { - signal = init.signal - } + return this[kState].blobLike.slice(...args) + } - // 27. Set this’s request to request. - this[kState] = request + text (...args) { + webidl.brandCheck(this, FileLike) - // 28. Set this’s signal to a new AbortSignal object with this’s relevant - // Realm. - // TODO: could this be simplified with AbortSignal.any - // (https://dom.spec.whatwg.org/#dom-abortsignal-any) - const ac = new AbortController() - this[kSignal] = ac.signal - this[kSignal][kRealm] = this[kRealm] + return this[kState].blobLike.text(...args) + } - // 29. If signal is not null, then make this’s signal follow signal. - if (signal != null) { - if ( - !signal || - typeof signal.aborted !== 'boolean' || - typeof signal.addEventListener !== 'function' - ) { - throw new TypeError( - "Failed to construct 'Request': member signal is not of type AbortSignal." - ) - } - - if (signal.aborted) { - ac.abort(signal.reason) - } else { - // Keep a strong ref to ac while request object - // is alive. This is needed to prevent AbortController - // from being prematurely garbage collected. - // See, https://github.com/nodejs/undici/issues/1926. - this[kAbortController] = ac - - const acRef = new WeakRef(ac) - const abort = function () { - const ac = acRef.deref() - if (ac !== undefined) { - ac.abort(this.reason) - } - } - - // Third-party AbortControllers may not work with these. - // See, https://github.com/nodejs/undici/pull/1910#issuecomment-1464495619. - try { - // If the max amount of listeners is equal to the default, increase it - // This is only available in node >= v19.9.0 - if (typeof getMaxListeners === 'function' && getMaxListeners(signal) === defaultMaxListeners) { - setMaxListeners(100, signal) - } else if (getEventListeners(signal, 'abort').length >= defaultMaxListeners) { - setMaxListeners(100, signal) - } - } catch {} + get size () { + webidl.brandCheck(this, FileLike) - util.addAbortListener(signal, abort) - requestFinalizer.register(ac, { signal, abort }) - } - } + return this[kState].blobLike.size + } - // 30. Set this’s headers to a new Headers object with this’s relevant - // Realm, whose header list is request’s header list and guard is - // "request". - this[kHeaders] = new Headers(kConstruct) - this[kHeaders][kHeadersList] = request.headersList - this[kHeaders][kGuard] = 'request' - this[kHeaders][kRealm] = this[kRealm] + get type () { + webidl.brandCheck(this, FileLike) - // 31. If this’s request’s mode is "no-cors", then: - if (mode === 'no-cors') { - // 1. If this’s request’s method is not a CORS-safelisted method, - // then throw a TypeError. - if (!corsSafeListedMethodsSet.has(request.method)) { - throw new TypeError( - `'${request.method} is unsupported in no-cors mode.` - ) - } + return this[kState].blobLike.type + } - // 2. Set this’s headers’s guard to "request-no-cors". - this[kHeaders][kGuard] = 'request-no-cors' - } + get name () { + webidl.brandCheck(this, FileLike) - // 32. If init is not empty, then: - if (initHasKey) { - /** @type {HeadersList} */ - const headersList = this[kHeaders][kHeadersList] - // 1. Let headers be a copy of this’s headers and its associated header - // list. - // 2. If init["headers"] exists, then set headers to init["headers"]. - const headers = init.headers !== undefined ? init.headers : new HeadersList(headersList) + return this[kState].name + } - // 3. Empty this’s headers’s header list. - headersList.clear() + get lastModified () { + webidl.brandCheck(this, FileLike) - // 4. If headers is a Headers object, then for each header in its header - // list, append header’s name/header’s value to this’s headers. - if (headers instanceof HeadersList) { - for (const [key, val] of headers) { - headersList.append(key, val) - } - // Note: Copy the `set-cookie` meta-data. - headersList.cookies = headers.cookies - } else { - // 5. Otherwise, fill this’s headers with headers. - fillHeaders(this[kHeaders], headers) - } - } + return this[kState].lastModified + } - // 33. Let inputBody be input’s request’s body if input is a Request - // object; otherwise null. - const inputBody = input instanceof Request ? input[kState].body : null + get [Symbol.toStringTag] () { + return 'File' + } +} - // 34. If either init["body"] exists and is non-null or inputBody is - // non-null, and request’s method is `GET` or `HEAD`, then throw a - // TypeError. - if ( - (init.body != null || inputBody != null) && - (request.method === 'GET' || request.method === 'HEAD') - ) { - throw new TypeError('Request with GET/HEAD method cannot have body.') - } +webidl.converters.Blob = webidl.interfaceConverter(Blob) - // 35. Let initBody be null. - let initBody = null +// If this function is moved to ./util.js, some tools (such as +// rollup) will warn about circular dependencies. See: +// https://github.com/nodejs/undici/issues/1629 +function isFileLike (object) { + return ( + (object instanceof File) || + ( + object && + (typeof object.stream === 'function' || + typeof object.arrayBuffer === 'function') && + object[Symbol.toStringTag] === 'File' + ) + ) +} - // 36. If init["body"] exists and is non-null, then: - if (init.body != null) { - // 1. Let Content-Type be null. - // 2. Set initBody and Content-Type to the result of extracting - // init["body"], with keepalive set to request’s keepalive. - const [extractedBody, contentType] = extractBody( - init.body, - request.keepalive - ) - initBody = extractedBody +module.exports = { FileLike, isFileLike } - // 3, If Content-Type is non-null and this’s headers’s header list does - // not contain `Content-Type`, then append `Content-Type`/Content-Type to - // this’s headers. - if (contentType && !this[kHeaders][kHeadersList].contains('content-type')) { - this[kHeaders].append('content-type', contentType) - } - } - // 37. Let inputOrInitBody be initBody if it is non-null; otherwise - // inputBody. - const inputOrInitBody = initBody ?? inputBody +/***/ }), - // 38. If inputOrInitBody is non-null and inputOrInitBody’s source is - // null, then: - if (inputOrInitBody != null && inputOrInitBody.source == null) { - // 1. If initBody is non-null and init["duplex"] does not exist, - // then throw a TypeError. - if (initBody != null && init.duplex == null) { - throw new TypeError('RequestInit: duplex option is required when sending a body.') - } +/***/ 8622: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - // 2. If this’s request’s mode is neither "same-origin" nor "cors", - // then throw a TypeError. - if (request.mode !== 'same-origin' && request.mode !== 'cors') { - throw new TypeError( - 'If request is made from ReadableStream, mode should be "same-origin" or "cors"' - ) - } - // 3. Set this’s request’s use-CORS-preflight flag. - request.useCORSPreflightFlag = true - } - // 39. Let finalBody be inputOrInitBody. - let finalBody = inputOrInitBody +const { isUSVString, bufferToLowerCasedHeaderName } = __nccwpck_require__(7234) +const { utf8DecodeBytes } = __nccwpck_require__(1046) +const { HTTP_TOKEN_CODEPOINTS, isomorphicDecode } = __nccwpck_require__(6406) +const { isFileLike } = __nccwpck_require__(3148) +const { makeEntry } = __nccwpck_require__(9411) +const assert = __nccwpck_require__(4589) +const { File: NodeFile } = __nccwpck_require__(4573) - // 40. If initBody is null and inputBody is non-null, then: - if (initBody == null && inputBody != null) { - // 1. If input is unusable, then throw a TypeError. - if (util.isDisturbed(inputBody.stream) || inputBody.stream.locked) { - throw new TypeError( - 'Cannot construct a Request with a Request object that has already been used.' - ) - } +const File = globalThis.File ?? NodeFile - // 2. Set finalBody to the result of creating a proxy for inputBody. - if (!TransformStream) { - TransformStream = (__nccwpck_require__(3774).TransformStream) - } +const formDataNameBuffer = Buffer.from('form-data; name="') +const filenameBuffer = Buffer.from('; filename') +const dd = Buffer.from('--') +const ddcrlf = Buffer.from('--\r\n') - // https://streams.spec.whatwg.org/#readablestream-create-a-proxy - const identityTransform = new TransformStream() - inputBody.stream.pipeThrough(identityTransform) - finalBody = { - source: inputBody.source, - length: inputBody.length, - stream: identityTransform.readable - } +/** + * @param {string} chars + */ +function isAsciiString (chars) { + for (let i = 0; i < chars.length; ++i) { + if ((chars.charCodeAt(i) & ~0x7F) !== 0) { + return false } - - // 41. Set this’s request’s body to finalBody. - this[kState].body = finalBody } + return true +} - // Returns request’s HTTP method, which is "GET" by default. - get method () { - webidl.brandCheck(this, Request) +/** + * @see https://andreubotella.github.io/multipart-form-data/#multipart-form-data-boundary + * @param {string} boundary + */ +function validateBoundary (boundary) { + const length = boundary.length - // The method getter steps are to return this’s request’s method. - return this[kState].method + // - its length is greater or equal to 27 and lesser or equal to 70, and + if (length < 27 || length > 70) { + return false } - // Returns the URL of request as a string. - get url () { - webidl.brandCheck(this, Request) + // - it is composed by bytes in the ranges 0x30 to 0x39, 0x41 to 0x5A, or + // 0x61 to 0x7A, inclusive (ASCII alphanumeric), or which are 0x27 ('), + // 0x2D (-) or 0x5F (_). + for (let i = 0; i < length; ++i) { + const cp = boundary.charCodeAt(i) - // The url getter steps are to return this’s request’s URL, serialized. - return URLSerializer(this[kState].url) + if (!( + (cp >= 0x30 && cp <= 0x39) || + (cp >= 0x41 && cp <= 0x5a) || + (cp >= 0x61 && cp <= 0x7a) || + cp === 0x27 || + cp === 0x2d || + cp === 0x5f + )) { + return false + } } - // Returns a Headers object consisting of the headers associated with request. - // Note that headers added in the network layer by the user agent will not - // be accounted for in this object, e.g., the "Host" header. - get headers () { - webidl.brandCheck(this, Request) + return true +} - // The headers getter steps are to return this’s headers. - return this[kHeaders] - } +/** + * @see https://andreubotella.github.io/multipart-form-data/#multipart-form-data-parser + * @param {Buffer} input + * @param {ReturnType} mimeType + */ +function multipartFormDataParser (input, mimeType) { + // 1. Assert: mimeType’s essence is "multipart/form-data". + assert(mimeType !== 'failure' && mimeType.essence === 'multipart/form-data') - // Returns the kind of resource requested by request, e.g., "document" - // or "script". - get destination () { - webidl.brandCheck(this, Request) + const boundaryString = mimeType.parameters.get('boundary') - // The destination getter are to return this’s request’s destination. - return this[kState].destination + // 2. If mimeType’s parameters["boundary"] does not exist, return failure. + // Otherwise, let boundary be the result of UTF-8 decoding mimeType’s + // parameters["boundary"]. + if (boundaryString === undefined) { + return 'failure' } - // Returns the referrer of request. Its value can be a same-origin URL if - // explicitly set in init, the empty string to indicate no referrer, and - // "about:client" when defaulting to the global’s default. This is used - // during fetching to determine the value of the `Referer` header of the - // request being made. - get referrer () { - webidl.brandCheck(this, Request) + const boundary = Buffer.from(`--${boundaryString}`, 'utf8') - // 1. If this’s request’s referrer is "no-referrer", then return the - // empty string. - if (this[kState].referrer === 'no-referrer') { - return '' - } + // 3. Let entry list be an empty entry list. + const entryList = [] - // 2. If this’s request’s referrer is "client", then return - // "about:client". - if (this[kState].referrer === 'client') { - return 'about:client' - } + // 4. Let position be a pointer to a byte in input, initially pointing at + // the first byte. + const position = { position: 0 } - // Return this’s request’s referrer, serialized. - return this[kState].referrer.toString() + // Note: undici addition, allows leading and trailing CRLFs. + while (input[position.position] === 0x0d && input[position.position + 1] === 0x0a) { + position.position += 2 } - // Returns the referrer policy associated with request. - // This is used during fetching to compute the value of the request’s - // referrer. - get referrerPolicy () { - webidl.brandCheck(this, Request) + let trailing = input.length - // The referrerPolicy getter steps are to return this’s request’s referrer policy. - return this[kState].referrerPolicy + while (input[trailing - 1] === 0x0a && input[trailing - 2] === 0x0d) { + trailing -= 2 } - // Returns the mode associated with request, which is a string indicating - // whether the request will use CORS, or will be restricted to same-origin - // URLs. - get mode () { - webidl.brandCheck(this, Request) - - // The mode getter steps are to return this’s request’s mode. - return this[kState].mode + if (trailing !== input.length) { + input = input.subarray(0, trailing) } - // Returns the credentials mode associated with request, - // which is a string indicating whether credentials will be sent with the - // request always, never, or only when sent to a same-origin URL. - get credentials () { - // The credentials getter steps are to return this’s request’s credentials mode. - return this[kState].credentials - } + // 5. While true: + while (true) { + // 5.1. If position points to a sequence of bytes starting with 0x2D 0x2D + // (`--`) followed by boundary, advance position by 2 + the length of + // boundary. Otherwise, return failure. + // Note: boundary is padded with 2 dashes already, no need to add 2. + if (input.subarray(position.position, position.position + boundary.length).equals(boundary)) { + position.position += boundary.length + } else { + return 'failure' + } - // Returns the cache mode associated with request, - // which is a string indicating how the request will - // interact with the browser’s cache when fetching. - get cache () { - webidl.brandCheck(this, Request) + // 5.2. If position points to the sequence of bytes 0x2D 0x2D 0x0D 0x0A + // (`--` followed by CR LF) followed by the end of input, return entry list. + // Note: a body does NOT need to end with CRLF. It can end with --. + if ( + (position.position === input.length - 2 && bufferStartsWith(input, dd, position)) || + (position.position === input.length - 4 && bufferStartsWith(input, ddcrlf, position)) + ) { + return entryList + } - // The cache getter steps are to return this’s request’s cache mode. - return this[kState].cache - } + // 5.3. If position does not point to a sequence of bytes starting with 0x0D + // 0x0A (CR LF), return failure. + if (input[position.position] !== 0x0d || input[position.position + 1] !== 0x0a) { + return 'failure' + } - // Returns the redirect mode associated with request, - // which is a string indicating how redirects for the - // request will be handled during fetching. A request - // will follow redirects by default. - get redirect () { - webidl.brandCheck(this, Request) + // 5.4. Advance position by 2. (This skips past the newline.) + position.position += 2 - // The redirect getter steps are to return this’s request’s redirect mode. - return this[kState].redirect - } + // 5.5. Let name, filename and contentType be the result of parsing + // multipart/form-data headers on input and position, if the result + // is not failure. Otherwise, return failure. + const result = parseMultipartFormDataHeaders(input, position) - // Returns request’s subresource integrity metadata, which is a - // cryptographic hash of the resource being fetched. Its value - // consists of multiple hashes separated by whitespace. [SRI] - get integrity () { - webidl.brandCheck(this, Request) + if (result === 'failure') { + return 'failure' + } - // The integrity getter steps are to return this’s request’s integrity - // metadata. - return this[kState].integrity - } + let { name, filename, contentType, encoding } = result - // Returns a boolean indicating whether or not request can outlive the - // global in which it was created. - get keepalive () { - webidl.brandCheck(this, Request) + // 5.6. Advance position by 2. (This skips past the empty line that marks + // the end of the headers.) + position.position += 2 - // The keepalive getter steps are to return this’s request’s keepalive. - return this[kState].keepalive - } + // 5.7. Let body be the empty byte sequence. + let body - // Returns a boolean indicating whether or not request is for a reload - // navigation. - get isReloadNavigation () { - webidl.brandCheck(this, Request) + // 5.8. Body loop: While position is not past the end of input: + // TODO: the steps here are completely wrong + { + const boundaryIndex = input.indexOf(boundary.subarray(2), position.position) - // The isReloadNavigation getter steps are to return true if this’s - // request’s reload-navigation flag is set; otherwise false. - return this[kState].reloadNavigation - } + if (boundaryIndex === -1) { + return 'failure' + } - // Returns a boolean indicating whether or not request is for a history - // navigation (a.k.a. back-foward navigation). - get isHistoryNavigation () { - webidl.brandCheck(this, Request) + body = input.subarray(position.position, boundaryIndex - 4) - // The isHistoryNavigation getter steps are to return true if this’s request’s - // history-navigation flag is set; otherwise false. - return this[kState].historyNavigation - } + position.position += body.length - // Returns the signal associated with request, which is an AbortSignal - // object indicating whether or not request has been aborted, and its - // abort event handler. - get signal () { - webidl.brandCheck(this, Request) + // Note: position must be advanced by the body's length before being + // decoded, otherwise the parsing will fail. + if (encoding === 'base64') { + body = Buffer.from(body.toString(), 'base64') + } + } - // The signal getter steps are to return this’s signal. - return this[kSignal] - } + // 5.9. If position does not point to a sequence of bytes starting with + // 0x0D 0x0A (CR LF), return failure. Otherwise, advance position by 2. + if (input[position.position] !== 0x0d || input[position.position + 1] !== 0x0a) { + return 'failure' + } else { + position.position += 2 + } - get body () { - webidl.brandCheck(this, Request) + // 5.10. If filename is not null: + let value - return this[kState].body ? this[kState].body.stream : null - } + if (filename !== null) { + // 5.10.1. If contentType is null, set contentType to "text/plain". + contentType ??= 'text/plain' - get bodyUsed () { - webidl.brandCheck(this, Request) + // 5.10.2. If contentType is not an ASCII string, set contentType to the empty string. - return !!this[kState].body && util.isDisturbed(this[kState].body.stream) - } + // Note: `buffer.isAscii` can be used at zero-cost, but converting a string to a buffer is a high overhead. + // Content-Type is a relatively small string, so it is faster to use `String#charCodeAt`. + if (!isAsciiString(contentType)) { + contentType = '' + } - get duplex () { - webidl.brandCheck(this, Request) + // 5.10.3. Let value be a new File object with name filename, type contentType, and body body. + value = new File([body], filename, { type: contentType }) + } else { + // 5.11. Otherwise: - return 'half' + // 5.11.1. Let value be the UTF-8 decoding without BOM of body. + value = utf8DecodeBytes(Buffer.from(body)) + } + + // 5.12. Assert: name is a scalar value string and value is either a scalar value string or a File object. + assert(isUSVString(name)) + assert((typeof value === 'string' && isUSVString(value)) || isFileLike(value)) + + // 5.13. Create an entry with name and value, and append it to entry list. + entryList.push(makeEntry(name, value, filename)) } +} - // Returns a clone of request. - clone () { - webidl.brandCheck(this, Request) +/** + * @see https://andreubotella.github.io/multipart-form-data/#parse-multipart-form-data-headers + * @param {Buffer} input + * @param {{ position: number }} position + */ +function parseMultipartFormDataHeaders (input, position) { + // 1. Let name, filename and contentType be null. + let name = null + let filename = null + let contentType = null + let encoding = null - // 1. If this is unusable, then throw a TypeError. - if (this.bodyUsed || this.body?.locked) { - throw new TypeError('unusable') + // 2. While true: + while (true) { + // 2.1. If position points to a sequence of bytes starting with 0x0D 0x0A (CR LF): + if (input[position.position] === 0x0d && input[position.position + 1] === 0x0a) { + // 2.1.1. If name is null, return failure. + if (name === null) { + return 'failure' + } + + // 2.1.2. Return name, filename and contentType. + return { name, filename, contentType, encoding } } - // 2. Let clonedRequest be the result of cloning this’s request. - const clonedRequest = cloneRequest(this[kState]) + // 2.2. Let header name be the result of collecting a sequence of bytes that are + // not 0x0A (LF), 0x0D (CR) or 0x3A (:), given position. + let headerName = collectASequenceOfBytes( + (char) => char !== 0x0a && char !== 0x0d && char !== 0x3a, + input, + position + ) - // 3. Let clonedRequestObject be the result of creating a Request object, - // given clonedRequest, this’s headers’s guard, and this’s relevant Realm. - const clonedRequestObject = new Request(kConstruct) - clonedRequestObject[kState] = clonedRequest - clonedRequestObject[kRealm] = this[kRealm] - clonedRequestObject[kHeaders] = new Headers(kConstruct) - clonedRequestObject[kHeaders][kHeadersList] = clonedRequest.headersList - clonedRequestObject[kHeaders][kGuard] = this[kHeaders][kGuard] - clonedRequestObject[kHeaders][kRealm] = this[kHeaders][kRealm] + // 2.3. Remove any HTTP tab or space bytes from the start or end of header name. + headerName = removeChars(headerName, true, true, (char) => char === 0x9 || char === 0x20) - // 4. Make clonedRequestObject’s signal follow this’s signal. - const ac = new AbortController() - if (this.signal.aborted) { - ac.abort(this.signal.reason) - } else { - util.addAbortListener( - this.signal, - () => { - ac.abort(this.signal.reason) - } - ) + // 2.4. If header name does not match the field-name token production, return failure. + if (!HTTP_TOKEN_CODEPOINTS.test(headerName.toString())) { + return 'failure' } - clonedRequestObject[kSignal] = ac.signal - // 4. Return clonedRequestObject. - return clonedRequestObject - } -} + // 2.5. If the byte at position is not 0x3A (:), return failure. + if (input[position.position] !== 0x3a) { + return 'failure' + } -mixinBody(Request) + // 2.6. Advance position by 1. + position.position++ -function makeRequest (init) { - // https://fetch.spec.whatwg.org/#requests - const request = { - method: 'GET', - localURLsOnly: false, - unsafeRequest: false, - body: null, - client: null, - reservedClient: null, - replacesClientId: '', - window: 'client', - keepalive: false, - serviceWorkers: 'all', - initiator: '', - destination: '', - priority: null, - origin: 'client', - policyContainer: 'client', - referrer: 'client', - referrerPolicy: '', - mode: 'no-cors', - useCORSPreflightFlag: false, - credentials: 'same-origin', - useCredentials: false, - cache: 'default', - redirect: 'follow', - integrity: '', - cryptoGraphicsNonceMetadata: '', - parserMetadata: '', - reloadNavigation: false, - historyNavigation: false, - userActivation: false, - taintedOrigin: false, - redirectCount: 0, - responseTainting: 'basic', - preventNoCacheCacheControlHeaderModification: false, - done: false, - timingAllowFailed: false, - ...init, - headersList: init.headersList - ? new HeadersList(init.headersList) - : new HeadersList() - } - request.url = request.urlList[0] - return request -} - -// https://fetch.spec.whatwg.org/#concept-request-clone -function cloneRequest (request) { - // To clone a request request, run these steps: + // 2.7. Collect a sequence of bytes that are HTTP tab or space bytes given position. + // (Do nothing with those bytes.) + collectASequenceOfBytes( + (char) => char === 0x20 || char === 0x09, + input, + position + ) - // 1. Let newRequest be a copy of request, except for its body. - const newRequest = makeRequest({ ...request, body: null }) + // 2.8. Byte-lowercase header name and switch on the result: + switch (bufferToLowerCasedHeaderName(headerName)) { + case 'content-disposition': { + // 1. Set name and filename to null. + name = filename = null - // 2. If request’s body is non-null, set newRequest’s body to the - // result of cloning request’s body. - if (request.body != null) { - newRequest.body = cloneBody(request.body) - } + // 2. If position does not point to a sequence of bytes starting with + // `form-data; name="`, return failure. + if (!bufferStartsWith(input, formDataNameBuffer, position)) { + return 'failure' + } - // 3. Return newRequest. - return newRequest -} + // 3. Advance position so it points at the byte after the next 0x22 (") + // byte (the one in the sequence of bytes matched above). + position.position += 17 -Object.defineProperties(Request.prototype, { - method: kEnumerableProperty, - url: kEnumerableProperty, - headers: kEnumerableProperty, - redirect: kEnumerableProperty, - clone: kEnumerableProperty, - signal: kEnumerableProperty, - duplex: kEnumerableProperty, - destination: kEnumerableProperty, - body: kEnumerableProperty, - bodyUsed: kEnumerableProperty, - isHistoryNavigation: kEnumerableProperty, - isReloadNavigation: kEnumerableProperty, - keepalive: kEnumerableProperty, - integrity: kEnumerableProperty, - cache: kEnumerableProperty, - credentials: kEnumerableProperty, - attribute: kEnumerableProperty, - referrerPolicy: kEnumerableProperty, - referrer: kEnumerableProperty, - mode: kEnumerableProperty, - [Symbol.toStringTag]: { - value: 'Request', - configurable: true - } -}) + // 4. Set name to the result of parsing a multipart/form-data name given + // input and position, if the result is not failure. Otherwise, return + // failure. + name = parseMultipartFormDataName(input, position) -webidl.converters.Request = webidl.interfaceConverter( - Request -) + if (name === null) { + return 'failure' + } -// https://fetch.spec.whatwg.org/#requestinfo -webidl.converters.RequestInfo = function (V) { - if (typeof V === 'string') { - return webidl.converters.USVString(V) - } + // 5. If position points to a sequence of bytes starting with `; filename="`: + if (bufferStartsWith(input, filenameBuffer, position)) { + // Note: undici also handles filename* + let check = position.position + filenameBuffer.length - if (V instanceof Request) { - return webidl.converters.Request(V) - } + if (input[check] === 0x2a) { + position.position += 1 + check += 1 + } - return webidl.converters.USVString(V) -} + if (input[check] !== 0x3d || input[check + 1] !== 0x22) { // =" + return 'failure' + } -webidl.converters.AbortSignal = webidl.interfaceConverter( - AbortSignal -) + // 1. Advance position so it points at the byte after the next 0x22 (") byte + // (the one in the sequence of bytes matched above). + position.position += 12 -// https://fetch.spec.whatwg.org/#requestinit -webidl.converters.RequestInit = webidl.dictionaryConverter([ - { - key: 'method', - converter: webidl.converters.ByteString - }, - { - key: 'headers', - converter: webidl.converters.HeadersInit - }, - { - key: 'body', - converter: webidl.nullableConverter( - webidl.converters.BodyInit - ) - }, - { - key: 'referrer', - converter: webidl.converters.USVString - }, - { - key: 'referrerPolicy', - converter: webidl.converters.DOMString, - // https://w3c.github.io/webappsec-referrer-policy/#referrer-policy - allowedValues: referrerPolicy - }, - { - key: 'mode', - converter: webidl.converters.DOMString, - // https://fetch.spec.whatwg.org/#concept-request-mode - allowedValues: requestMode - }, - { - key: 'credentials', - converter: webidl.converters.DOMString, - // https://fetch.spec.whatwg.org/#requestcredentials - allowedValues: requestCredentials - }, - { - key: 'cache', - converter: webidl.converters.DOMString, - // https://fetch.spec.whatwg.org/#requestcache - allowedValues: requestCache - }, - { - key: 'redirect', - converter: webidl.converters.DOMString, - // https://fetch.spec.whatwg.org/#requestredirect - allowedValues: requestRedirect - }, - { - key: 'integrity', - converter: webidl.converters.DOMString - }, - { - key: 'keepalive', - converter: webidl.converters.boolean - }, - { - key: 'signal', - converter: webidl.nullableConverter( - (signal) => webidl.converters.AbortSignal( - signal, - { strict: false } - ) - ) - }, - { - key: 'window', - converter: webidl.converters.any - }, - { - key: 'duplex', - converter: webidl.converters.DOMString, - allowedValues: requestDuplex - } -]) + // 2. Set filename to the result of parsing a multipart/form-data name given + // input and position, if the result is not failure. Otherwise, return failure. + filename = parseMultipartFormDataName(input, position) -module.exports = { Request, makeRequest } + if (filename === null) { + return 'failure' + } + } + break + } + case 'content-type': { + // 1. Let header value be the result of collecting a sequence of bytes that are + // not 0x0A (LF) or 0x0D (CR), given position. + let headerValue = collectASequenceOfBytes( + (char) => char !== 0x0a && char !== 0x0d, + input, + position + ) -/***/ }), + // 2. Remove any HTTP tab or space bytes from the end of header value. + headerValue = removeChars(headerValue, false, true, (char) => char === 0x9 || char === 0x20) -/***/ 5743: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // 3. Set contentType to the isomorphic decoding of header value. + contentType = isomorphicDecode(headerValue) -"use strict"; + break + } + case 'content-transfer-encoding': { + let headerValue = collectASequenceOfBytes( + (char) => char !== 0x0a && char !== 0x0d, + input, + position + ) + headerValue = removeChars(headerValue, false, true, (char) => char === 0x9 || char === 0x20) -const { Headers, HeadersList, fill } = __nccwpck_require__(3640) -const { extractBody, cloneBody, mixinBody } = __nccwpck_require__(1056) -const util = __nccwpck_require__(5069) -const { kEnumerableProperty } = util -const { - isValidReasonPhrase, - isCancelled, - isAborted, - isBlobLike, - serializeJavascriptValueToJSONString, - isErrorLike, - isomorphicEncode -} = __nccwpck_require__(1612) -const { - redirectStatusSet, - nullBodyStatus, - DOMException -} = __nccwpck_require__(3283) -const { kState, kHeaders, kGuard, kRealm } = __nccwpck_require__(2895) -const { webidl } = __nccwpck_require__(8201) -const { FormData } = __nccwpck_require__(322) -const { getGlobalOrigin } = __nccwpck_require__(4407) -const { URLSerializer } = __nccwpck_require__(4955) -const { kHeadersList, kConstruct } = __nccwpck_require__(1028) -const assert = __nccwpck_require__(2613) -const { types } = __nccwpck_require__(9023) - -const ReadableStream = globalThis.ReadableStream || (__nccwpck_require__(3774).ReadableStream) -const textEncoder = new TextEncoder('utf-8') + encoding = isomorphicDecode(headerValue) -// https://fetch.spec.whatwg.org/#response-class -class Response { - // Creates network error Response. - static error () { - // TODO - const relevantRealm = { settingsObject: {} } + break + } + default: { + // Collect a sequence of bytes that are not 0x0A (LF) or 0x0D (CR), given position. + // (Do nothing with those bytes.) + collectASequenceOfBytes( + (char) => char !== 0x0a && char !== 0x0d, + input, + position + ) + } + } - // The static error() method steps are to return the result of creating a - // Response object, given a new network error, "immutable", and this’s - // relevant Realm. - const responseObject = new Response() - responseObject[kState] = makeNetworkError() - responseObject[kRealm] = relevantRealm - responseObject[kHeaders][kHeadersList] = responseObject[kState].headersList - responseObject[kHeaders][kGuard] = 'immutable' - responseObject[kHeaders][kRealm] = relevantRealm - return responseObject + // 2.9. If position does not point to a sequence of bytes starting with 0x0D 0x0A + // (CR LF), return failure. Otherwise, advance position by 2 (past the newline). + if (input[position.position] !== 0x0d && input[position.position + 1] !== 0x0a) { + return 'failure' + } else { + position.position += 2 + } } +} - // https://fetch.spec.whatwg.org/#dom-response-json - static json (data, init = {}) { - webidl.argumentLengthCheck(arguments, 1, { header: 'Response.json' }) +/** + * @see https://andreubotella.github.io/multipart-form-data/#parse-a-multipart-form-data-name + * @param {Buffer} input + * @param {{ position: number }} position + */ +function parseMultipartFormDataName (input, position) { + // 1. Assert: The byte at (position - 1) is 0x22 ("). + assert(input[position.position - 1] === 0x22) - if (init !== null) { - init = webidl.converters.ResponseInit(init) - } + // 2. Let name be the result of collecting a sequence of bytes that are not 0x0A (LF), 0x0D (CR) or 0x22 ("), given position. + /** @type {string | Buffer} */ + let name = collectASequenceOfBytes( + (char) => char !== 0x0a && char !== 0x0d && char !== 0x22, + input, + position + ) - // 1. Let bytes the result of running serialize a JavaScript value to JSON bytes on data. - const bytes = textEncoder.encode( - serializeJavascriptValueToJSONString(data) - ) + // 3. If the byte at position is not 0x22 ("), return failure. Otherwise, advance position by 1. + if (input[position.position] !== 0x22) { + return null // name could be 'failure' + } else { + position.position++ + } - // 2. Let body be the result of extracting bytes. - const body = extractBody(bytes) + // 4. Replace any occurrence of the following subsequences in name with the given byte: + // - `%0A`: 0x0A (LF) + // - `%0D`: 0x0D (CR) + // - `%22`: 0x22 (") + name = new TextDecoder().decode(name) + .replace(/%0A/ig, '\n') + .replace(/%0D/ig, '\r') + .replace(/%22/g, '"') - // 3. Let responseObject be the result of creating a Response object, given a new response, - // "response", and this’s relevant Realm. - const relevantRealm = { settingsObject: {} } - const responseObject = new Response() - responseObject[kRealm] = relevantRealm - responseObject[kHeaders][kGuard] = 'response' - responseObject[kHeaders][kRealm] = relevantRealm + // 5. Return the UTF-8 decoding without BOM of name. + return name +} - // 4. Perform initialize a response given responseObject, init, and (body, "application/json"). - initializeResponse(responseObject, init, { body: body[0], type: 'application/json' }) +/** + * @param {(char: number) => boolean} condition + * @param {Buffer} input + * @param {{ position: number }} position + */ +function collectASequenceOfBytes (condition, input, position) { + let start = position.position - // 5. Return responseObject. - return responseObject + while (start < input.length && condition(input[start])) { + ++start } - // Creates a redirect Response that redirects to url with status status. - static redirect (url, status = 302) { - const relevantRealm = { settingsObject: {} } + return input.subarray(position.position, (position.position = start)) +} - webidl.argumentLengthCheck(arguments, 1, { header: 'Response.redirect' }) +/** + * @param {Buffer} buf + * @param {boolean} leading + * @param {boolean} trailing + * @param {(charCode: number) => boolean} predicate + * @returns {Buffer} + */ +function removeChars (buf, leading, trailing, predicate) { + let lead = 0 + let trail = buf.length - 1 - url = webidl.converters.USVString(url) - status = webidl.converters['unsigned short'](status) + if (leading) { + while (lead < buf.length && predicate(buf[lead])) lead++ + } - // 1. Let parsedURL be the result of parsing url with current settings - // object’s API base URL. - // 2. If parsedURL is failure, then throw a TypeError. - // TODO: base-URL? - let parsedURL - try { - parsedURL = new URL(url, getGlobalOrigin()) - } catch (err) { - throw Object.assign(new TypeError('Failed to parse URL from ' + url), { - cause: err - }) - } + if (trailing) { + while (trail > 0 && predicate(buf[trail])) trail-- + } - // 3. If status is not a redirect status, then throw a RangeError. - if (!redirectStatusSet.has(status)) { - throw new RangeError('Invalid status code ' + status) - } + return lead === 0 && trail === buf.length - 1 ? buf : buf.subarray(lead, trail + 1) +} - // 4. Let responseObject be the result of creating a Response object, - // given a new response, "immutable", and this’s relevant Realm. - const responseObject = new Response() - responseObject[kRealm] = relevantRealm - responseObject[kHeaders][kGuard] = 'immutable' - responseObject[kHeaders][kRealm] = relevantRealm +/** + * Checks if {@param buffer} starts with {@param start} + * @param {Buffer} buffer + * @param {Buffer} start + * @param {{ position: number }} position + */ +function bufferStartsWith (buffer, start, position) { + if (buffer.length < start.length) { + return false + } - // 5. Set responseObject’s response’s status to status. - responseObject[kState].status = status + for (let i = 0; i < start.length; i++) { + if (start[i] !== buffer[position.position + i]) { + return false + } + } - // 6. Let value be parsedURL, serialized and isomorphic encoded. - const value = isomorphicEncode(URLSerializer(parsedURL)) + return true +} - // 7. Append `Location`/value to responseObject’s response’s header list. - responseObject[kState].headersList.append('location', value) +module.exports = { + multipartFormDataParser, + validateBoundary +} - // 8. Return responseObject. - return responseObject - } - // https://fetch.spec.whatwg.org/#dom-response - constructor (body = null, init = {}) { - if (body !== null) { - body = webidl.converters.BodyInit(body) - } +/***/ }), - init = webidl.converters.ResponseInit(init) +/***/ 9411: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - // TODO - this[kRealm] = { settingsObject: {} } - // 1. Set this’s response to a new response. - this[kState] = makeResponse({}) - // 2. Set this’s headers to a new Headers object with this’s relevant - // Realm, whose header list is this’s response’s header list and guard - // is "response". - this[kHeaders] = new Headers(kConstruct) - this[kHeaders][kGuard] = 'response' - this[kHeaders][kHeadersList] = this[kState].headersList - this[kHeaders][kRealm] = this[kRealm] +const { isBlobLike, iteratorMixin } = __nccwpck_require__(1046) +const { kState } = __nccwpck_require__(1445) +const { kEnumerableProperty } = __nccwpck_require__(7234) +const { FileLike, isFileLike } = __nccwpck_require__(3148) +const { webidl } = __nccwpck_require__(4859) +const { File: NativeFile } = __nccwpck_require__(4573) +const nodeUtil = __nccwpck_require__(7975) - // 3. Let bodyWithType be null. - let bodyWithType = null +/** @type {globalThis['File']} */ +const File = globalThis.File ?? NativeFile - // 4. If body is non-null, then set bodyWithType to the result of extracting body. - if (body != null) { - const [extractedBody, type] = extractBody(body) - bodyWithType = { body: extractedBody, type } +// https://xhr.spec.whatwg.org/#formdata +class FormData { + constructor (form) { + webidl.util.markAsUncloneable(this) + + if (form !== undefined) { + throw webidl.errors.conversionFailed({ + prefix: 'FormData constructor', + argument: 'Argument 1', + types: ['undefined'] + }) } - // 5. Perform initialize a response given this, init, and bodyWithType. - initializeResponse(this, init, bodyWithType) + this[kState] = [] } - // Returns response’s type, e.g., "cors". - get type () { - webidl.brandCheck(this, Response) + append (name, value, filename = undefined) { + webidl.brandCheck(this, FormData) - // The type getter steps are to return this’s response’s type. - return this[kState].type - } + const prefix = 'FormData.append' + webidl.argumentLengthCheck(arguments, 2, prefix) - // Returns response’s URL, if it has one; otherwise the empty string. - get url () { - webidl.brandCheck(this, Response) + if (arguments.length === 3 && !isBlobLike(value)) { + throw new TypeError( + "Failed to execute 'append' on 'FormData': parameter 2 is not of type 'Blob'" + ) + } - const urlList = this[kState].urlList + // 1. Let value be value if given; otherwise blobValue. - // The url getter steps are to return the empty string if this’s - // response’s URL is null; otherwise this’s response’s URL, - // serialized with exclude fragment set to true. - const url = urlList[urlList.length - 1] ?? null + name = webidl.converters.USVString(name, prefix, 'name') + value = isBlobLike(value) + ? webidl.converters.Blob(value, prefix, 'value', { strict: false }) + : webidl.converters.USVString(value, prefix, 'value') + filename = arguments.length === 3 + ? webidl.converters.USVString(filename, prefix, 'filename') + : undefined - if (url === null) { - return '' - } + // 2. Let entry be the result of creating an entry with + // name, value, and filename if given. + const entry = makeEntry(name, value, filename) - return URLSerializer(url, true) + // 3. Append entry to this’s entry list. + this[kState].push(entry) } - // Returns whether response was obtained through a redirect. - get redirected () { - webidl.brandCheck(this, Response) + delete (name) { + webidl.brandCheck(this, FormData) - // The redirected getter steps are to return true if this’s response’s URL - // list has more than one item; otherwise false. - return this[kState].urlList.length > 1 - } + const prefix = 'FormData.delete' + webidl.argumentLengthCheck(arguments, 1, prefix) - // Returns response’s status. - get status () { - webidl.brandCheck(this, Response) + name = webidl.converters.USVString(name, prefix, 'name') - // The status getter steps are to return this’s response’s status. - return this[kState].status + // The delete(name) method steps are to remove all entries whose name + // is name from this’s entry list. + this[kState] = this[kState].filter(entry => entry.name !== name) } - // Returns whether response’s status is an ok status. - get ok () { - webidl.brandCheck(this, Response) + get (name) { + webidl.brandCheck(this, FormData) - // The ok getter steps are to return true if this’s response’s status is an - // ok status; otherwise false. - return this[kState].status >= 200 && this[kState].status <= 299 - } + const prefix = 'FormData.get' + webidl.argumentLengthCheck(arguments, 1, prefix) - // Returns response’s status message. - get statusText () { - webidl.brandCheck(this, Response) + name = webidl.converters.USVString(name, prefix, 'name') - // The statusText getter steps are to return this’s response’s status - // message. - return this[kState].statusText + // 1. If there is no entry whose name is name in this’s entry list, + // then return null. + const idx = this[kState].findIndex((entry) => entry.name === name) + if (idx === -1) { + return null + } + + // 2. Return the value of the first entry whose name is name from + // this’s entry list. + return this[kState][idx].value } - // Returns response’s headers as Headers. - get headers () { - webidl.brandCheck(this, Response) + getAll (name) { + webidl.brandCheck(this, FormData) - // The headers getter steps are to return this’s headers. - return this[kHeaders] - } + const prefix = 'FormData.getAll' + webidl.argumentLengthCheck(arguments, 1, prefix) - get body () { - webidl.brandCheck(this, Response) + name = webidl.converters.USVString(name, prefix, 'name') - return this[kState].body ? this[kState].body.stream : null + // 1. If there is no entry whose name is name in this’s entry list, + // then return the empty list. + // 2. Return the values of all entries whose name is name, in order, + // from this’s entry list. + return this[kState] + .filter((entry) => entry.name === name) + .map((entry) => entry.value) } - get bodyUsed () { - webidl.brandCheck(this, Response) + has (name) { + webidl.brandCheck(this, FormData) - return !!this[kState].body && util.isDisturbed(this[kState].body.stream) + const prefix = 'FormData.has' + webidl.argumentLengthCheck(arguments, 1, prefix) + + name = webidl.converters.USVString(name, prefix, 'name') + + // The has(name) method steps are to return true if there is an entry + // whose name is name in this’s entry list; otherwise false. + return this[kState].findIndex((entry) => entry.name === name) !== -1 } - // Returns a clone of response. - clone () { - webidl.brandCheck(this, Response) + set (name, value, filename = undefined) { + webidl.brandCheck(this, FormData) - // 1. If this is unusable, then throw a TypeError. - if (this.bodyUsed || (this.body && this.body.locked)) { - throw webidl.errors.exception({ - header: 'Response.clone', - message: 'Body has already been consumed.' - }) - } + const prefix = 'FormData.set' + webidl.argumentLengthCheck(arguments, 2, prefix) - // 2. Let clonedResponse be the result of cloning this’s response. - const clonedResponse = cloneResponse(this[kState]) + if (arguments.length === 3 && !isBlobLike(value)) { + throw new TypeError( + "Failed to execute 'set' on 'FormData': parameter 2 is not of type 'Blob'" + ) + } - // 3. Return the result of creating a Response object, given - // clonedResponse, this’s headers’s guard, and this’s relevant Realm. - const clonedResponseObject = new Response() - clonedResponseObject[kState] = clonedResponse - clonedResponseObject[kRealm] = this[kRealm] - clonedResponseObject[kHeaders][kHeadersList] = clonedResponse.headersList - clonedResponseObject[kHeaders][kGuard] = this[kHeaders][kGuard] - clonedResponseObject[kHeaders][kRealm] = this[kHeaders][kRealm] + // The set(name, value) and set(name, blobValue, filename) method steps + // are: - return clonedResponseObject - } -} + // 1. Let value be value if given; otherwise blobValue. -mixinBody(Response) + name = webidl.converters.USVString(name, prefix, 'name') + value = isBlobLike(value) + ? webidl.converters.Blob(value, prefix, 'name', { strict: false }) + : webidl.converters.USVString(value, prefix, 'name') + filename = arguments.length === 3 + ? webidl.converters.USVString(filename, prefix, 'name') + : undefined -Object.defineProperties(Response.prototype, { - type: kEnumerableProperty, - url: kEnumerableProperty, - status: kEnumerableProperty, - ok: kEnumerableProperty, - redirected: kEnumerableProperty, - statusText: kEnumerableProperty, - headers: kEnumerableProperty, - clone: kEnumerableProperty, - body: kEnumerableProperty, - bodyUsed: kEnumerableProperty, - [Symbol.toStringTag]: { - value: 'Response', - configurable: true - } -}) - -Object.defineProperties(Response, { - json: kEnumerableProperty, - redirect: kEnumerableProperty, - error: kEnumerableProperty -}) - -// https://fetch.spec.whatwg.org/#concept-response-clone -function cloneResponse (response) { - // To clone a response response, run these steps: - - // 1. If response is a filtered response, then return a new identical - // filtered response whose internal response is a clone of response’s - // internal response. - if (response.internalResponse) { - return filterResponse( - cloneResponse(response.internalResponse), - response.type - ) - } - - // 2. Let newResponse be a copy of response, except for its body. - const newResponse = makeResponse({ ...response, body: null }) - - // 3. If response’s body is non-null, then set newResponse’s body to the - // result of cloning response’s body. - if (response.body != null) { - newResponse.body = cloneBody(response.body) - } - - // 4. Return newResponse. - return newResponse -} - -function makeResponse (init) { - return { - aborted: false, - rangeRequested: false, - timingAllowPassed: false, - requestIncludesCredentials: false, - type: 'default', - status: 200, - timingInfo: null, - cacheState: '', - statusText: '', - ...init, - headersList: init.headersList - ? new HeadersList(init.headersList) - : new HeadersList(), - urlList: init.urlList ? [...init.urlList] : [] - } -} - -function makeNetworkError (reason) { - const isError = isErrorLike(reason) - return makeResponse({ - type: 'error', - status: 0, - error: isError - ? reason - : new Error(reason ? String(reason) : reason), - aborted: reason && reason.name === 'AbortError' - }) -} - -function makeFilteredResponse (response, state) { - state = { - internalResponse: response, - ...state - } + // 2. Let entry be the result of creating an entry with name, value, and + // filename if given. + const entry = makeEntry(name, value, filename) - return new Proxy(response, { - get (target, p) { - return p in state ? state[p] : target[p] - }, - set (target, p, value) { - assert(!(p in state)) - target[p] = value - return true + // 3. If there are entries in this’s entry list whose name is name, then + // replace the first such entry with entry and remove the others. + const idx = this[kState].findIndex((entry) => entry.name === name) + if (idx !== -1) { + this[kState] = [ + ...this[kState].slice(0, idx), + entry, + ...this[kState].slice(idx + 1).filter((entry) => entry.name !== name) + ] + } else { + // 4. Otherwise, append entry to this’s entry list. + this[kState].push(entry) } - }) -} + } -// https://fetch.spec.whatwg.org/#concept-filtered-response -function filterResponse (response, type) { - // Set response to the following filtered response with response as its - // internal response, depending on request’s response tainting: - if (type === 'basic') { - // A basic filtered response is a filtered response whose type is "basic" - // and header list excludes any headers in internal response’s header list - // whose name is a forbidden response-header name. + [nodeUtil.inspect.custom] (depth, options) { + const state = this[kState].reduce((a, b) => { + if (a[b.name]) { + if (Array.isArray(a[b.name])) { + a[b.name].push(b.value) + } else { + a[b.name] = [a[b.name], b.value] + } + } else { + a[b.name] = b.value + } - // Note: undici does not implement forbidden response-header names - return makeFilteredResponse(response, { - type: 'basic', - headersList: response.headersList - }) - } else if (type === 'cors') { - // A CORS filtered response is a filtered response whose type is "cors" - // and header list excludes any headers in internal response’s header - // list whose name is not a CORS-safelisted response-header name, given - // internal response’s CORS-exposed header-name list. + return a + }, { __proto__: null }) - // Note: undici does not implement CORS-safelisted response-header names - return makeFilteredResponse(response, { - type: 'cors', - headersList: response.headersList - }) - } else if (type === 'opaque') { - // An opaque filtered response is a filtered response whose type is - // "opaque", URL list is the empty list, status is 0, status message - // is the empty byte sequence, header list is empty, and body is null. + options.depth ??= depth + options.colors ??= true - return makeFilteredResponse(response, { - type: 'opaque', - urlList: Object.freeze([]), - status: 0, - statusText: '', - body: null - }) - } else if (type === 'opaqueredirect') { - // An opaque-redirect filtered response is a filtered response whose type - // is "opaqueredirect", status is 0, status message is the empty byte - // sequence, header list is empty, and body is null. + const output = nodeUtil.formatWithOptions(options, state) - return makeFilteredResponse(response, { - type: 'opaqueredirect', - status: 0, - statusText: '', - headersList: [], - body: null - }) - } else { - assert(false) + // remove [Object null prototype] + return `FormData ${output.slice(output.indexOf(']') + 2)}` } } -// https://fetch.spec.whatwg.org/#appropriate-network-error -function makeAppropriateNetworkError (fetchParams, err = null) { - // 1. Assert: fetchParams is canceled. - assert(isCancelled(fetchParams)) - - // 2. Return an aborted network error if fetchParams is aborted; - // otherwise return a network error. - return isAborted(fetchParams) - ? makeNetworkError(Object.assign(new DOMException('The operation was aborted.', 'AbortError'), { cause: err })) - : makeNetworkError(Object.assign(new DOMException('Request was cancelled.'), { cause: err })) -} - -// https://whatpr.org/fetch/1392.html#initialize-a-response -function initializeResponse (response, init, body) { - // 1. If init["status"] is not in the range 200 to 599, inclusive, then - // throw a RangeError. - if (init.status !== null && (init.status < 200 || init.status > 599)) { - throw new RangeError('init["status"] must be in the range of 200 to 599, inclusive.') - } - - // 2. If init["statusText"] does not match the reason-phrase token production, - // then throw a TypeError. - if ('statusText' in init && init.statusText != null) { - // See, https://datatracker.ietf.org/doc/html/rfc7230#section-3.1.2: - // reason-phrase = *( HTAB / SP / VCHAR / obs-text ) - if (!isValidReasonPhrase(String(init.statusText))) { - throw new TypeError('Invalid statusText') - } - } +iteratorMixin('FormData', FormData, kState, 'name', 'value') - // 3. Set response’s response’s status to init["status"]. - if ('status' in init && init.status != null) { - response[kState].status = init.status +Object.defineProperties(FormData.prototype, { + append: kEnumerableProperty, + delete: kEnumerableProperty, + get: kEnumerableProperty, + getAll: kEnumerableProperty, + has: kEnumerableProperty, + set: kEnumerableProperty, + [Symbol.toStringTag]: { + value: 'FormData', + configurable: true } +}) - // 4. Set response’s response’s status message to init["statusText"]. - if ('statusText' in init && init.statusText != null) { - response[kState].statusText = init.statusText - } +/** + * @see https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#create-an-entry + * @param {string} name + * @param {string|Blob} value + * @param {?string} filename + * @returns + */ +function makeEntry (name, value, filename) { + // 1. Set name to the result of converting name into a scalar value string. + // Note: This operation was done by the webidl converter USVString. - // 5. If init["headers"] exists, then fill response’s headers with init["headers"]. - if ('headers' in init && init.headers != null) { - fill(response[kHeaders], init.headers) - } + // 2. If value is a string, then set value to the result of converting + // value into a scalar value string. + if (typeof value === 'string') { + // Note: This operation was done by the webidl converter USVString. + } else { + // 3. Otherwise: - // 6. If body was given, then: - if (body) { - // 1. If response's status is a null body status, then throw a TypeError. - if (nullBodyStatus.includes(response.status)) { - throw webidl.errors.exception({ - header: 'Response constructor', - message: 'Invalid response status code ' + response.status - }) + // 1. If value is not a File object, then set value to a new File object, + // representing the same bytes, whose name attribute value is "blob" + if (!isFileLike(value)) { + value = value instanceof Blob + ? new File([value], 'blob', { type: value.type }) + : new FileLike(value, 'blob', { type: value.type }) } - // 2. Set response's body to body's body. - response[kState].body = body.body + // 2. If filename is given, then set value to a new File object, + // representing the same bytes, whose name attribute is filename. + if (filename !== undefined) { + /** @type {FilePropertyBag} */ + const options = { + type: value.type, + lastModified: value.lastModified + } - // 3. If body's type is non-null and response's header list does not contain - // `Content-Type`, then append (`Content-Type`, body's type) to response's header list. - if (body.type != null && !response[kState].headersList.contains('Content-Type')) { - response[kState].headersList.append('content-type', body.type) + value = value instanceof NativeFile + ? new File([value], filename, options) + : new FileLike(value, filename, options) } } -} -webidl.converters.ReadableStream = webidl.interfaceConverter( - ReadableStream -) + // 4. Return an entry whose name is name and whose value is value. + return { name, value } +} -webidl.converters.FormData = webidl.interfaceConverter( - FormData -) +module.exports = { FormData, makeEntry } -webidl.converters.URLSearchParams = webidl.interfaceConverter( - URLSearchParams -) -// https://fetch.spec.whatwg.org/#typedefdef-xmlhttprequestbodyinit -webidl.converters.XMLHttpRequestBodyInit = function (V) { - if (typeof V === 'string') { - return webidl.converters.USVString(V) - } +/***/ }), - if (isBlobLike(V)) { - return webidl.converters.Blob(V, { strict: false }) - } +/***/ 7786: +/***/ ((module) => { - if (types.isArrayBuffer(V) || types.isTypedArray(V) || types.isDataView(V)) { - return webidl.converters.BufferSource(V) - } - if (util.isFormDataLike(V)) { - return webidl.converters.FormData(V, { strict: false }) - } - if (V instanceof URLSearchParams) { - return webidl.converters.URLSearchParams(V) - } +// In case of breaking changes, increase the version +// number to avoid conflicts. +const globalOrigin = Symbol.for('undici.globalOrigin.1') - return webidl.converters.DOMString(V) +function getGlobalOrigin () { + return globalThis[globalOrigin] } -// https://fetch.spec.whatwg.org/#bodyinit -webidl.converters.BodyInit = function (V) { - if (V instanceof ReadableStream) { - return webidl.converters.ReadableStream(V) - } +function setGlobalOrigin (newOrigin) { + if (newOrigin === undefined) { + Object.defineProperty(globalThis, globalOrigin, { + value: undefined, + writable: true, + enumerable: false, + configurable: false + }) - // Note: the spec doesn't include async iterables, - // this is an undici extension. - if (V?.[Symbol.asyncIterator]) { - return V + return } - return webidl.converters.XMLHttpRequestBodyInit(V) -} + const parsedURL = new URL(newOrigin) -webidl.converters.ResponseInit = webidl.dictionaryConverter([ - { - key: 'status', - converter: webidl.converters['unsigned short'], - defaultValue: 200 - }, - { - key: 'statusText', - converter: webidl.converters.ByteString, - defaultValue: '' - }, - { - key: 'headers', - converter: webidl.converters.HeadersInit + if (parsedURL.protocol !== 'http:' && parsedURL.protocol !== 'https:') { + throw new TypeError(`Only http & https urls are allowed, received ${parsedURL.protocol}`) } -]) -module.exports = { - makeNetworkError, - makeResponse, - makeAppropriateNetworkError, - filterResponse, - Response, - cloneResponse + Object.defineProperty(globalThis, globalOrigin, { + value: parsedURL, + writable: true, + enumerable: false, + configurable: false + }) } - -/***/ }), - -/***/ 2895: -/***/ ((module) => { - -"use strict"; - - module.exports = { - kUrl: Symbol('url'), - kHeaders: Symbol('headers'), - kSignal: Symbol('signal'), - kState: Symbol('state'), - kGuard: Symbol('guard'), - kRealm: Symbol('realm') + getGlobalOrigin, + setGlobalOrigin } /***/ }), -/***/ 1612: +/***/ 217: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; +// https://github.com/Ethan-Arrowood/undici-fetch -const { redirectStatusSet, referrerPolicySet: referrerPolicyTokens, badPortsSet } = __nccwpck_require__(3283) -const { getGlobalOrigin } = __nccwpck_require__(4407) -const { performance } = __nccwpck_require__(2987) -const { isBlobLike, toUSVString, ReadableStreamFrom } = __nccwpck_require__(5069) -const assert = __nccwpck_require__(2613) -const { isUint8Array } = __nccwpck_require__(8253) -let supportedHashes = [] +const { kConstruct } = __nccwpck_require__(7417) +const { kEnumerableProperty } = __nccwpck_require__(7234) +const { + iteratorMixin, + isValidHeaderName, + isValidHeaderValue +} = __nccwpck_require__(1046) +const { webidl } = __nccwpck_require__(4859) +const assert = __nccwpck_require__(4589) +const util = __nccwpck_require__(7975) -// https://nodejs.org/api/crypto.html#determining-if-crypto-support-is-unavailable -/** @type {import('crypto')|undefined} */ -let crypto +const kHeadersMap = Symbol('headers map') +const kHeadersSortedMap = Symbol('headers map sorted') -try { - crypto = __nccwpck_require__(6982) - const possibleRelevantHashes = ['sha256', 'sha384', 'sha512'] - supportedHashes = crypto.getHashes().filter((hash) => possibleRelevantHashes.includes(hash)) -/* c8 ignore next 3 */ -} catch { +/** + * @param {number} code + */ +function isHTTPWhiteSpaceCharCode (code) { + return code === 0x00a || code === 0x00d || code === 0x009 || code === 0x020 } -function responseURL (response) { - // https://fetch.spec.whatwg.org/#responses - // A response has an associated URL. It is a pointer to the last URL - // in response’s URL list and null if response’s URL list is empty. - const urlList = response.urlList - const length = urlList.length - return length === 0 ? null : urlList[length - 1].toString() +/** + * @see https://fetch.spec.whatwg.org/#concept-header-value-normalize + * @param {string} potentialValue + */ +function headerValueNormalize (potentialValue) { + // To normalize a byte sequence potentialValue, remove + // any leading and trailing HTTP whitespace bytes from + // potentialValue. + let i = 0; let j = potentialValue.length + + while (j > i && isHTTPWhiteSpaceCharCode(potentialValue.charCodeAt(j - 1))) --j + while (j > i && isHTTPWhiteSpaceCharCode(potentialValue.charCodeAt(i))) ++i + + return i === 0 && j === potentialValue.length ? potentialValue : potentialValue.substring(i, j) } -// https://fetch.spec.whatwg.org/#concept-response-location-url -function responseLocationURL (response, requestFragment) { - // 1. If response’s status is not a redirect status, then return null. - if (!redirectStatusSet.has(response.status)) { - return null - } +function fill (headers, object) { + // To fill a Headers object headers with a given object object, run these steps: - // 2. Let location be the result of extracting header list values given - // `Location` and response’s header list. - let location = response.headersList.get('location') + // 1. If object is a sequence, then for each header in object: + // Note: webidl conversion to array has already been done. + if (Array.isArray(object)) { + for (let i = 0; i < object.length; ++i) { + const header = object[i] + // 1. If header does not contain exactly two items, then throw a TypeError. + if (header.length !== 2) { + throw webidl.errors.exception({ + header: 'Headers constructor', + message: `expected name/value pair to be length 2, found ${header.length}.` + }) + } - // 3. If location is a header value, then set location to the result of - // parsing location with response’s URL. - if (location !== null && isValidHeaderValue(location)) { - location = new URL(location, responseURL(response)) - } + // 2. Append (header’s first item, header’s second item) to headers. + appendHeader(headers, header[0], header[1]) + } + } else if (typeof object === 'object' && object !== null) { + // Note: null should throw - // 4. If location is a URL whose fragment is null, then set location’s - // fragment to requestFragment. - if (location && !location.hash) { - location.hash = requestFragment + // 2. Otherwise, object is a record, then for each key → value in object, + // append (key, value) to headers + const keys = Object.keys(object) + for (let i = 0; i < keys.length; ++i) { + appendHeader(headers, keys[i], object[keys[i]]) + } + } else { + throw webidl.errors.conversionFailed({ + prefix: 'Headers constructor', + argument: 'Argument 1', + types: ['sequence>', 'record'] + }) } - - // 5. Return location. - return location } -/** @returns {URL} */ -function requestCurrentURL (request) { - return request.urlList[request.urlList.length - 1] -} +/** + * @see https://fetch.spec.whatwg.org/#concept-headers-append + */ +function appendHeader (headers, name, value) { + // 1. Normalize value. + value = headerValueNormalize(value) -function requestBadPort (request) { - // 1. Let url be request’s current URL. - const url = requestCurrentURL(request) + // 2. If name is not a header name or value is not a + // header value, then throw a TypeError. + if (!isValidHeaderName(name)) { + throw webidl.errors.invalidArgument({ + prefix: 'Headers.append', + value: name, + type: 'header name' + }) + } else if (!isValidHeaderValue(value)) { + throw webidl.errors.invalidArgument({ + prefix: 'Headers.append', + value, + type: 'header value' + }) + } - // 2. If url’s scheme is an HTTP(S) scheme and url’s port is a bad port, - // then return blocked. - if (urlIsHttpHttpsScheme(url) && badPortsSet.has(url.port)) { - return 'blocked' + // 3. If headers’s guard is "immutable", then throw a TypeError. + // 4. Otherwise, if headers’s guard is "request" and name is a + // forbidden header name, return. + // 5. Otherwise, if headers’s guard is "request-no-cors": + // TODO + // Note: undici does not implement forbidden header names + if (getHeadersGuard(headers) === 'immutable') { + throw new TypeError('immutable') } - // 3. Return allowed. - return 'allowed' + // 6. Otherwise, if headers’s guard is "response" and name is a + // forbidden response-header name, return. + + // 7. Append (name, value) to headers’s header list. + return getHeadersList(headers).append(name, value, false) + + // 8. If headers’s guard is "request-no-cors", then remove + // privileged no-CORS request headers from headers } -function isErrorLike (object) { - return object instanceof Error || ( - object?.constructor?.name === 'Error' || - object?.constructor?.name === 'DOMException' - ) +function compareHeaderName (a, b) { + return a[0] < b[0] ? -1 : 1 } -// Check whether |statusText| is a ByteString and -// matches the Reason-Phrase token production. -// RFC 2616: https://tools.ietf.org/html/rfc2616 -// RFC 7230: https://tools.ietf.org/html/rfc7230 -// "reason-phrase = *( HTAB / SP / VCHAR / obs-text )" -// https://github.com/chromium/chromium/blob/94.0.4604.1/third_party/blink/renderer/core/fetch/response.cc#L116 -function isValidReasonPhrase (statusText) { - for (let i = 0; i < statusText.length; ++i) { - const c = statusText.charCodeAt(i) - if ( - !( - ( - c === 0x09 || // HTAB - (c >= 0x20 && c <= 0x7e) || // SP / VCHAR - (c >= 0x80 && c <= 0xff) - ) // obs-text - ) - ) { - return false +class HeadersList { + /** @type {[string, string][]|null} */ + cookies = null + + constructor (init) { + if (init instanceof HeadersList) { + this[kHeadersMap] = new Map(init[kHeadersMap]) + this[kHeadersSortedMap] = init[kHeadersSortedMap] + this.cookies = init.cookies === null ? null : [...init.cookies] + } else { + this[kHeadersMap] = new Map(init) + this[kHeadersSortedMap] = null } } - return true -} -/** - * @see https://tools.ietf.org/html/rfc7230#section-3.2.6 - * @param {number} c - */ -function isTokenCharCode (c) { - switch (c) { - case 0x22: - case 0x28: - case 0x29: - case 0x2c: - case 0x2f: - case 0x3a: - case 0x3b: - case 0x3c: - case 0x3d: - case 0x3e: - case 0x3f: - case 0x40: - case 0x5b: - case 0x5c: - case 0x5d: - case 0x7b: - case 0x7d: - // DQUOTE and "(),/:;<=>?@[\]{}" - return false - default: - // VCHAR %x21-7E - return c >= 0x21 && c <= 0x7e + /** + * @see https://fetch.spec.whatwg.org/#header-list-contains + * @param {string} name + * @param {boolean} isLowerCase + */ + contains (name, isLowerCase) { + // A header list list contains a header name name if list + // contains a header whose name is a byte-case-insensitive + // match for name. + + return this[kHeadersMap].has(isLowerCase ? name : name.toLowerCase()) } -} -/** - * @param {string} characters - */ -function isValidHTTPToken (characters) { - if (characters.length === 0) { - return false + clear () { + this[kHeadersMap].clear() + this[kHeadersSortedMap] = null + this.cookies = null } - for (let i = 0; i < characters.length; ++i) { - if (!isTokenCharCode(characters.charCodeAt(i))) { - return false + + /** + * @see https://fetch.spec.whatwg.org/#concept-header-list-append + * @param {string} name + * @param {string} value + * @param {boolean} isLowerCase + */ + append (name, value, isLowerCase) { + this[kHeadersSortedMap] = null + + // 1. If list contains name, then set name to the first such + // header’s name. + const lowercaseName = isLowerCase ? name : name.toLowerCase() + const exists = this[kHeadersMap].get(lowercaseName) + + // 2. Append (name, value) to list. + if (exists) { + const delimiter = lowercaseName === 'cookie' ? '; ' : ', ' + this[kHeadersMap].set(lowercaseName, { + name: exists.name, + value: `${exists.value}${delimiter}${value}` + }) + } else { + this[kHeadersMap].set(lowercaseName, { name, value }) + } + + if (lowercaseName === 'set-cookie') { + (this.cookies ??= []).push(value) } } - return true -} -/** - * @see https://fetch.spec.whatwg.org/#header-name - * @param {string} potentialValue - */ -function isValidHeaderName (potentialValue) { - return isValidHTTPToken(potentialValue) -} + /** + * @see https://fetch.spec.whatwg.org/#concept-header-list-set + * @param {string} name + * @param {string} value + * @param {boolean} isLowerCase + */ + set (name, value, isLowerCase) { + this[kHeadersSortedMap] = null + const lowercaseName = isLowerCase ? name : name.toLowerCase() -/** - * @see https://fetch.spec.whatwg.org/#header-value - * @param {string} potentialValue - */ -function isValidHeaderValue (potentialValue) { - // - Has no leading or trailing HTTP tab or space bytes. - // - Contains no 0x00 (NUL) or HTTP newline bytes. - if ( - potentialValue.startsWith('\t') || - potentialValue.startsWith(' ') || - potentialValue.endsWith('\t') || - potentialValue.endsWith(' ') - ) { - return false + if (lowercaseName === 'set-cookie') { + this.cookies = [value] + } + + // 1. If list contains name, then set the value of + // the first such header to value and remove the + // others. + // 2. Otherwise, append header (name, value) to list. + this[kHeadersMap].set(lowercaseName, { name, value }) } - if ( - potentialValue.includes('\0') || - potentialValue.includes('\r') || - potentialValue.includes('\n') - ) { - return false + /** + * @see https://fetch.spec.whatwg.org/#concept-header-list-delete + * @param {string} name + * @param {boolean} isLowerCase + */ + delete (name, isLowerCase) { + this[kHeadersSortedMap] = null + if (!isLowerCase) name = name.toLowerCase() + + if (name === 'set-cookie') { + this.cookies = null + } + + this[kHeadersMap].delete(name) } - return true -} + /** + * @see https://fetch.spec.whatwg.org/#concept-header-list-get + * @param {string} name + * @param {boolean} isLowerCase + * @returns {string | null} + */ + get (name, isLowerCase) { + // 1. If list does not contain name, then return null. + // 2. Return the values of all headers in list whose name + // is a byte-case-insensitive match for name, + // separated from each other by 0x2C 0x20, in order. + return this[kHeadersMap].get(isLowerCase ? name : name.toLowerCase())?.value ?? null + } -// https://w3c.github.io/webappsec-referrer-policy/#set-requests-referrer-policy-on-redirect -function setRequestReferrerPolicyOnRedirect (request, actualResponse) { - // Given a request request and a response actualResponse, this algorithm - // updates request’s referrer policy according to the Referrer-Policy - // header (if any) in actualResponse. + * [Symbol.iterator] () { + // use the lowercased name + for (const { 0: name, 1: { value } } of this[kHeadersMap]) { + yield [name, value] + } + } - // 1. Let policy be the result of executing § 8.1 Parse a referrer policy - // from a Referrer-Policy header on actualResponse. + get entries () { + const headers = {} - // 8.1 Parse a referrer policy from a Referrer-Policy header - // 1. Let policy-tokens be the result of extracting header list values given `Referrer-Policy` and response’s header list. - const { headersList } = actualResponse - // 2. Let policy be the empty string. - // 3. For each token in policy-tokens, if token is a referrer policy and token is not the empty string, then set policy to token. - // 4. Return policy. - const policyHeader = (headersList.get('referrer-policy') ?? '').split(',') + if (this[kHeadersMap].size !== 0) { + for (const { name, value } of this[kHeadersMap].values()) { + headers[name] = value + } + } - // Note: As the referrer-policy can contain multiple policies - // separated by comma, we need to loop through all of them - // and pick the first valid one. - // Ref: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy#specify_a_fallback_policy - let policy = '' - if (policyHeader.length > 0) { - // The right-most policy takes precedence. - // The left-most policy is the fallback. - for (let i = policyHeader.length; i !== 0; i--) { - const token = policyHeader[i - 1].trim() - if (referrerPolicyTokens.has(token)) { - policy = token - break + return headers + } + + rawValues () { + return this[kHeadersMap].values() + } + + get entriesList () { + const headers = [] + + if (this[kHeadersMap].size !== 0) { + for (const { 0: lowerName, 1: { name, value } } of this[kHeadersMap]) { + if (lowerName === 'set-cookie') { + for (const cookie of this.cookies) { + headers.push([name, cookie]) + } + } else { + headers.push([name, value]) + } } } + + return headers } - // 2. If policy is not the empty string, then set request’s referrer policy to policy. - if (policy !== '') { - request.referrerPolicy = policy + // https://fetch.spec.whatwg.org/#convert-header-names-to-a-sorted-lowercase-set + toSortedArray () { + const size = this[kHeadersMap].size + const array = new Array(size) + // In most cases, you will use the fast-path. + // fast-path: Use binary insertion sort for small arrays. + if (size <= 32) { + if (size === 0) { + // If empty, it is an empty array. To avoid the first index assignment. + return array + } + // Improve performance by unrolling loop and avoiding double-loop. + // Double-loop-less version of the binary insertion sort. + const iterator = this[kHeadersMap][Symbol.iterator]() + const firstValue = iterator.next().value + // set [name, value] to first index. + array[0] = [firstValue[0], firstValue[1].value] + // https://fetch.spec.whatwg.org/#concept-header-list-sort-and-combine + // 3.2.2. Assert: value is non-null. + assert(firstValue[1].value !== null) + for ( + let i = 1, j = 0, right = 0, left = 0, pivot = 0, x, value; + i < size; + ++i + ) { + // get next value + value = iterator.next().value + // set [name, value] to current index. + x = array[i] = [value[0], value[1].value] + // https://fetch.spec.whatwg.org/#concept-header-list-sort-and-combine + // 3.2.2. Assert: value is non-null. + assert(x[1] !== null) + left = 0 + right = i + // binary search + while (left < right) { + // middle index + pivot = left + ((right - left) >> 1) + // compare header name + if (array[pivot][0] <= x[0]) { + left = pivot + 1 + } else { + right = pivot + } + } + if (i !== pivot) { + j = i + while (j > left) { + array[j] = array[--j] + } + array[left] = x + } + } + /* c8 ignore next 4 */ + if (!iterator.next().done) { + // This is for debugging and will never be called. + throw new TypeError('Unreachable') + } + return array + } else { + // This case would be a rare occurrence. + // slow-path: fallback + let i = 0 + for (const { 0: name, 1: { value } } of this[kHeadersMap]) { + array[i++] = [name, value] + // https://fetch.spec.whatwg.org/#concept-header-list-sort-and-combine + // 3.2.2. Assert: value is non-null. + assert(value !== null) + } + return array.sort(compareHeaderName) + } } } -// https://fetch.spec.whatwg.org/#cross-origin-resource-policy-check -function crossOriginResourcePolicyCheck () { - // TODO - return 'allowed' -} +// https://fetch.spec.whatwg.org/#headers-class +class Headers { + #guard + #headersList -// https://fetch.spec.whatwg.org/#concept-cors-check -function corsCheck () { - // TODO - return 'success' -} + constructor (init = undefined) { + webidl.util.markAsUncloneable(this) -// https://fetch.spec.whatwg.org/#concept-tao-check -function TAOCheck () { - // TODO - return 'success' -} + if (init === kConstruct) { + return + } -function appendFetchMetadata (httpRequest) { - // https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-dest-header - // TODO + this.#headersList = new HeadersList() - // https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-mode-header + // The new Headers(init) constructor steps are: - // 1. Assert: r’s url is a potentially trustworthy URL. - // TODO + // 1. Set this’s guard to "none". + this.#guard = 'none' - // 2. Let header be a Structured Header whose value is a token. - let header = null + // 2. If init is given, then fill this with init. + if (init !== undefined) { + init = webidl.converters.HeadersInit(init, 'Headers contructor', 'init') + fill(this, init) + } + } - // 3. Set header’s value to r’s mode. - header = httpRequest.mode + // https://fetch.spec.whatwg.org/#dom-headers-append + append (name, value) { + webidl.brandCheck(this, Headers) - // 4. Set a structured field value `Sec-Fetch-Mode`/header in r’s header list. - httpRequest.headersList.set('sec-fetch-mode', header) + webidl.argumentLengthCheck(arguments, 2, 'Headers.append') - // https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-site-header - // TODO + const prefix = 'Headers.append' + name = webidl.converters.ByteString(name, prefix, 'name') + value = webidl.converters.ByteString(value, prefix, 'value') - // https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-user-header - // TODO -} + return appendHeader(this, name, value) + } -// https://fetch.spec.whatwg.org/#append-a-request-origin-header -function appendRequestOriginHeader (request) { - // 1. Let serializedOrigin be the result of byte-serializing a request origin with request. - let serializedOrigin = request.origin + // https://fetch.spec.whatwg.org/#dom-headers-delete + delete (name) { + webidl.brandCheck(this, Headers) - // 2. If request’s response tainting is "cors" or request’s mode is "websocket", then append (`Origin`, serializedOrigin) to request’s header list. - if (request.responseTainting === 'cors' || request.mode === 'websocket') { - if (serializedOrigin) { - request.headersList.append('origin', serializedOrigin) - } + webidl.argumentLengthCheck(arguments, 1, 'Headers.delete') - // 3. Otherwise, if request’s method is neither `GET` nor `HEAD`, then: - } else if (request.method !== 'GET' && request.method !== 'HEAD') { - // 1. Switch on request’s referrer policy: - switch (request.referrerPolicy) { - case 'no-referrer': - // Set serializedOrigin to `null`. - serializedOrigin = null - break - case 'no-referrer-when-downgrade': - case 'strict-origin': - case 'strict-origin-when-cross-origin': - // If request’s origin is a tuple origin, its scheme is "https", and request’s current URL’s scheme is not "https", then set serializedOrigin to `null`. - if (request.origin && urlHasHttpsScheme(request.origin) && !urlHasHttpsScheme(requestCurrentURL(request))) { - serializedOrigin = null - } - break - case 'same-origin': - // If request’s origin is not same origin with request’s current URL’s origin, then set serializedOrigin to `null`. - if (!sameOrigin(request, requestCurrentURL(request))) { - serializedOrigin = null - } - break - default: - // Do nothing. + const prefix = 'Headers.delete' + name = webidl.converters.ByteString(name, prefix, 'name') + + // 1. If name is not a header name, then throw a TypeError. + if (!isValidHeaderName(name)) { + throw webidl.errors.invalidArgument({ + prefix: 'Headers.delete', + value: name, + type: 'header name' + }) } - if (serializedOrigin) { - // 2. Append (`Origin`, serializedOrigin) to request’s header list. - request.headersList.append('origin', serializedOrigin) + // 2. If this’s guard is "immutable", then throw a TypeError. + // 3. Otherwise, if this’s guard is "request" and name is a + // forbidden header name, return. + // 4. Otherwise, if this’s guard is "request-no-cors", name + // is not a no-CORS-safelisted request-header name, and + // name is not a privileged no-CORS request-header name, + // return. + // 5. Otherwise, if this’s guard is "response" and name is + // a forbidden response-header name, return. + // Note: undici does not implement forbidden header names + if (this.#guard === 'immutable') { + throw new TypeError('immutable') } - } -} -function coarsenedSharedCurrentTime (crossOriginIsolatedCapability) { - // TODO - return performance.now() -} + // 6. If this’s header list does not contain name, then + // return. + if (!this.#headersList.contains(name, false)) { + return + } -// https://fetch.spec.whatwg.org/#create-an-opaque-timing-info -function createOpaqueTimingInfo (timingInfo) { - return { - startTime: timingInfo.startTime ?? 0, - redirectStartTime: 0, - redirectEndTime: 0, - postRedirectStartTime: timingInfo.startTime ?? 0, - finalServiceWorkerStartTime: 0, - finalNetworkResponseStartTime: 0, - finalNetworkRequestStartTime: 0, - endTime: 0, - encodedBodySize: 0, - decodedBodySize: 0, - finalConnectionTimingInfo: null + // 7. Delete name from this’s header list. + // 8. If this’s guard is "request-no-cors", then remove + // privileged no-CORS request headers from this. + this.#headersList.delete(name, false) } -} -// https://html.spec.whatwg.org/multipage/origin.html#policy-container -function makePolicyContainer () { - // Note: the fetch spec doesn't make use of embedder policy or CSP list - return { - referrerPolicy: 'strict-origin-when-cross-origin' - } -} + // https://fetch.spec.whatwg.org/#dom-headers-get + get (name) { + webidl.brandCheck(this, Headers) -// https://html.spec.whatwg.org/multipage/origin.html#clone-a-policy-container -function clonePolicyContainer (policyContainer) { - return { - referrerPolicy: policyContainer.referrerPolicy - } -} + webidl.argumentLengthCheck(arguments, 1, 'Headers.get') -// https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer -function determineRequestsReferrer (request) { - // 1. Let policy be request's referrer policy. - const policy = request.referrerPolicy + const prefix = 'Headers.get' + name = webidl.converters.ByteString(name, prefix, 'name') - // Note: policy cannot (shouldn't) be null or an empty string. - assert(policy) + // 1. If name is not a header name, then throw a TypeError. + if (!isValidHeaderName(name)) { + throw webidl.errors.invalidArgument({ + prefix, + value: name, + type: 'header name' + }) + } - // 2. Let environment be request’s client. + // 2. Return the result of getting name from this’s header + // list. + return this.#headersList.get(name, false) + } - let referrerSource = null + // https://fetch.spec.whatwg.org/#dom-headers-has + has (name) { + webidl.brandCheck(this, Headers) - // 3. Switch on request’s referrer: - if (request.referrer === 'client') { - // Note: node isn't a browser and doesn't implement document/iframes, - // so we bypass this step and replace it with our own. + webidl.argumentLengthCheck(arguments, 1, 'Headers.has') - const globalOrigin = getGlobalOrigin() + const prefix = 'Headers.has' + name = webidl.converters.ByteString(name, prefix, 'name') - if (!globalOrigin || globalOrigin.origin === 'null') { - return 'no-referrer' + // 1. If name is not a header name, then throw a TypeError. + if (!isValidHeaderName(name)) { + throw webidl.errors.invalidArgument({ + prefix, + value: name, + type: 'header name' + }) } - // note: we need to clone it as it's mutated - referrerSource = new URL(globalOrigin) - } else if (request.referrer instanceof URL) { - // Let referrerSource be request’s referrer. - referrerSource = request.referrer + // 2. Return true if this’s header list contains name; + // otherwise false. + return this.#headersList.contains(name, false) } - // 4. Let request’s referrerURL be the result of stripping referrerSource for - // use as a referrer. - let referrerURL = stripURLForReferrer(referrerSource) - - // 5. Let referrerOrigin be the result of stripping referrerSource for use as - // a referrer, with the origin-only flag set to true. - const referrerOrigin = stripURLForReferrer(referrerSource, true) - - // 6. If the result of serializing referrerURL is a string whose length is - // greater than 4096, set referrerURL to referrerOrigin. - if (referrerURL.toString().length > 4096) { - referrerURL = referrerOrigin - } - - const areSameOrigin = sameOrigin(request, referrerURL) - const isNonPotentiallyTrustWorthy = isURLPotentiallyTrustworthy(referrerURL) && - !isURLPotentiallyTrustworthy(request.url) + // https://fetch.spec.whatwg.org/#dom-headers-set + set (name, value) { + webidl.brandCheck(this, Headers) - // 8. Execute the switch statements corresponding to the value of policy: - switch (policy) { - case 'origin': return referrerOrigin != null ? referrerOrigin : stripURLForReferrer(referrerSource, true) - case 'unsafe-url': return referrerURL - case 'same-origin': - return areSameOrigin ? referrerOrigin : 'no-referrer' - case 'origin-when-cross-origin': - return areSameOrigin ? referrerURL : referrerOrigin - case 'strict-origin-when-cross-origin': { - const currentURL = requestCurrentURL(request) + webidl.argumentLengthCheck(arguments, 2, 'Headers.set') - // 1. If the origin of referrerURL and the origin of request’s current - // URL are the same, then return referrerURL. - if (sameOrigin(referrerURL, currentURL)) { - return referrerURL - } + const prefix = 'Headers.set' + name = webidl.converters.ByteString(name, prefix, 'name') + value = webidl.converters.ByteString(value, prefix, 'value') - // 2. If referrerURL is a potentially trustworthy URL and request’s - // current URL is not a potentially trustworthy URL, then return no - // referrer. - if (isURLPotentiallyTrustworthy(referrerURL) && !isURLPotentiallyTrustworthy(currentURL)) { - return 'no-referrer' - } + // 1. Normalize value. + value = headerValueNormalize(value) - // 3. Return referrerOrigin. - return referrerOrigin + // 2. If name is not a header name or value is not a + // header value, then throw a TypeError. + if (!isValidHeaderName(name)) { + throw webidl.errors.invalidArgument({ + prefix, + value: name, + type: 'header name' + }) + } else if (!isValidHeaderValue(value)) { + throw webidl.errors.invalidArgument({ + prefix, + value, + type: 'header value' + }) } - case 'strict-origin': // eslint-disable-line - /** - * 1. If referrerURL is a potentially trustworthy URL and - * request’s current URL is not a potentially trustworthy URL, - * then return no referrer. - * 2. Return referrerOrigin - */ - case 'no-referrer-when-downgrade': // eslint-disable-line - /** - * 1. If referrerURL is a potentially trustworthy URL and - * request’s current URL is not a potentially trustworthy URL, - * then return no referrer. - * 2. Return referrerOrigin - */ - - default: // eslint-disable-line - return isNonPotentiallyTrustWorthy ? 'no-referrer' : referrerOrigin - } -} -/** - * @see https://w3c.github.io/webappsec-referrer-policy/#strip-url - * @param {URL} url - * @param {boolean|undefined} originOnly - */ -function stripURLForReferrer (url, originOnly) { - // 1. Assert: url is a URL. - assert(url instanceof URL) + // 3. If this’s guard is "immutable", then throw a TypeError. + // 4. Otherwise, if this’s guard is "request" and name is a + // forbidden header name, return. + // 5. Otherwise, if this’s guard is "request-no-cors" and + // name/value is not a no-CORS-safelisted request-header, + // return. + // 6. Otherwise, if this’s guard is "response" and name is a + // forbidden response-header name, return. + // Note: undici does not implement forbidden header names + if (this.#guard === 'immutable') { + throw new TypeError('immutable') + } - // 2. If url’s scheme is a local scheme, then return no referrer. - if (url.protocol === 'file:' || url.protocol === 'about:' || url.protocol === 'blank:') { - return 'no-referrer' + // 7. Set (name, value) in this’s header list. + // 8. If this’s guard is "request-no-cors", then remove + // privileged no-CORS request headers from this + this.#headersList.set(name, value, false) } - // 3. Set url’s username to the empty string. - url.username = '' + // https://fetch.spec.whatwg.org/#dom-headers-getsetcookie + getSetCookie () { + webidl.brandCheck(this, Headers) - // 4. Set url’s password to the empty string. - url.password = '' + // 1. If this’s header list does not contain `Set-Cookie`, then return « ». + // 2. Return the values of all headers in this’s header list whose name is + // a byte-case-insensitive match for `Set-Cookie`, in order. - // 5. Set url’s fragment to null. - url.hash = '' + const list = this.#headersList.cookies - // 6. If the origin-only flag is true, then: - if (originOnly) { - // 1. Set url’s path to « the empty string ». - url.pathname = '' + if (list) { + return [...list] + } - // 2. Set url’s query to null. - url.search = '' + return [] } - // 7. Return url. - return url -} + // https://fetch.spec.whatwg.org/#concept-header-list-sort-and-combine + get [kHeadersSortedMap] () { + if (this.#headersList[kHeadersSortedMap]) { + return this.#headersList[kHeadersSortedMap] + } -function isURLPotentiallyTrustworthy (url) { - if (!(url instanceof URL)) { - return false - } + // 1. Let headers be an empty list of headers with the key being the name + // and value the value. + const headers = [] - // If child of about, return true - if (url.href === 'about:blank' || url.href === 'about:srcdoc') { - return true - } + // 2. Let names be the result of convert header names to a sorted-lowercase + // set with all the names of the headers in list. + const names = this.#headersList.toSortedArray() - // If scheme is data, return true - if (url.protocol === 'data:') return true + const cookies = this.#headersList.cookies - // If file, return true - if (url.protocol === 'file:') return true + // fast-path + if (cookies === null || cookies.length === 1) { + // Note: The non-null assertion of value has already been done by `HeadersList#toSortedArray` + return (this.#headersList[kHeadersSortedMap] = names) + } - return isOriginPotentiallyTrustworthy(url.origin) + // 3. For each name of names: + for (let i = 0; i < names.length; ++i) { + const { 0: name, 1: value } = names[i] + // 1. If name is `set-cookie`, then: + if (name === 'set-cookie') { + // 1. Let values be a list of all values of headers in list whose name + // is a byte-case-insensitive match for name, in order. - function isOriginPotentiallyTrustworthy (origin) { - // If origin is explicitly null, return false - if (origin == null || origin === 'null') return false + // 2. For each value of values: + // 1. Append (name, value) to headers. + for (let j = 0; j < cookies.length; ++j) { + headers.push([name, cookies[j]]) + } + } else { + // 2. Otherwise: - const originAsURL = new URL(origin) + // 1. Let value be the result of getting name from list. - // If secure, return true - if (originAsURL.protocol === 'https:' || originAsURL.protocol === 'wss:') { - return true - } + // 2. Assert: value is non-null. + // Note: This operation was done by `HeadersList#toSortedArray`. - // If localhost or variants, return true - if (/^127(?:\.[0-9]+){0,2}\.[0-9]+$|^\[(?:0*:)*?:?0*1\]$/.test(originAsURL.hostname) || - (originAsURL.hostname === 'localhost' || originAsURL.hostname.includes('localhost.')) || - (originAsURL.hostname.endsWith('.localhost'))) { - return true + // 3. Append (name, value) to headers. + headers.push([name, value]) + } } - // If any other, return false - return false + // 4. Return headers. + return (this.#headersList[kHeadersSortedMap] = headers) } -} -/** - * @see https://w3c.github.io/webappsec-subresource-integrity/#does-response-match-metadatalist - * @param {Uint8Array} bytes - * @param {string} metadataList - */ -function bytesMatch (bytes, metadataList) { - // If node is not built with OpenSSL support, we cannot check - // a request's integrity, so allow it by default (the spec will - // allow requests if an invalid hash is given, as precedence). - /* istanbul ignore if: only if node is built with --without-ssl */ - if (crypto === undefined) { - return true - } + [util.inspect.custom] (depth, options) { + options.depth ??= depth - // 1. Let parsedMetadata be the result of parsing metadataList. - const parsedMetadata = parseMetadata(metadataList) + return `Headers ${util.formatWithOptions(options, this.#headersList.entries)}` + } - // 2. If parsedMetadata is no metadata, return true. - if (parsedMetadata === 'no metadata') { - return true + static getHeadersGuard (o) { + return o.#guard } - // 3. If response is not eligible for integrity validation, return false. - // TODO + static setHeadersGuard (o, guard) { + o.#guard = guard + } - // 4. If parsedMetadata is the empty set, return true. - if (parsedMetadata.length === 0) { - return true + static getHeadersList (o) { + return o.#headersList } - // 5. Let metadata be the result of getting the strongest - // metadata from parsedMetadata. - const strongest = getStrongestMetadata(parsedMetadata) - const metadata = filterMetadataListByAlgorithm(parsedMetadata, strongest) + static setHeadersList (o, list) { + o.#headersList = list + } +} - // 6. For each item in metadata: - for (const item of metadata) { - // 1. Let algorithm be the alg component of item. - const algorithm = item.algo +const { getHeadersGuard, setHeadersGuard, getHeadersList, setHeadersList } = Headers +Reflect.deleteProperty(Headers, 'getHeadersGuard') +Reflect.deleteProperty(Headers, 'setHeadersGuard') +Reflect.deleteProperty(Headers, 'getHeadersList') +Reflect.deleteProperty(Headers, 'setHeadersList') - // 2. Let expectedValue be the val component of item. - const expectedValue = item.hash +iteratorMixin('Headers', Headers, kHeadersSortedMap, 0, 1) - // See https://github.com/web-platform-tests/wpt/commit/e4c5cc7a5e48093220528dfdd1c4012dc3837a0e - // "be liberal with padding". This is annoying, and it's not even in the spec. +Object.defineProperties(Headers.prototype, { + append: kEnumerableProperty, + delete: kEnumerableProperty, + get: kEnumerableProperty, + has: kEnumerableProperty, + set: kEnumerableProperty, + getSetCookie: kEnumerableProperty, + [Symbol.toStringTag]: { + value: 'Headers', + configurable: true + }, + [util.inspect.custom]: { + enumerable: false + } +}) - // 3. Let actualValue be the result of applying algorithm to bytes. - let actualValue = crypto.createHash(algorithm).update(bytes).digest('base64') +webidl.converters.HeadersInit = function (V, prefix, argument) { + if (webidl.util.Type(V) === 'Object') { + const iterator = Reflect.get(V, Symbol.iterator) - if (actualValue[actualValue.length - 1] === '=') { - if (actualValue[actualValue.length - 2] === '=') { - actualValue = actualValue.slice(0, -2) - } else { - actualValue = actualValue.slice(0, -1) + // A work-around to ensure we send the properly-cased Headers when V is a Headers object. + // Read https://github.com/nodejs/undici/pull/3159#issuecomment-2075537226 before touching, please. + if (!util.types.isProxy(V) && iterator === Headers.prototype.entries) { // Headers object + try { + return getHeadersList(V).entriesList + } catch { + // fall-through } } - // 4. If actualValue is a case-sensitive match for expectedValue, - // return true. - if (compareBase64Mixed(actualValue, expectedValue)) { - return true + if (typeof iterator === 'function') { + return webidl.converters['sequence>'](V, prefix, argument, iterator.bind(V)) } + + return webidl.converters['record'](V, prefix, argument) } - // 7. Return false. - return false + throw webidl.errors.conversionFailed({ + prefix: 'Headers constructor', + argument: 'Argument 1', + types: ['sequence>', 'record'] + }) } -// https://w3c.github.io/webappsec-subresource-integrity/#grammardef-hash-with-options -// https://www.w3.org/TR/CSP2/#source-list-syntax -// https://www.rfc-editor.org/rfc/rfc5234#appendix-B.1 -const parseHashWithOptions = /(?sha256|sha384|sha512)-((?[A-Za-z0-9+/]+|[A-Za-z0-9_-]+)={0,2}(?:\s|$)( +[!-~]*)?)?/i +module.exports = { + fill, + // for test. + compareHeaderName, + Headers, + HeadersList, + getHeadersGuard, + setHeadersGuard, + setHeadersList, + getHeadersList +} -/** - * @see https://w3c.github.io/webappsec-subresource-integrity/#parse-metadata - * @param {string} metadata - */ -function parseMetadata (metadata) { - // 1. Let result be the empty set. - /** @type {{ algo: string, hash: string }[]} */ - const result = [] - // 2. Let empty be equal to true. - let empty = true +/***/ }), - // 3. For each token returned by splitting metadata on spaces: - for (const token of metadata.split(' ')) { - // 1. Set empty to false. - empty = false +/***/ 5780: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - // 2. Parse token as a hash-with-options. - const parsedToken = parseHashWithOptions.exec(token) +// https://github.com/Ethan-Arrowood/undici-fetch - // 3. If token does not parse, continue to the next token. - if ( - parsedToken === null || - parsedToken.groups === undefined || - parsedToken.groups.algo === undefined - ) { - // Note: Chromium blocks the request at this point, but Firefox - // gives a warning that an invalid integrity was given. The - // correct behavior is to ignore these, and subsequently not - // check the integrity of the resource. - continue - } - // 4. Let algorithm be the hash-algo component of token. - const algorithm = parsedToken.groups.algo.toLowerCase() - // 5. If algorithm is a hash function recognized by the user - // agent, add the parsed token to result. - if (supportedHashes.includes(algorithm)) { - result.push(parsedToken.groups) - } - } +const { + makeNetworkError, + makeAppropriateNetworkError, + filterResponse, + makeResponse, + fromInnerResponse +} = __nccwpck_require__(4317) +const { HeadersList } = __nccwpck_require__(217) +const { Request, cloneRequest } = __nccwpck_require__(5417) +const zlib = __nccwpck_require__(8522) +const { + bytesMatch, + makePolicyContainer, + clonePolicyContainer, + requestBadPort, + TAOCheck, + appendRequestOriginHeader, + responseLocationURL, + requestCurrentURL, + setRequestReferrerPolicyOnRedirect, + tryUpgradeRequestToAPotentiallyTrustworthyURL, + createOpaqueTimingInfo, + appendFetchMetadata, + corsCheck, + crossOriginResourcePolicyCheck, + determineRequestsReferrer, + coarsenedSharedCurrentTime, + createDeferredPromise, + isBlobLike, + sameOrigin, + isCancelled, + isAborted, + isErrorLike, + fullyReadBody, + readableStreamClose, + isomorphicEncode, + urlIsLocal, + urlIsHttpHttpsScheme, + urlHasHttpsScheme, + clampAndCoarsenConnectionTimingInfo, + simpleRangeHeaderValue, + buildContentRange, + createInflate, + extractMimeType +} = __nccwpck_require__(1046) +const { kState, kDispatcher } = __nccwpck_require__(1445) +const assert = __nccwpck_require__(4589) +const { safelyExtractBody, extractBody } = __nccwpck_require__(8106) +const { + redirectStatusSet, + nullBodyStatus, + safeMethodsSet, + requestBodyHeader, + subresourceSet +} = __nccwpck_require__(6169) +const EE = __nccwpck_require__(8474) +const { Readable, pipeline, finished } = __nccwpck_require__(7075) +const { addAbortListener, isErrored, isReadable, bufferToLowerCasedHeaderName } = __nccwpck_require__(7234) +const { dataURLProcessor, serializeAMimeType, minimizeSupportedMimeType } = __nccwpck_require__(6406) +const { getGlobalDispatcher } = __nccwpck_require__(1903) +const { webidl } = __nccwpck_require__(4859) +const { STATUS_CODES } = __nccwpck_require__(7067) +const GET_OR_HEAD = ['GET', 'HEAD'] - // 4. Return no metadata if empty is true, otherwise return result. - if (empty === true) { - return 'no metadata' - } +const defaultUserAgent = typeof __UNDICI_IS_NODE__ !== 'undefined' || typeof esbuildDetection !== 'undefined' + ? 'node' + : 'undici' - return result -} +/** @type {import('buffer').resolveObjectURL} */ +let resolveObjectURL -/** - * @param {{ algo: 'sha256' | 'sha384' | 'sha512' }[]} metadataList - */ -function getStrongestMetadata (metadataList) { - // Let algorithm be the algo component of the first item in metadataList. - // Can be sha256 - let algorithm = metadataList[0].algo - // If the algorithm is sha512, then it is the strongest - // and we can return immediately - if (algorithm[3] === '5') { - return algorithm +class Fetch extends EE { + constructor (dispatcher) { + super() + + this.dispatcher = dispatcher + this.connection = null + this.dump = false + this.state = 'ongoing' } - for (let i = 1; i < metadataList.length; ++i) { - const metadata = metadataList[i] - // If the algorithm is sha512, then it is the strongest - // and we can break the loop immediately - if (metadata.algo[3] === '5') { - algorithm = 'sha512' - break - // If the algorithm is sha384, then a potential sha256 or sha384 is ignored - } else if (algorithm[3] === '3') { - continue - // algorithm is sha256, check if algorithm is sha384 and if so, set it as - // the strongest - } else if (metadata.algo[3] === '3') { - algorithm = 'sha384' + terminate (reason) { + if (this.state !== 'ongoing') { + return } - } - return algorithm -} -function filterMetadataListByAlgorithm (metadataList, algorithm) { - if (metadataList.length === 1) { - return metadataList + this.state = 'terminated' + this.connection?.destroy(reason) + this.emit('terminated', reason) } - let pos = 0 - for (let i = 0; i < metadataList.length; ++i) { - if (metadataList[i].algo === algorithm) { - metadataList[pos++] = metadataList[i] + // https://fetch.spec.whatwg.org/#fetch-controller-abort + abort (error) { + if (this.state !== 'ongoing') { + return } - } - - metadataList.length = pos - return metadataList -} + // 1. Set controller’s state to "aborted". + this.state = 'aborted' -/** - * Compares two base64 strings, allowing for base64url - * in the second string. - * -* @param {string} actualValue always base64 - * @param {string} expectedValue base64 or base64url - * @returns {boolean} - */ -function compareBase64Mixed (actualValue, expectedValue) { - if (actualValue.length !== expectedValue.length) { - return false - } - for (let i = 0; i < actualValue.length; ++i) { - if (actualValue[i] !== expectedValue[i]) { - if ( - (actualValue[i] === '+' && expectedValue[i] === '-') || - (actualValue[i] === '/' && expectedValue[i] === '_') - ) { - continue - } - return false + // 2. Let fallbackError be an "AbortError" DOMException. + // 3. Set error to fallbackError if it is not given. + if (!error) { + error = new DOMException('The operation was aborted.', 'AbortError') } - } - return true + // 4. Let serializedError be StructuredSerialize(error). + // If that threw an exception, catch it, and let + // serializedError be StructuredSerialize(fallbackError). + + // 5. Set controller’s serialized abort reason to serializedError. + this.serializedAbortReason = error + + this.connection?.destroy(error) + this.emit('terminated', error) + } } -// https://w3c.github.io/webappsec-upgrade-insecure-requests/#upgrade-request -function tryUpgradeRequestToAPotentiallyTrustworthyURL (request) { - // TODO +function handleFetchDone (response) { + finalizeAndReportTiming(response, 'fetch') } -/** - * @link {https://html.spec.whatwg.org/multipage/origin.html#same-origin} - * @param {URL} A - * @param {URL} B - */ -function sameOrigin (A, B) { - // 1. If A and B are the same opaque origin, then return true. - if (A.origin === B.origin && A.origin === 'null') { - return true - } - - // 2. If A and B are both tuple origins and their schemes, - // hosts, and port are identical, then return true. - if (A.protocol === B.protocol && A.hostname === B.hostname && A.port === B.port) { - return true - } - - // 3. Return false. - return false -} - -function createDeferredPromise () { - let res - let rej - const promise = new Promise((resolve, reject) => { - res = resolve - rej = reject - }) +// https://fetch.spec.whatwg.org/#fetch-method +function fetch (input, init = undefined) { + webidl.argumentLengthCheck(arguments, 1, 'globalThis.fetch') - return { promise, resolve: res, reject: rej } -} + // 1. Let p be a new promise. + let p = createDeferredPromise() -function isAborted (fetchParams) { - return fetchParams.controller.state === 'aborted' -} + // 2. Let requestObject be the result of invoking the initial value of + // Request as constructor with input and init as arguments. If this throws + // an exception, reject p with it and return p. + let requestObject -function isCancelled (fetchParams) { - return fetchParams.controller.state === 'aborted' || - fetchParams.controller.state === 'terminated' -} + try { + requestObject = new Request(input, init) + } catch (e) { + p.reject(e) + return p.promise + } -const normalizeMethodRecord = { - delete: 'DELETE', - DELETE: 'DELETE', - get: 'GET', - GET: 'GET', - head: 'HEAD', - HEAD: 'HEAD', - options: 'OPTIONS', - OPTIONS: 'OPTIONS', - post: 'POST', - POST: 'POST', - put: 'PUT', - PUT: 'PUT' -} + // 3. Let request be requestObject’s request. + const request = requestObject[kState] -// Note: object prototypes should not be able to be referenced. e.g. `Object#hasOwnProperty`. -Object.setPrototypeOf(normalizeMethodRecord, null) + // 4. If requestObject’s signal’s aborted flag is set, then: + if (requestObject.signal.aborted) { + // 1. Abort the fetch() call with p, request, null, and + // requestObject’s signal’s abort reason. + abortFetch(p, request, null, requestObject.signal.reason) -/** - * @see https://fetch.spec.whatwg.org/#concept-method-normalize - * @param {string} method - */ -function normalizeMethod (method) { - return normalizeMethodRecord[method.toLowerCase()] ?? method -} + // 2. Return p. + return p.promise + } -// https://infra.spec.whatwg.org/#serialize-a-javascript-value-to-a-json-string -function serializeJavascriptValueToJSONString (value) { - // 1. Let result be ? Call(%JSON.stringify%, undefined, « value »). - const result = JSON.stringify(value) + // 5. Let globalObject be request’s client’s global object. + const globalObject = request.client.globalObject - // 2. If result is undefined, then throw a TypeError. - if (result === undefined) { - throw new TypeError('Value is not JSON serializable') + // 6. If globalObject is a ServiceWorkerGlobalScope object, then set + // request’s service-workers mode to "none". + if (globalObject?.constructor?.name === 'ServiceWorkerGlobalScope') { + request.serviceWorkers = 'none' } - // 3. Assert: result is a string. - assert(typeof result === 'string') + // 7. Let responseObject be null. + let responseObject = null - // 4. Return result. - return result -} + // 8. Let relevantRealm be this’s relevant Realm. -// https://tc39.es/ecma262/#sec-%25iteratorprototype%25-object -const esIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]())) + // 9. Let locallyAborted be false. + let locallyAborted = false -/** - * @see https://webidl.spec.whatwg.org/#dfn-iterator-prototype-object - * @param {() => unknown[]} iterator - * @param {string} name name of the instance - * @param {'key'|'value'|'key+value'} kind - */ -function makeIterator (iterator, name, kind) { - const object = { - index: 0, - kind, - target: iterator - } + // 10. Let controller be null. + let controller = null - const i = { - next () { - // 1. Let interface be the interface for which the iterator prototype object exists. + // 11. Add the following abort steps to requestObject’s signal: + addAbortListener( + requestObject.signal, + () => { + // 1. Set locallyAborted to true. + locallyAborted = true - // 2. Let thisValue be the this value. + // 2. Assert: controller is non-null. + assert(controller != null) - // 3. Let object be ? ToObject(thisValue). + // 3. Abort controller with requestObject’s signal’s abort reason. + controller.abort(requestObject.signal.reason) - // 4. If object is a platform object, then perform a security - // check, passing: + const realResponse = responseObject?.deref() - // 5. If object is not a default iterator object for interface, - // then throw a TypeError. - if (Object.getPrototypeOf(this) !== i) { - throw new TypeError( - `'next' called on an object that does not implement interface ${name} Iterator.` - ) - } + // 4. Abort the fetch() call with p, request, responseObject, + // and requestObject’s signal’s abort reason. + abortFetch(p, request, realResponse, requestObject.signal.reason) + } + ) - // 6. Let index be object’s index. - // 7. Let kind be object’s kind. - // 8. Let values be object’s target's value pairs to iterate over. - const { index, kind, target } = object - const values = target() + // 12. Let handleFetchDone given response response be to finalize and + // report timing with response, globalObject, and "fetch". + // see function handleFetchDone - // 9. Let len be the length of values. - const len = values.length + // 13. Set controller to the result of calling fetch given request, + // with processResponseEndOfBody set to handleFetchDone, and processResponse + // given response being these substeps: - // 10. If index is greater than or equal to len, then return - // CreateIterResultObject(undefined, true). - if (index >= len) { - return { value: undefined, done: true } - } + const processResponse = (response) => { + // 1. If locallyAborted is true, terminate these substeps. + if (locallyAborted) { + return + } - // 11. Let pair be the entry in values at index index. - const pair = values[index] + // 2. If response’s aborted flag is set, then: + if (response.aborted) { + // 1. Let deserializedError be the result of deserialize a serialized + // abort reason given controller’s serialized abort reason and + // relevantRealm. - // 12. Set object’s index to index + 1. - object.index = index + 1 + // 2. Abort the fetch() call with p, request, responseObject, and + // deserializedError. - // 13. Return the iterator result for pair and kind. - return iteratorResult(pair, kind) - }, - // The class string of an iterator prototype object for a given interface is the - // result of concatenating the identifier of the interface and the string " Iterator". - [Symbol.toStringTag]: `${name} Iterator` - } - - // The [[Prototype]] internal slot of an iterator prototype object must be %IteratorPrototype%. - Object.setPrototypeOf(i, esIteratorPrototype) - // esIteratorPrototype needs to be the prototype of i - // which is the prototype of an empty object. Yes, it's confusing. - return Object.setPrototypeOf({}, i) -} - -// https://webidl.spec.whatwg.org/#iterator-result -function iteratorResult (pair, kind) { - let result - - // 1. Let result be a value determined by the value of kind: - switch (kind) { - case 'key': { - // 1. Let idlKey be pair’s key. - // 2. Let key be the result of converting idlKey to an - // ECMAScript value. - // 3. result is key. - result = pair[0] - break - } - case 'value': { - // 1. Let idlValue be pair’s value. - // 2. Let value be the result of converting idlValue to - // an ECMAScript value. - // 3. result is value. - result = pair[1] - break + abortFetch(p, request, responseObject, controller.serializedAbortReason) + return } - case 'key+value': { - // 1. Let idlKey be pair’s key. - // 2. Let idlValue be pair’s value. - // 3. Let key be the result of converting idlKey to an - // ECMAScript value. - // 4. Let value be the result of converting idlValue to - // an ECMAScript value. - // 5. Let array be ! ArrayCreate(2). - // 6. Call ! CreateDataProperty(array, "0", key). - // 7. Call ! CreateDataProperty(array, "1", value). - // 8. result is array. - result = pair - break + + // 3. If response is a network error, then reject p with a TypeError + // and terminate these substeps. + if (response.type === 'error') { + p.reject(new TypeError('fetch failed', { cause: response.error })) + return } + + // 4. Set responseObject to the result of creating a Response object, + // given response, "immutable", and relevantRealm. + responseObject = new WeakRef(fromInnerResponse(response, 'immutable')) + + // 5. Resolve p with responseObject. + p.resolve(responseObject.deref()) + p = null } - // 2. Return CreateIterResultObject(result, false). - return { value: result, done: false } + controller = fetching({ + request, + processResponseEndOfBody: handleFetchDone, + processResponse, + dispatcher: requestObject[kDispatcher] // undici + }) + + // 14. Return p. + return p.promise } -/** - * @see https://fetch.spec.whatwg.org/#body-fully-read - */ -async function fullyReadBody (body, processBody, processBodyError) { - // 1. If taskDestination is null, then set taskDestination to - // the result of starting a new parallel queue. +// https://fetch.spec.whatwg.org/#finalize-and-report-timing +function finalizeAndReportTiming (response, initiatorType = 'other') { + // 1. If response is an aborted network error, then return. + if (response.type === 'error' && response.aborted) { + return + } - // 2. Let successSteps given a byte sequence bytes be to queue a - // fetch task to run processBody given bytes, with taskDestination. - const successSteps = processBody + // 2. If response’s URL list is null or empty, then return. + if (!response.urlList?.length) { + return + } - // 3. Let errorSteps be to queue a fetch task to run processBodyError, - // with taskDestination. - const errorSteps = processBodyError + // 3. Let originalURL be response’s URL list[0]. + const originalURL = response.urlList[0] - // 4. Let reader be the result of getting a reader for body’s stream. - // If that threw an exception, then run errorSteps with that - // exception and return. - let reader + // 4. Let timingInfo be response’s timing info. + let timingInfo = response.timingInfo - try { - reader = body.stream.getReader() - } catch (e) { - errorSteps(e) + // 5. Let cacheState be response’s cache state. + let cacheState = response.cacheState + + // 6. If originalURL’s scheme is not an HTTP(S) scheme, then return. + if (!urlIsHttpHttpsScheme(originalURL)) { return } - // 5. Read all bytes from reader, given successSteps and errorSteps. - try { - const result = await readAllBytes(reader) - successSteps(result) - } catch (e) { - errorSteps(e) + // 7. If timingInfo is null, then return. + if (timingInfo === null) { + return } -} -/** @type {ReadableStream} */ -let ReadableStream = globalThis.ReadableStream + // 8. If response’s timing allow passed flag is not set, then: + if (!response.timingAllowPassed) { + // 1. Set timingInfo to a the result of creating an opaque timing info for timingInfo. + timingInfo = createOpaqueTimingInfo({ + startTime: timingInfo.startTime + }) -function isReadableStreamLike (stream) { - if (!ReadableStream) { - ReadableStream = (__nccwpck_require__(3774).ReadableStream) + // 2. Set cacheState to the empty string. + cacheState = '' } - return stream instanceof ReadableStream || ( - stream[Symbol.toStringTag] === 'ReadableStream' && - typeof stream.tee === 'function' + // 9. Set timingInfo’s end time to the coarsened shared current time + // given global’s relevant settings object’s cross-origin isolated + // capability. + // TODO: given global’s relevant settings object’s cross-origin isolated + // capability? + timingInfo.endTime = coarsenedSharedCurrentTime() + + // 10. Set response’s timing info to timingInfo. + response.timingInfo = timingInfo + + // 11. Mark resource timing for timingInfo, originalURL, initiatorType, + // global, and cacheState. + markResourceTiming( + timingInfo, + originalURL.href, + initiatorType, + globalThis, + cacheState ) } -const MAXIMUM_ARGUMENT_LENGTH = 65535 +// https://w3c.github.io/resource-timing/#dfn-mark-resource-timing +const markResourceTiming = performance.markResourceTiming -/** - * @see https://infra.spec.whatwg.org/#isomorphic-decode - * @param {number[]|Uint8Array} input - */ -function isomorphicDecode (input) { - // 1. To isomorphic decode a byte sequence input, return a string whose code point - // length is equal to input’s length and whose code points have the same values - // as the values of input’s bytes, in the same order. +// https://fetch.spec.whatwg.org/#abort-fetch +function abortFetch (p, request, responseObject, error) { + // 1. Reject promise with error. + if (p) { + // We might have already resolved the promise at this stage + p.reject(error) + } - if (input.length < MAXIMUM_ARGUMENT_LENGTH) { - return String.fromCharCode(...input) + // 2. If request’s body is not null and is readable, then cancel request’s + // body with error. + if (request.body != null && isReadable(request.body?.stream)) { + request.body.stream.cancel(error).catch((err) => { + if (err.code === 'ERR_INVALID_STATE') { + // Node bug? + return + } + throw err + }) } - return input.reduce((previous, current) => previous + String.fromCharCode(current), '') -} + // 3. If responseObject is null, then return. + if (responseObject == null) { + return + } -/** - * @param {ReadableStreamController} controller - */ -function readableStreamClose (controller) { - try { - controller.close() - } catch (err) { - // TODO: add comment explaining why this error occurs. - if (!err.message.includes('Controller is already closed')) { + // 4. Let response be responseObject’s response. + const response = responseObject[kState] + + // 5. If response’s body is not null and is readable, then error response’s + // body with error. + if (response.body != null && isReadable(response.body?.stream)) { + response.body.stream.cancel(error).catch((err) => { + if (err.code === 'ERR_INVALID_STATE') { + // Node bug? + return + } throw err - } + }) } } -/** - * @see https://infra.spec.whatwg.org/#isomorphic-encode - * @param {string} input - */ -function isomorphicEncode (input) { - // 1. Assert: input contains no code points greater than U+00FF. - for (let i = 0; i < input.length; i++) { - assert(input.charCodeAt(i) <= 0xFF) - } +// https://fetch.spec.whatwg.org/#fetching +function fetching ({ + request, + processRequestBodyChunkLength, + processRequestEndOfBody, + processResponse, + processResponseEndOfBody, + processResponseConsumeBody, + useParallelQueue = false, + dispatcher = getGlobalDispatcher() // undici +}) { + // Ensure that the dispatcher is set accordingly + assert(dispatcher) - // 2. Return a byte sequence whose length is equal to input’s code - // point length and whose bytes have the same values as the - // values of input’s code points, in the same order - return input -} + // 1. Let taskDestination be null. + let taskDestination = null -/** - * @see https://streams.spec.whatwg.org/#readablestreamdefaultreader-read-all-bytes - * @see https://streams.spec.whatwg.org/#read-loop - * @param {ReadableStreamDefaultReader} reader - */ -async function readAllBytes (reader) { - const bytes = [] - let byteLength = 0 + // 2. Let crossOriginIsolatedCapability be false. + let crossOriginIsolatedCapability = false - while (true) { - const { done, value: chunk } = await reader.read() + // 3. If request’s client is non-null, then: + if (request.client != null) { + // 1. Set taskDestination to request’s client’s global object. + taskDestination = request.client.globalObject - if (done) { - // 1. Call successSteps with bytes. - return Buffer.concat(bytes, byteLength) - } + // 2. Set crossOriginIsolatedCapability to request’s client’s cross-origin + // isolated capability. + crossOriginIsolatedCapability = + request.client.crossOriginIsolatedCapability + } - // 1. If chunk is not a Uint8Array object, call failureSteps - // with a TypeError and abort these steps. - if (!isUint8Array(chunk)) { - throw new TypeError('Received non-Uint8Array chunk') - } + // 4. If useParallelQueue is true, then set taskDestination to the result of + // starting a new parallel queue. + // TODO - // 2. Append the bytes represented by chunk to bytes. - bytes.push(chunk) - byteLength += chunk.length + // 5. Let timingInfo be a new fetch timing info whose start time and + // post-redirect start time are the coarsened shared current time given + // crossOriginIsolatedCapability. + const currentTime = coarsenedSharedCurrentTime(crossOriginIsolatedCapability) + const timingInfo = createOpaqueTimingInfo({ + startTime: currentTime + }) - // 3. Read-loop given reader, bytes, successSteps, and failureSteps. + // 6. Let fetchParams be a new fetch params whose + // request is request, + // timing info is timingInfo, + // process request body chunk length is processRequestBodyChunkLength, + // process request end-of-body is processRequestEndOfBody, + // process response is processResponse, + // process response consume body is processResponseConsumeBody, + // process response end-of-body is processResponseEndOfBody, + // task destination is taskDestination, + // and cross-origin isolated capability is crossOriginIsolatedCapability. + const fetchParams = { + controller: new Fetch(dispatcher), + request, + timingInfo, + processRequestBodyChunkLength, + processRequestEndOfBody, + processResponse, + processResponseConsumeBody, + processResponseEndOfBody, + taskDestination, + crossOriginIsolatedCapability } -} -/** - * @see https://fetch.spec.whatwg.org/#is-local - * @param {URL} url - */ -function urlIsLocal (url) { - assert('protocol' in url) // ensure it's a url object + // 7. If request’s body is a byte sequence, then set request’s body to + // request’s body as a body. + // NOTE: Since fetching is only called from fetch, body should already be + // extracted. + assert(!request.body || request.body.stream) - const protocol = url.protocol + // 8. If request’s window is "client", then set request’s window to request’s + // client, if request’s client’s global object is a Window object; otherwise + // "no-window". + if (request.window === 'client') { + // TODO: What if request.client is null? + request.window = + request.client?.globalObject?.constructor?.name === 'Window' + ? request.client + : 'no-window' + } - return protocol === 'about:' || protocol === 'blob:' || protocol === 'data:' -} + // 9. If request’s origin is "client", then set request’s origin to request’s + // client’s origin. + if (request.origin === 'client') { + request.origin = request.client.origin + } -/** - * @param {string|URL} url - */ -function urlHasHttpsScheme (url) { - if (typeof url === 'string') { - return url.startsWith('https:') + // 10. If all of the following conditions are true: + // TODO + + // 11. If request’s policy container is "client", then: + if (request.policyContainer === 'client') { + // 1. If request’s client is non-null, then set request’s policy + // container to a clone of request’s client’s policy container. [HTML] + if (request.client != null) { + request.policyContainer = clonePolicyContainer( + request.client.policyContainer + ) + } else { + // 2. Otherwise, set request’s policy container to a new policy + // container. + request.policyContainer = makePolicyContainer() + } } - return url.protocol === 'https:' -} + // 12. If request’s header list does not contain `Accept`, then: + if (!request.headersList.contains('accept', true)) { + // 1. Let value be `*/*`. + const value = '*/*' -/** - * @see https://fetch.spec.whatwg.org/#http-scheme - * @param {URL} url - */ -function urlIsHttpHttpsScheme (url) { - assert('protocol' in url) // ensure it's a url object + // 2. A user agent should set value to the first matching statement, if + // any, switching on request’s destination: + // "document" + // "frame" + // "iframe" + // `text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8` + // "image" + // `image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5` + // "style" + // `text/css,*/*;q=0.1` + // TODO - const protocol = url.protocol + // 3. Append `Accept`/value to request’s header list. + request.headersList.append('accept', value, true) + } - return protocol === 'http:' || protocol === 'https:' -} + // 13. If request’s header list does not contain `Accept-Language`, then + // user agents should append `Accept-Language`/an appropriate value to + // request’s header list. + if (!request.headersList.contains('accept-language', true)) { + request.headersList.append('accept-language', '*', true) + } -/** - * Fetch supports node >= 16.8.0, but Object.hasOwn was added in v16.9.0. - */ -const hasOwn = Object.hasOwn || ((dict, key) => Object.prototype.hasOwnProperty.call(dict, key)) + // 14. If request’s priority is null, then use request’s initiator and + // destination appropriately in setting request’s priority to a + // user-agent-defined object. + if (request.priority === null) { + // TODO + } -module.exports = { - isAborted, - isCancelled, - createDeferredPromise, - ReadableStreamFrom, - toUSVString, - tryUpgradeRequestToAPotentiallyTrustworthyURL, - coarsenedSharedCurrentTime, - determineRequestsReferrer, - makePolicyContainer, - clonePolicyContainer, - appendFetchMetadata, - appendRequestOriginHeader, - TAOCheck, - corsCheck, - crossOriginResourcePolicyCheck, - createOpaqueTimingInfo, - setRequestReferrerPolicyOnRedirect, - isValidHTTPToken, - requestBadPort, - requestCurrentURL, - responseURL, - responseLocationURL, - isBlobLike, - isURLPotentiallyTrustworthy, - isValidReasonPhrase, - sameOrigin, - normalizeMethod, - serializeJavascriptValueToJSONString, - makeIterator, - isValidHeaderName, - isValidHeaderValue, - hasOwn, - isErrorLike, - fullyReadBody, - bytesMatch, - isReadableStreamLike, - readableStreamClose, - isomorphicEncode, - isomorphicDecode, - urlIsLocal, - urlHasHttpsScheme, - urlIsHttpHttpsScheme, - readAllBytes, - normalizeMethodRecord, - parseMetadata -} + // 15. If request is a subresource request, then: + if (subresourceSet.has(request.destination)) { + // TODO + } + // 16. Run main fetch given fetchParams. + mainFetch(fetchParams) + .catch(err => { + fetchParams.controller.terminate(err) + }) -/***/ }), + // 17. Return fetchParam's controller + return fetchParams.controller +} -/***/ 8201: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +// https://fetch.spec.whatwg.org/#concept-main-fetch +async function mainFetch (fetchParams, recursive = false) { + // 1. Let request be fetchParams’s request. + const request = fetchParams.request -"use strict"; + // 2. Let response be null. + let response = null + // 3. If request’s local-URLs-only flag is set and request’s current URL is + // not local, then set response to a network error. + if (request.localURLsOnly && !urlIsLocal(requestCurrentURL(request))) { + response = makeNetworkError('local URLs only') + } -const { types } = __nccwpck_require__(9023) -const { hasOwn, toUSVString } = __nccwpck_require__(1612) + // 4. Run report Content Security Policy violations for request. + // TODO -/** @type {import('../../types/webidl').Webidl} */ -const webidl = {} -webidl.converters = {} -webidl.util = {} -webidl.errors = {} + // 5. Upgrade request to a potentially trustworthy URL, if appropriate. + tryUpgradeRequestToAPotentiallyTrustworthyURL(request) -webidl.errors.exception = function (message) { - return new TypeError(`${message.header}: ${message.message}`) -} + // 6. If should request be blocked due to a bad port, should fetching request + // be blocked as mixed content, or should request be blocked by Content + // Security Policy returns blocked, then set response to a network error. + if (requestBadPort(request) === 'blocked') { + response = makeNetworkError('bad port') + } + // TODO: should fetching request be blocked as mixed content? + // TODO: should request be blocked by Content Security Policy? -webidl.errors.conversionFailed = function (context) { - const plural = context.types.length === 1 ? '' : ' one of' - const message = - `${context.argument} could not be converted to` + - `${plural}: ${context.types.join(', ')}.` + // 7. If request’s referrer policy is the empty string, then set request’s + // referrer policy to request’s policy container’s referrer policy. + if (request.referrerPolicy === '') { + request.referrerPolicy = request.policyContainer.referrerPolicy + } - return webidl.errors.exception({ - header: context.prefix, - message - }) -} + // 8. If request’s referrer is not "no-referrer", then set request’s + // referrer to the result of invoking determine request’s referrer. + if (request.referrer !== 'no-referrer') { + request.referrer = determineRequestsReferrer(request) + } -webidl.errors.invalidArgument = function (context) { - return webidl.errors.exception({ - header: context.prefix, - message: `"${context.value}" is an invalid ${context.type}.` - }) -} + // 9. Set request’s current URL’s scheme to "https" if all of the following + // conditions are true: + // - request’s current URL’s scheme is "http" + // - request’s current URL’s host is a domain + // - Matching request’s current URL’s host per Known HSTS Host Domain Name + // Matching results in either a superdomain match with an asserted + // includeSubDomains directive or a congruent match (with or without an + // asserted includeSubDomains directive). [HSTS] + // TODO -// https://webidl.spec.whatwg.org/#implements -webidl.brandCheck = function (V, I, opts = undefined) { - if (opts?.strict !== false && !(V instanceof I)) { - throw new TypeError('Illegal invocation') - } else { - return V?.[Symbol.toStringTag] === I.prototype[Symbol.toStringTag] - } -} + // 10. If recursive is false, then run the remaining steps in parallel. + // TODO -webidl.argumentLengthCheck = function ({ length }, min, ctx) { - if (length < min) { - throw webidl.errors.exception({ - message: `${min} argument${min !== 1 ? 's' : ''} required, ` + - `but${length ? ' only' : ''} ${length} found.`, - ...ctx - }) - } -} + // 11. If response is null, then set response to the result of running + // the steps corresponding to the first matching statement: + if (response === null) { + response = await (async () => { + const currentURL = requestCurrentURL(request) -webidl.illegalConstructor = function () { - throw webidl.errors.exception({ - header: 'TypeError', - message: 'Illegal constructor' - }) -} + if ( + // - request’s current URL’s origin is same origin with request’s origin, + // and request’s response tainting is "basic" + (sameOrigin(currentURL, request.url) && request.responseTainting === 'basic') || + // request’s current URL’s scheme is "data" + (currentURL.protocol === 'data:') || + // - request’s mode is "navigate" or "websocket" + (request.mode === 'navigate' || request.mode === 'websocket') + ) { + // 1. Set request’s response tainting to "basic". + request.responseTainting = 'basic' -// https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values -webidl.util.Type = function (V) { - switch (typeof V) { - case 'undefined': return 'Undefined' - case 'boolean': return 'Boolean' - case 'string': return 'String' - case 'symbol': return 'Symbol' - case 'number': return 'Number' - case 'bigint': return 'BigInt' - case 'function': - case 'object': { - if (V === null) { - return 'Null' + // 2. Return the result of running scheme fetch given fetchParams. + return await schemeFetch(fetchParams) } - return 'Object' - } - } -} + // request’s mode is "same-origin" + if (request.mode === 'same-origin') { + // 1. Return a network error. + return makeNetworkError('request mode cannot be "same-origin"') + } -// https://webidl.spec.whatwg.org/#abstract-opdef-converttoint -webidl.util.ConvertToInt = function (V, bitLength, signedness, opts = {}) { - let upperBound - let lowerBound + // request’s mode is "no-cors" + if (request.mode === 'no-cors') { + // 1. If request’s redirect mode is not "follow", then return a network + // error. + if (request.redirect !== 'follow') { + return makeNetworkError( + 'redirect mode cannot be "follow" for "no-cors" request' + ) + } - // 1. If bitLength is 64, then: - if (bitLength === 64) { - // 1. Let upperBound be 2^53 − 1. - upperBound = Math.pow(2, 53) - 1 + // 2. Set request’s response tainting to "opaque". + request.responseTainting = 'opaque' - // 2. If signedness is "unsigned", then let lowerBound be 0. - if (signedness === 'unsigned') { - lowerBound = 0 - } else { - // 3. Otherwise let lowerBound be −2^53 + 1. - lowerBound = Math.pow(-2, 53) + 1 - } - } else if (signedness === 'unsigned') { - // 2. Otherwise, if signedness is "unsigned", then: + // 3. Return the result of running scheme fetch given fetchParams. + return await schemeFetch(fetchParams) + } - // 1. Let lowerBound be 0. - lowerBound = 0 + // request’s current URL’s scheme is not an HTTP(S) scheme + if (!urlIsHttpHttpsScheme(requestCurrentURL(request))) { + // Return a network error. + return makeNetworkError('URL scheme must be a HTTP(S) scheme') + } - // 2. Let upperBound be 2^bitLength − 1. - upperBound = Math.pow(2, bitLength) - 1 - } else { - // 3. Otherwise: + // - request’s use-CORS-preflight flag is set + // - request’s unsafe-request flag is set and either request’s method is + // not a CORS-safelisted method or CORS-unsafe request-header names with + // request’s header list is not empty + // 1. Set request’s response tainting to "cors". + // 2. Let corsWithPreflightResponse be the result of running HTTP fetch + // given fetchParams and true. + // 3. If corsWithPreflightResponse is a network error, then clear cache + // entries using request. + // 4. Return corsWithPreflightResponse. + // TODO - // 1. Let lowerBound be -2^bitLength − 1. - lowerBound = Math.pow(-2, bitLength) - 1 + // Otherwise + // 1. Set request’s response tainting to "cors". + request.responseTainting = 'cors' - // 2. Let upperBound be 2^bitLength − 1 − 1. - upperBound = Math.pow(2, bitLength - 1) - 1 + // 2. Return the result of running HTTP fetch given fetchParams. + return await httpFetch(fetchParams) + })() } - // 4. Let x be ? ToNumber(V). - let x = Number(V) - - // 5. If x is −0, then set x to +0. - if (x === 0) { - x = 0 + // 12. If recursive is true, then return response. + if (recursive) { + return response } - // 6. If the conversion is to an IDL type associated - // with the [EnforceRange] extended attribute, then: - if (opts.enforceRange === true) { - // 1. If x is NaN, +∞, or −∞, then throw a TypeError. - if ( - Number.isNaN(x) || - x === Number.POSITIVE_INFINITY || - x === Number.NEGATIVE_INFINITY - ) { - throw webidl.errors.exception({ - header: 'Integer conversion', - message: `Could not convert ${V} to an integer.` - }) + // 13. If response is not a network error and response is not a filtered + // response, then: + if (response.status !== 0 && !response.internalResponse) { + // If request’s response tainting is "cors", then: + if (request.responseTainting === 'cors') { + // 1. Let headerNames be the result of extracting header list values + // given `Access-Control-Expose-Headers` and response’s header list. + // TODO + // 2. If request’s credentials mode is not "include" and headerNames + // contains `*`, then set response’s CORS-exposed header-name list to + // all unique header names in response’s header list. + // TODO + // 3. Otherwise, if headerNames is not null or failure, then set + // response’s CORS-exposed header-name list to headerNames. + // TODO } - // 2. Set x to IntegerPart(x). - x = webidl.util.IntegerPart(x) - - // 3. If x < lowerBound or x > upperBound, then - // throw a TypeError. - if (x < lowerBound || x > upperBound) { - throw webidl.errors.exception({ - header: 'Integer conversion', - message: `Value must be between ${lowerBound}-${upperBound}, got ${x}.` - }) + // Set response to the following filtered response with response as its + // internal response, depending on request’s response tainting: + if (request.responseTainting === 'basic') { + response = filterResponse(response, 'basic') + } else if (request.responseTainting === 'cors') { + response = filterResponse(response, 'cors') + } else if (request.responseTainting === 'opaque') { + response = filterResponse(response, 'opaque') + } else { + assert(false) } + } - // 4. Return x. - return x + // 14. Let internalResponse be response, if response is a network error, + // and response’s internal response otherwise. + let internalResponse = + response.status === 0 ? response : response.internalResponse + + // 15. If internalResponse’s URL list is empty, then set it to a clone of + // request’s URL list. + if (internalResponse.urlList.length === 0) { + internalResponse.urlList.push(...request.urlList) } - // 7. If x is not NaN and the conversion is to an IDL - // type associated with the [Clamp] extended - // attribute, then: - if (!Number.isNaN(x) && opts.clamp === true) { - // 1. Set x to min(max(x, lowerBound), upperBound). - x = Math.min(Math.max(x, lowerBound), upperBound) + // 16. If request’s timing allow failed flag is unset, then set + // internalResponse’s timing allow passed flag. + if (!request.timingAllowFailed) { + response.timingAllowPassed = true + } - // 2. Round x to the nearest integer, choosing the - // even integer if it lies halfway between two, - // and choosing +0 rather than −0. - if (Math.floor(x) % 2 === 0) { - x = Math.floor(x) - } else { - x = Math.ceil(x) - } + // 17. If response is not a network error and any of the following returns + // blocked + // - should internalResponse to request be blocked as mixed content + // - should internalResponse to request be blocked by Content Security Policy + // - should internalResponse to request be blocked due to its MIME type + // - should internalResponse to request be blocked due to nosniff + // TODO - // 3. Return x. - return x + // 18. If response’s type is "opaque", internalResponse’s status is 206, + // internalResponse’s range-requested flag is set, and request’s header + // list does not contain `Range`, then set response and internalResponse + // to a network error. + if ( + response.type === 'opaque' && + internalResponse.status === 206 && + internalResponse.rangeRequested && + !request.headers.contains('range', true) + ) { + response = internalResponse = makeNetworkError() } - // 8. If x is NaN, +0, +∞, or −∞, then return +0. + // 19. If response is not a network error and either request’s method is + // `HEAD` or `CONNECT`, or internalResponse’s status is a null body status, + // set internalResponse’s body to null and disregard any enqueuing toward + // it (if any). if ( - Number.isNaN(x) || - (x === 0 && Object.is(0, x)) || - x === Number.POSITIVE_INFINITY || - x === Number.NEGATIVE_INFINITY + response.status !== 0 && + (request.method === 'HEAD' || + request.method === 'CONNECT' || + nullBodyStatus.includes(internalResponse.status)) ) { - return 0 + internalResponse.body = null + fetchParams.controller.dump = true } - // 9. Set x to IntegerPart(x). - x = webidl.util.IntegerPart(x) + // 20. If request’s integrity metadata is not the empty string, then: + if (request.integrity) { + // 1. Let processBodyError be this step: run fetch finale given fetchParams + // and a network error. + const processBodyError = (reason) => + fetchFinale(fetchParams, makeNetworkError(reason)) - // 10. Set x to x modulo 2^bitLength. - x = x % Math.pow(2, bitLength) + // 2. If request’s response tainting is "opaque", or response’s body is null, + // then run processBodyError and abort these steps. + if (request.responseTainting === 'opaque' || response.body == null) { + processBodyError(response.error) + return + } - // 11. If signedness is "signed" and x ≥ 2^bitLength − 1, - // then return x − 2^bitLength. - if (signedness === 'signed' && x >= Math.pow(2, bitLength) - 1) { - return x - Math.pow(2, bitLength) - } + // 3. Let processBody given bytes be these steps: + const processBody = (bytes) => { + // 1. If bytes do not match request’s integrity metadata, + // then run processBodyError and abort these steps. [SRI] + if (!bytesMatch(bytes, request.integrity)) { + processBodyError('integrity mismatch') + return + } - // 12. Otherwise, return x. - return x -} + // 2. Set response’s body to bytes as a body. + response.body = safelyExtractBody(bytes)[0] -// https://webidl.spec.whatwg.org/#abstract-opdef-integerpart -webidl.util.IntegerPart = function (n) { - // 1. Let r be floor(abs(n)). - const r = Math.floor(Math.abs(n)) + // 3. Run fetch finale given fetchParams and response. + fetchFinale(fetchParams, response) + } - // 2. If n < 0, then return -1 × r. - if (n < 0) { - return -1 * r + // 4. Fully read response’s body given processBody and processBodyError. + await fullyReadBody(response.body, processBody, processBodyError) + } else { + // 21. Otherwise, run fetch finale given fetchParams and response. + fetchFinale(fetchParams, response) } - - // 3. Otherwise, return r. - return r } -// https://webidl.spec.whatwg.org/#es-sequence -webidl.sequenceConverter = function (converter) { - return (V) => { - // 1. If Type(V) is not Object, throw a TypeError. - if (webidl.util.Type(V) !== 'Object') { - throw webidl.errors.exception({ - header: 'Sequence', - message: `Value of type ${webidl.util.Type(V)} is not an Object.` - }) - } +// https://fetch.spec.whatwg.org/#concept-scheme-fetch +// given a fetch params fetchParams +function schemeFetch (fetchParams) { + // Note: since the connection is destroyed on redirect, which sets fetchParams to a + // cancelled state, we do not want this condition to trigger *unless* there have been + // no redirects. See https://github.com/nodejs/undici/issues/1776 + // 1. If fetchParams is canceled, then return the appropriate network error for fetchParams. + if (isCancelled(fetchParams) && fetchParams.request.redirectCount === 0) { + return Promise.resolve(makeAppropriateNetworkError(fetchParams)) + } - // 2. Let method be ? GetMethod(V, @@iterator). - /** @type {Generator} */ - const method = V?.[Symbol.iterator]?.() - const seq = [] + // 2. Let request be fetchParams’s request. + const { request } = fetchParams - // 3. If method is undefined, throw a TypeError. - if ( - method === undefined || - typeof method.next !== 'function' - ) { - throw webidl.errors.exception({ - header: 'Sequence', - message: 'Object is not an iterator.' - }) - } + const { protocol: scheme } = requestCurrentURL(request) - // https://webidl.spec.whatwg.org/#create-sequence-from-iterable - while (true) { - const { done, value } = method.next() + // 3. Switch on request’s current URL’s scheme and run the associated steps: + switch (scheme) { + case 'about:': { + // If request’s current URL’s path is the string "blank", then return a new response + // whose status message is `OK`, header list is « (`Content-Type`, `text/html;charset=utf-8`) », + // and body is the empty byte sequence as a body. - if (done) { - break + // Otherwise, return a network error. + return Promise.resolve(makeNetworkError('about scheme is not supported')) + } + case 'blob:': { + if (!resolveObjectURL) { + resolveObjectURL = (__nccwpck_require__(4573).resolveObjectURL) } - seq.push(converter(value)) - } + // 1. Let blobURLEntry be request’s current URL’s blob URL entry. + const blobURLEntry = requestCurrentURL(request) - return seq - } -} + // https://github.com/web-platform-tests/wpt/blob/7b0ebaccc62b566a1965396e5be7bb2bc06f841f/FileAPI/url/resources/fetch-tests.js#L52-L56 + // Buffer.resolveObjectURL does not ignore URL queries. + if (blobURLEntry.search.length !== 0) { + return Promise.resolve(makeNetworkError('NetworkError when attempting to fetch resource.')) + } -// https://webidl.spec.whatwg.org/#es-to-record -webidl.recordConverter = function (keyConverter, valueConverter) { - return (O) => { - // 1. If Type(O) is not Object, throw a TypeError. - if (webidl.util.Type(O) !== 'Object') { - throw webidl.errors.exception({ - header: 'Record', - message: `Value of type ${webidl.util.Type(O)} is not an Object.` - }) - } + const blob = resolveObjectURL(blobURLEntry.toString()) - // 2. Let result be a new empty instance of record. - const result = {} + // 2. If request’s method is not `GET`, blobURLEntry is null, or blobURLEntry’s + // object is not a Blob object, then return a network error. + if (request.method !== 'GET' || !isBlobLike(blob)) { + return Promise.resolve(makeNetworkError('invalid method')) + } - if (!types.isProxy(O)) { - // Object.keys only returns enumerable properties - const keys = Object.keys(O) + // 3. Let blob be blobURLEntry’s object. + // Note: done above - for (const key of keys) { - // 1. Let typedKey be key converted to an IDL value of type K. - const typedKey = keyConverter(key) + // 4. Let response be a new response. + const response = makeResponse() - // 2. Let value be ? Get(O, key). - // 3. Let typedValue be value converted to an IDL value of type V. - const typedValue = valueConverter(O[key]) + // 5. Let fullLength be blob’s size. + const fullLength = blob.size - // 4. Set result[typedKey] to typedValue. - result[typedKey] = typedValue - } + // 6. Let serializedFullLength be fullLength, serialized and isomorphic encoded. + const serializedFullLength = isomorphicEncode(`${fullLength}`) - // 5. Return result. - return result - } + // 7. Let type be blob’s type. + const type = blob.type - // 3. Let keys be ? O.[[OwnPropertyKeys]](). - const keys = Reflect.ownKeys(O) - - // 4. For each key of keys. - for (const key of keys) { - // 1. Let desc be ? O.[[GetOwnProperty]](key). - const desc = Reflect.getOwnPropertyDescriptor(O, key) + // 8. If request’s header list does not contain `Range`: + // 9. Otherwise: + if (!request.headersList.contains('range', true)) { + // 1. Let bodyWithType be the result of safely extracting blob. + // Note: in the FileAPI a blob "object" is a Blob *or* a MediaSource. + // In node, this can only ever be a Blob. Therefore we can safely + // use extractBody directly. + const bodyWithType = extractBody(blob) - // 2. If desc is not undefined and desc.[[Enumerable]] is true: - if (desc?.enumerable) { - // 1. Let typedKey be key converted to an IDL value of type K. - const typedKey = keyConverter(key) + // 2. Set response’s status message to `OK`. + response.statusText = 'OK' - // 2. Let value be ? Get(O, key). - // 3. Let typedValue be value converted to an IDL value of type V. - const typedValue = valueConverter(O[key]) + // 3. Set response’s body to bodyWithType’s body. + response.body = bodyWithType[0] - // 4. Set result[typedKey] to typedValue. - result[typedKey] = typedValue - } - } + // 4. Set response’s header list to « (`Content-Length`, serializedFullLength), (`Content-Type`, type) ». + response.headersList.set('content-length', serializedFullLength, true) + response.headersList.set('content-type', type, true) + } else { + // 1. Set response’s range-requested flag. + response.rangeRequested = true - // 5. Return result. - return result - } -} + // 2. Let rangeHeader be the result of getting `Range` from request’s header list. + const rangeHeader = request.headersList.get('range', true) -webidl.interfaceConverter = function (i) { - return (V, opts = {}) => { - if (opts.strict !== false && !(V instanceof i)) { - throw webidl.errors.exception({ - header: i.name, - message: `Expected ${V} to be an instance of ${i.name}.` - }) - } + // 3. Let rangeValue be the result of parsing a single range header value given rangeHeader and true. + const rangeValue = simpleRangeHeaderValue(rangeHeader, true) - return V - } -} + // 4. If rangeValue is failure, then return a network error. + if (rangeValue === 'failure') { + return Promise.resolve(makeNetworkError('failed to fetch the data URL')) + } -webidl.dictionaryConverter = function (converters) { - return (dictionary) => { - const type = webidl.util.Type(dictionary) - const dict = {} + // 5. Let (rangeStart, rangeEnd) be rangeValue. + let { rangeStartValue: rangeStart, rangeEndValue: rangeEnd } = rangeValue - if (type === 'Null' || type === 'Undefined') { - return dict - } else if (type !== 'Object') { - throw webidl.errors.exception({ - header: 'Dictionary', - message: `Expected ${dictionary} to be one of: Null, Undefined, Object.` - }) - } + // 6. If rangeStart is null: + // 7. Otherwise: + if (rangeStart === null) { + // 1. Set rangeStart to fullLength − rangeEnd. + rangeStart = fullLength - rangeEnd - for (const options of converters) { - const { key, defaultValue, required, converter } = options + // 2. Set rangeEnd to rangeStart + rangeEnd − 1. + rangeEnd = rangeStart + rangeEnd - 1 + } else { + // 1. If rangeStart is greater than or equal to fullLength, then return a network error. + if (rangeStart >= fullLength) { + return Promise.resolve(makeNetworkError('Range start is greater than the blob\'s size.')) + } - if (required === true) { - if (!hasOwn(dictionary, key)) { - throw webidl.errors.exception({ - header: 'Dictionary', - message: `Missing required key "${key}".` - }) + // 2. If rangeEnd is null or rangeEnd is greater than or equal to fullLength, then set + // rangeEnd to fullLength − 1. + if (rangeEnd === null || rangeEnd >= fullLength) { + rangeEnd = fullLength - 1 + } } - } - let value = dictionary[key] - const hasDefault = hasOwn(options, 'defaultValue') + // 8. Let slicedBlob be the result of invoking slice blob given blob, rangeStart, + // rangeEnd + 1, and type. + const slicedBlob = blob.slice(rangeStart, rangeEnd, type) - // Only use defaultValue if value is undefined and - // a defaultValue options was provided. - if (hasDefault && value !== null) { - value = value ?? defaultValue - } + // 9. Let slicedBodyWithType be the result of safely extracting slicedBlob. + // Note: same reason as mentioned above as to why we use extractBody + const slicedBodyWithType = extractBody(slicedBlob) - // A key can be optional and have no default value. - // When this happens, do not perform a conversion, - // and do not assign the key a value. - if (required || hasDefault || value !== undefined) { - value = converter(value) + // 10. Set response’s body to slicedBodyWithType’s body. + response.body = slicedBodyWithType[0] - if ( - options.allowedValues && - !options.allowedValues.includes(value) - ) { - throw webidl.errors.exception({ - header: 'Dictionary', - message: `${value} is not an accepted type. Expected one of ${options.allowedValues.join(', ')}.` - }) - } + // 11. Let serializedSlicedLength be slicedBlob’s size, serialized and isomorphic encoded. + const serializedSlicedLength = isomorphicEncode(`${slicedBlob.size}`) - dict[key] = value - } - } + // 12. Let contentRange be the result of invoking build a content range given rangeStart, + // rangeEnd, and fullLength. + const contentRange = buildContentRange(rangeStart, rangeEnd, fullLength) - return dict - } -} + // 13. Set response’s status to 206. + response.status = 206 -webidl.nullableConverter = function (converter) { - return (V) => { - if (V === null) { - return V - } + // 14. Set response’s status message to `Partial Content`. + response.statusText = 'Partial Content' - return converter(V) - } -} + // 15. Set response’s header list to « (`Content-Length`, serializedSlicedLength), + // (`Content-Type`, type), (`Content-Range`, contentRange) ». + response.headersList.set('content-length', serializedSlicedLength, true) + response.headersList.set('content-type', type, true) + response.headersList.set('content-range', contentRange, true) + } -// https://webidl.spec.whatwg.org/#es-DOMString -webidl.converters.DOMString = function (V, opts = {}) { - // 1. If V is null and the conversion is to an IDL type - // associated with the [LegacyNullToEmptyString] - // extended attribute, then return the DOMString value - // that represents the empty string. - if (V === null && opts.legacyNullToEmptyString) { - return '' - } + // 10. Return response. + return Promise.resolve(response) + } + case 'data:': { + // 1. Let dataURLStruct be the result of running the + // data: URL processor on request’s current URL. + const currentURL = requestCurrentURL(request) + const dataURLStruct = dataURLProcessor(currentURL) - // 2. Let x be ? ToString(V). - if (typeof V === 'symbol') { - throw new TypeError('Could not convert argument of type symbol to string.') - } + // 2. If dataURLStruct is failure, then return a + // network error. + if (dataURLStruct === 'failure') { + return Promise.resolve(makeNetworkError('failed to fetch the data URL')) + } - // 3. Return the IDL DOMString value that represents the - // same sequence of code units as the one the - // ECMAScript String value x represents. - return String(V) -} + // 3. Let mimeType be dataURLStruct’s MIME type, serialized. + const mimeType = serializeAMimeType(dataURLStruct.mimeType) -// https://webidl.spec.whatwg.org/#es-ByteString -webidl.converters.ByteString = function (V) { - // 1. Let x be ? ToString(V). - // Note: DOMString converter perform ? ToString(V) - const x = webidl.converters.DOMString(V) + // 4. Return a response whose status message is `OK`, + // header list is « (`Content-Type`, mimeType) », + // and body is dataURLStruct’s body as a body. + return Promise.resolve(makeResponse({ + statusText: 'OK', + headersList: [ + ['content-type', { name: 'Content-Type', value: mimeType }] + ], + body: safelyExtractBody(dataURLStruct.body)[0] + })) + } + case 'file:': { + // For now, unfortunate as it is, file URLs are left as an exercise for the reader. + // When in doubt, return a network error. + return Promise.resolve(makeNetworkError('not implemented... yet...')) + } + case 'http:': + case 'https:': { + // Return the result of running HTTP fetch given fetchParams. - // 2. If the value of any element of x is greater than - // 255, then throw a TypeError. - for (let index = 0; index < x.length; index++) { - if (x.charCodeAt(index) > 255) { - throw new TypeError( - 'Cannot convert argument to a ByteString because the character at ' + - `index ${index} has a value of ${x.charCodeAt(index)} which is greater than 255.` - ) + return httpFetch(fetchParams) + .catch((err) => makeNetworkError(err)) + } + default: { + return Promise.resolve(makeNetworkError('unknown scheme')) } } - - // 3. Return an IDL ByteString value whose length is the - // length of x, and where the value of each element is - // the value of the corresponding element of x. - return x } -// https://webidl.spec.whatwg.org/#es-USVString -webidl.converters.USVString = toUSVString - -// https://webidl.spec.whatwg.org/#es-boolean -webidl.converters.boolean = function (V) { - // 1. Let x be the result of computing ToBoolean(V). - const x = Boolean(V) +// https://fetch.spec.whatwg.org/#finalize-response +function finalizeResponse (fetchParams, response) { + // 1. Set fetchParams’s request’s done flag. + fetchParams.request.done = true - // 2. Return the IDL boolean value that is the one that represents - // the same truth value as the ECMAScript Boolean value x. - return x + // 2, If fetchParams’s process response done is not null, then queue a fetch + // task to run fetchParams’s process response done given response, with + // fetchParams’s task destination. + if (fetchParams.processResponseDone != null) { + queueMicrotask(() => fetchParams.processResponseDone(response)) + } } -// https://webidl.spec.whatwg.org/#es-any -webidl.converters.any = function (V) { - return V -} +// https://fetch.spec.whatwg.org/#fetch-finale +function fetchFinale (fetchParams, response) { + // 1. Let timingInfo be fetchParams’s timing info. + let timingInfo = fetchParams.timingInfo -// https://webidl.spec.whatwg.org/#es-long-long -webidl.converters['long long'] = function (V) { - // 1. Let x be ? ConvertToInt(V, 64, "signed"). - const x = webidl.util.ConvertToInt(V, 64, 'signed') + // 2. If response is not a network error and fetchParams’s request’s client is a secure context, + // then set timingInfo’s server-timing headers to the result of getting, decoding, and splitting + // `Server-Timing` from response’s internal response’s header list. + // TODO - // 2. Return the IDL long long value that represents - // the same numeric value as x. - return x -} + // 3. Let processResponseEndOfBody be the following steps: + const processResponseEndOfBody = () => { + // 1. Let unsafeEndTime be the unsafe shared current time. + const unsafeEndTime = Date.now() // ? -// https://webidl.spec.whatwg.org/#es-unsigned-long-long -webidl.converters['unsigned long long'] = function (V) { - // 1. Let x be ? ConvertToInt(V, 64, "unsigned"). - const x = webidl.util.ConvertToInt(V, 64, 'unsigned') + // 2. If fetchParams’s request’s destination is "document", then set fetchParams’s controller’s + // full timing info to fetchParams’s timing info. + if (fetchParams.request.destination === 'document') { + fetchParams.controller.fullTimingInfo = timingInfo + } - // 2. Return the IDL unsigned long long value that - // represents the same numeric value as x. - return x -} + // 3. Set fetchParams’s controller’s report timing steps to the following steps given a global object global: + fetchParams.controller.reportTimingSteps = () => { + // 1. If fetchParams’s request’s URL’s scheme is not an HTTP(S) scheme, then return. + if (fetchParams.request.url.protocol !== 'https:') { + return + } -// https://webidl.spec.whatwg.org/#es-unsigned-long -webidl.converters['unsigned long'] = function (V) { - // 1. Let x be ? ConvertToInt(V, 32, "unsigned"). - const x = webidl.util.ConvertToInt(V, 32, 'unsigned') + // 2. Set timingInfo’s end time to the relative high resolution time given unsafeEndTime and global. + timingInfo.endTime = unsafeEndTime - // 2. Return the IDL unsigned long value that - // represents the same numeric value as x. - return x -} + // 3. Let cacheState be response’s cache state. + let cacheState = response.cacheState -// https://webidl.spec.whatwg.org/#es-unsigned-short -webidl.converters['unsigned short'] = function (V, opts) { - // 1. Let x be ? ConvertToInt(V, 16, "unsigned"). - const x = webidl.util.ConvertToInt(V, 16, 'unsigned', opts) + // 4. Let bodyInfo be response’s body info. + const bodyInfo = response.bodyInfo - // 2. Return the IDL unsigned short value that represents - // the same numeric value as x. - return x -} + // 5. If response’s timing allow passed flag is not set, then set timingInfo to the result of creating an + // opaque timing info for timingInfo and set cacheState to the empty string. + if (!response.timingAllowPassed) { + timingInfo = createOpaqueTimingInfo(timingInfo) -// https://webidl.spec.whatwg.org/#idl-ArrayBuffer -webidl.converters.ArrayBuffer = function (V, opts = {}) { - // 1. If Type(V) is not Object, or V does not have an - // [[ArrayBufferData]] internal slot, then throw a - // TypeError. - // see: https://tc39.es/ecma262/#sec-properties-of-the-arraybuffer-instances - // see: https://tc39.es/ecma262/#sec-properties-of-the-sharedarraybuffer-instances - if ( - webidl.util.Type(V) !== 'Object' || - !types.isAnyArrayBuffer(V) - ) { - throw webidl.errors.conversionFailed({ - prefix: `${V}`, - argument: `${V}`, - types: ['ArrayBuffer'] - }) - } + cacheState = '' + } - // 2. If the conversion is not to an IDL type associated - // with the [AllowShared] extended attribute, and - // IsSharedArrayBuffer(V) is true, then throw a - // TypeError. - if (opts.allowShared === false && types.isSharedArrayBuffer(V)) { - throw webidl.errors.exception({ - header: 'ArrayBuffer', - message: 'SharedArrayBuffer is not allowed.' - }) - } + // 6. Let responseStatus be 0. + let responseStatus = 0 - // 3. If the conversion is not to an IDL type associated - // with the [AllowResizable] extended attribute, and - // IsResizableArrayBuffer(V) is true, then throw a - // TypeError. - // Note: resizable ArrayBuffers are currently a proposal. + // 7. If fetchParams’s request’s mode is not "navigate" or response’s has-cross-origin-redirects is false: + if (fetchParams.request.mode !== 'navigator' || !response.hasCrossOriginRedirects) { + // 1. Set responseStatus to response’s status. + responseStatus = response.status - // 4. Return the IDL ArrayBuffer value that is a - // reference to the same object as V. - return V -} + // 2. Let mimeType be the result of extracting a MIME type from response’s header list. + const mimeType = extractMimeType(response.headersList) -webidl.converters.TypedArray = function (V, T, opts = {}) { - // 1. Let T be the IDL type V is being converted to. + // 3. If mimeType is not failure, then set bodyInfo’s content type to the result of minimizing a supported MIME type given mimeType. + if (mimeType !== 'failure') { + bodyInfo.contentType = minimizeSupportedMimeType(mimeType) + } + } - // 2. If Type(V) is not Object, or V does not have a - // [[TypedArrayName]] internal slot with a value - // equal to T’s name, then throw a TypeError. - if ( - webidl.util.Type(V) !== 'Object' || - !types.isTypedArray(V) || - V.constructor.name !== T.name - ) { - throw webidl.errors.conversionFailed({ - prefix: `${T.name}`, - argument: `${V}`, - types: [T.name] - }) - } + // 8. If fetchParams’s request’s initiator type is non-null, then mark resource timing given timingInfo, + // fetchParams’s request’s URL, fetchParams’s request’s initiator type, global, cacheState, bodyInfo, + // and responseStatus. + if (fetchParams.request.initiatorType != null) { + // TODO: update markresourcetiming + markResourceTiming(timingInfo, fetchParams.request.url.href, fetchParams.request.initiatorType, globalThis, cacheState, bodyInfo, responseStatus) + } + } - // 3. If the conversion is not to an IDL type associated - // with the [AllowShared] extended attribute, and - // IsSharedArrayBuffer(V.[[ViewedArrayBuffer]]) is - // true, then throw a TypeError. - if (opts.allowShared === false && types.isSharedArrayBuffer(V.buffer)) { - throw webidl.errors.exception({ - header: 'ArrayBuffer', - message: 'SharedArrayBuffer is not allowed.' - }) - } + // 4. Let processResponseEndOfBodyTask be the following steps: + const processResponseEndOfBodyTask = () => { + // 1. Set fetchParams’s request’s done flag. + fetchParams.request.done = true - // 4. If the conversion is not to an IDL type associated - // with the [AllowResizable] extended attribute, and - // IsResizableArrayBuffer(V.[[ViewedArrayBuffer]]) is - // true, then throw a TypeError. - // Note: resizable array buffers are currently a proposal + // 2. If fetchParams’s process response end-of-body is non-null, then run fetchParams’s process + // response end-of-body given response. + if (fetchParams.processResponseEndOfBody != null) { + queueMicrotask(() => fetchParams.processResponseEndOfBody(response)) + } - // 5. Return the IDL value of type T that is a reference - // to the same object as V. - return V -} + // 3. If fetchParams’s request’s initiator type is non-null and fetchParams’s request’s client’s + // global object is fetchParams’s task destination, then run fetchParams’s controller’s report + // timing steps given fetchParams’s request’s client’s global object. + if (fetchParams.request.initiatorType != null) { + fetchParams.controller.reportTimingSteps() + } + } -webidl.converters.DataView = function (V, opts = {}) { - // 1. If Type(V) is not Object, or V does not have a - // [[DataView]] internal slot, then throw a TypeError. - if (webidl.util.Type(V) !== 'Object' || !types.isDataView(V)) { - throw webidl.errors.exception({ - header: 'DataView', - message: 'Object is not a DataView.' - }) + // 5. Queue a fetch task to run processResponseEndOfBodyTask with fetchParams’s task destination + queueMicrotask(() => processResponseEndOfBodyTask()) } - // 2. If the conversion is not to an IDL type associated - // with the [AllowShared] extended attribute, and - // IsSharedArrayBuffer(V.[[ViewedArrayBuffer]]) is true, - // then throw a TypeError. - if (opts.allowShared === false && types.isSharedArrayBuffer(V.buffer)) { - throw webidl.errors.exception({ - header: 'ArrayBuffer', - message: 'SharedArrayBuffer is not allowed.' + // 4. If fetchParams’s process response is non-null, then queue a fetch task to run fetchParams’s + // process response given response, with fetchParams’s task destination. + if (fetchParams.processResponse != null) { + queueMicrotask(() => { + fetchParams.processResponse(response) + fetchParams.processResponse = null }) } - // 3. If the conversion is not to an IDL type associated - // with the [AllowResizable] extended attribute, and - // IsResizableArrayBuffer(V.[[ViewedArrayBuffer]]) is - // true, then throw a TypeError. - // Note: resizable ArrayBuffers are currently a proposal - - // 4. Return the IDL DataView value that is a reference - // to the same object as V. - return V -} + // 5. Let internalResponse be response, if response is a network error; otherwise response’s internal response. + const internalResponse = response.type === 'error' ? response : (response.internalResponse ?? response) -// https://webidl.spec.whatwg.org/#BufferSource -webidl.converters.BufferSource = function (V, opts = {}) { - if (types.isAnyArrayBuffer(V)) { - return webidl.converters.ArrayBuffer(V, opts) - } + // 6. If internalResponse’s body is null, then run processResponseEndOfBody. + // 7. Otherwise: + if (internalResponse.body == null) { + processResponseEndOfBody() + } else { + // mcollina: all the following steps of the specs are skipped. + // The internal transform stream is not needed. + // See https://github.com/nodejs/undici/pull/3093#issuecomment-2050198541 - if (types.isTypedArray(V)) { - return webidl.converters.TypedArray(V, V.constructor) - } + // 1. Let transformStream be a new TransformStream. + // 2. Let identityTransformAlgorithm be an algorithm which, given chunk, enqueues chunk in transformStream. + // 3. Set up transformStream with transformAlgorithm set to identityTransformAlgorithm and flushAlgorithm + // set to processResponseEndOfBody. + // 4. Set internalResponse’s body’s stream to the result of internalResponse’s body’s stream piped through transformStream. - if (types.isDataView(V)) { - return webidl.converters.DataView(V, opts) + finished(internalResponse.body.stream, () => { + processResponseEndOfBody() + }) } - - throw new TypeError(`Could not convert ${V} to a BufferSource.`) } -webidl.converters['sequence'] = webidl.sequenceConverter( - webidl.converters.ByteString -) +// https://fetch.spec.whatwg.org/#http-fetch +async function httpFetch (fetchParams) { + // 1. Let request be fetchParams’s request. + const request = fetchParams.request -webidl.converters['sequence>'] = webidl.sequenceConverter( - webidl.converters['sequence'] -) + // 2. Let response be null. + let response = null -webidl.converters['record'] = webidl.recordConverter( - webidl.converters.ByteString, - webidl.converters.ByteString -) + // 3. Let actualResponse be null. + let actualResponse = null -module.exports = { - webidl -} + // 4. Let timingInfo be fetchParams’s timing info. + const timingInfo = fetchParams.timingInfo + // 5. If request’s service-workers mode is "all", then: + if (request.serviceWorkers === 'all') { + // TODO + } -/***/ }), + // 6. If response is null, then: + if (response === null) { + // 1. If makeCORSPreflight is true and one of these conditions is true: + // TODO -/***/ 7043: -/***/ ((module) => { + // 2. If request’s redirect mode is "follow", then set request’s + // service-workers mode to "none". + if (request.redirect === 'follow') { + request.serviceWorkers = 'none' + } -"use strict"; + // 3. Set response and actualResponse to the result of running + // HTTP-network-or-cache fetch given fetchParams. + actualResponse = response = await httpNetworkOrCacheFetch(fetchParams) + // 4. If request’s response tainting is "cors" and a CORS check + // for request and response returns failure, then return a network error. + if ( + request.responseTainting === 'cors' && + corsCheck(request, response) === 'failure' + ) { + return makeNetworkError('cors failure') + } -/** - * @see https://encoding.spec.whatwg.org/#concept-encoding-get - * @param {string|undefined} label - */ -function getEncoding (label) { - if (!label) { - return 'failure' + // 5. If the TAO check for request and response returns failure, then set + // request’s timing allow failed flag. + if (TAOCheck(request, response) === 'failure') { + request.timingAllowFailed = true + } } - // 1. Remove any leading and trailing ASCII whitespace from label. - // 2. If label is an ASCII case-insensitive match for any of the - // labels listed in the table below, then return the - // corresponding encoding; otherwise return failure. - switch (label.trim().toLowerCase()) { - case 'unicode-1-1-utf-8': - case 'unicode11utf8': - case 'unicode20utf8': - case 'utf-8': - case 'utf8': - case 'x-unicode20utf8': - return 'UTF-8' - case '866': - case 'cp866': - case 'csibm866': - case 'ibm866': - return 'IBM866' - case 'csisolatin2': - case 'iso-8859-2': - case 'iso-ir-101': - case 'iso8859-2': - case 'iso88592': - case 'iso_8859-2': - case 'iso_8859-2:1987': - case 'l2': - case 'latin2': - return 'ISO-8859-2' - case 'csisolatin3': - case 'iso-8859-3': - case 'iso-ir-109': - case 'iso8859-3': - case 'iso88593': - case 'iso_8859-3': - case 'iso_8859-3:1988': - case 'l3': - case 'latin3': - return 'ISO-8859-3' - case 'csisolatin4': - case 'iso-8859-4': - case 'iso-ir-110': - case 'iso8859-4': - case 'iso88594': - case 'iso_8859-4': - case 'iso_8859-4:1988': - case 'l4': - case 'latin4': - return 'ISO-8859-4' - case 'csisolatincyrillic': - case 'cyrillic': - case 'iso-8859-5': - case 'iso-ir-144': - case 'iso8859-5': - case 'iso88595': - case 'iso_8859-5': - case 'iso_8859-5:1988': - return 'ISO-8859-5' - case 'arabic': - case 'asmo-708': - case 'csiso88596e': - case 'csiso88596i': - case 'csisolatinarabic': - case 'ecma-114': - case 'iso-8859-6': - case 'iso-8859-6-e': - case 'iso-8859-6-i': - case 'iso-ir-127': - case 'iso8859-6': - case 'iso88596': - case 'iso_8859-6': - case 'iso_8859-6:1987': - return 'ISO-8859-6' - case 'csisolatingreek': - case 'ecma-118': - case 'elot_928': - case 'greek': - case 'greek8': - case 'iso-8859-7': - case 'iso-ir-126': - case 'iso8859-7': - case 'iso88597': - case 'iso_8859-7': - case 'iso_8859-7:1987': - case 'sun_eu_greek': - return 'ISO-8859-7' - case 'csiso88598e': - case 'csisolatinhebrew': - case 'hebrew': - case 'iso-8859-8': - case 'iso-8859-8-e': - case 'iso-ir-138': - case 'iso8859-8': - case 'iso88598': - case 'iso_8859-8': - case 'iso_8859-8:1988': - case 'visual': - return 'ISO-8859-8' - case 'csiso88598i': - case 'iso-8859-8-i': - case 'logical': - return 'ISO-8859-8-I' - case 'csisolatin6': - case 'iso-8859-10': - case 'iso-ir-157': - case 'iso8859-10': - case 'iso885910': - case 'l6': - case 'latin6': - return 'ISO-8859-10' - case 'iso-8859-13': - case 'iso8859-13': - case 'iso885913': - return 'ISO-8859-13' - case 'iso-8859-14': - case 'iso8859-14': - case 'iso885914': - return 'ISO-8859-14' - case 'csisolatin9': - case 'iso-8859-15': - case 'iso8859-15': - case 'iso885915': - case 'iso_8859-15': - case 'l9': - return 'ISO-8859-15' - case 'iso-8859-16': - return 'ISO-8859-16' - case 'cskoi8r': - case 'koi': - case 'koi8': - case 'koi8-r': - case 'koi8_r': - return 'KOI8-R' - case 'koi8-ru': - case 'koi8-u': - return 'KOI8-U' - case 'csmacintosh': - case 'mac': - case 'macintosh': - case 'x-mac-roman': - return 'macintosh' - case 'iso-8859-11': - case 'iso8859-11': - case 'iso885911': - case 'tis-620': - case 'windows-874': - return 'windows-874' - case 'cp1250': - case 'windows-1250': - case 'x-cp1250': - return 'windows-1250' - case 'cp1251': - case 'windows-1251': - case 'x-cp1251': - return 'windows-1251' - case 'ansi_x3.4-1968': - case 'ascii': - case 'cp1252': - case 'cp819': - case 'csisolatin1': - case 'ibm819': - case 'iso-8859-1': - case 'iso-ir-100': - case 'iso8859-1': - case 'iso88591': - case 'iso_8859-1': - case 'iso_8859-1:1987': - case 'l1': - case 'latin1': - case 'us-ascii': - case 'windows-1252': - case 'x-cp1252': - return 'windows-1252' - case 'cp1253': - case 'windows-1253': - case 'x-cp1253': - return 'windows-1253' - case 'cp1254': - case 'csisolatin5': - case 'iso-8859-9': - case 'iso-ir-148': - case 'iso8859-9': - case 'iso88599': - case 'iso_8859-9': - case 'iso_8859-9:1989': - case 'l5': - case 'latin5': - case 'windows-1254': - case 'x-cp1254': - return 'windows-1254' - case 'cp1255': - case 'windows-1255': - case 'x-cp1255': - return 'windows-1255' - case 'cp1256': - case 'windows-1256': - case 'x-cp1256': - return 'windows-1256' - case 'cp1257': - case 'windows-1257': - case 'x-cp1257': - return 'windows-1257' - case 'cp1258': - case 'windows-1258': - case 'x-cp1258': - return 'windows-1258' - case 'x-mac-cyrillic': - case 'x-mac-ukrainian': - return 'x-mac-cyrillic' - case 'chinese': - case 'csgb2312': - case 'csiso58gb231280': - case 'gb2312': - case 'gb_2312': - case 'gb_2312-80': - case 'gbk': - case 'iso-ir-58': - case 'x-gbk': - return 'GBK' - case 'gb18030': - return 'gb18030' - case 'big5': - case 'big5-hkscs': - case 'cn-big5': - case 'csbig5': - case 'x-x-big5': - return 'Big5' - case 'cseucpkdfmtjapanese': - case 'euc-jp': - case 'x-euc-jp': - return 'EUC-JP' - case 'csiso2022jp': - case 'iso-2022-jp': - return 'ISO-2022-JP' - case 'csshiftjis': - case 'ms932': - case 'ms_kanji': - case 'shift-jis': - case 'shift_jis': - case 'sjis': - case 'windows-31j': - case 'x-sjis': - return 'Shift_JIS' - case 'cseuckr': - case 'csksc56011987': - case 'euc-kr': - case 'iso-ir-149': - case 'korean': - case 'ks_c_5601-1987': - case 'ks_c_5601-1989': - case 'ksc5601': - case 'ksc_5601': - case 'windows-949': - return 'EUC-KR' - case 'csiso2022kr': - case 'hz-gb-2312': - case 'iso-2022-cn': - case 'iso-2022-cn-ext': - case 'iso-2022-kr': - case 'replacement': - return 'replacement' - case 'unicodefffe': - case 'utf-16be': - return 'UTF-16BE' - case 'csunicode': - case 'iso-10646-ucs-2': - case 'ucs-2': - case 'unicode': - case 'unicodefeff': - case 'utf-16': - case 'utf-16le': - return 'UTF-16LE' - case 'x-user-defined': - return 'x-user-defined' - default: return 'failure' + // 7. If either request’s response tainting or response’s type + // is "opaque", and the cross-origin resource policy check with + // request’s origin, request’s client, request’s destination, + // and actualResponse returns blocked, then return a network error. + if ( + (request.responseTainting === 'opaque' || response.type === 'opaque') && + crossOriginResourcePolicyCheck( + request.origin, + request.client, + request.destination, + actualResponse + ) === 'blocked' + ) { + return makeNetworkError('blocked') } -} -module.exports = { - getEncoding -} + // 8. If actualResponse’s status is a redirect status, then: + if (redirectStatusSet.has(actualResponse.status)) { + // 1. If actualResponse’s status is not 303, request’s body is not null, + // and the connection uses HTTP/2, then user agents may, and are even + // encouraged to, transmit an RST_STREAM frame. + // See, https://github.com/whatwg/fetch/issues/1288 + if (request.redirect !== 'manual') { + fetchParams.controller.connection.destroy(undefined, false) + } + // 2. Switch on request’s redirect mode: + if (request.redirect === 'error') { + // Set response to a network error. + response = makeNetworkError('unexpected redirect') + } else if (request.redirect === 'manual') { + // Set response to an opaque-redirect filtered response whose internal + // response is actualResponse. + // NOTE(spec): On the web this would return an `opaqueredirect` response, + // but that doesn't make sense server side. + // See https://github.com/nodejs/undici/issues/1193. + response = actualResponse + } else if (request.redirect === 'follow') { + // Set response to the result of running HTTP-redirect fetch given + // fetchParams and response. + response = await httpRedirectFetch(fetchParams, response) + } else { + assert(false) + } + } -/***/ }), + // 9. Set response’s timing info to timingInfo. + response.timingInfo = timingInfo -/***/ 695: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // 10. Return response. + return response +} -"use strict"; +// https://fetch.spec.whatwg.org/#http-redirect-fetch +function httpRedirectFetch (fetchParams, response) { + // 1. Let request be fetchParams’s request. + const request = fetchParams.request + // 2. Let actualResponse be response, if response is not a filtered response, + // and response’s internal response otherwise. + const actualResponse = response.internalResponse + ? response.internalResponse + : response -const { - staticPropertyDescriptors, - readOperation, - fireAProgressEvent -} = __nccwpck_require__(2214) -const { - kState, - kError, - kResult, - kEvents, - kAborted -} = __nccwpck_require__(9042) -const { webidl } = __nccwpck_require__(8201) -const { kEnumerableProperty } = __nccwpck_require__(5069) + // 3. Let locationURL be actualResponse’s location URL given request’s current + // URL’s fragment. + let locationURL -class FileReader extends EventTarget { - constructor () { - super() + try { + locationURL = responseLocationURL( + actualResponse, + requestCurrentURL(request).hash + ) - this[kState] = 'empty' - this[kResult] = null - this[kError] = null - this[kEvents] = { - loadend: null, - error: null, - abort: null, - load: null, - progress: null, - loadstart: null + // 4. If locationURL is null, then return response. + if (locationURL == null) { + return response } + } catch (err) { + // 5. If locationURL is failure, then return a network error. + return Promise.resolve(makeNetworkError(err)) } - /** - * @see https://w3c.github.io/FileAPI/#dfn-readAsArrayBuffer - * @param {import('buffer').Blob} blob - */ - readAsArrayBuffer (blob) { - webidl.brandCheck(this, FileReader) - - webidl.argumentLengthCheck(arguments, 1, { header: 'FileReader.readAsArrayBuffer' }) - - blob = webidl.converters.Blob(blob, { strict: false }) + // 6. If locationURL’s scheme is not an HTTP(S) scheme, then return a network + // error. + if (!urlIsHttpHttpsScheme(locationURL)) { + return Promise.resolve(makeNetworkError('URL scheme must be a HTTP(S) scheme')) + } - // The readAsArrayBuffer(blob) method, when invoked, - // must initiate a read operation for blob with ArrayBuffer. - readOperation(this, blob, 'ArrayBuffer') + // 7. If request’s redirect count is 20, then return a network error. + if (request.redirectCount === 20) { + return Promise.resolve(makeNetworkError('redirect count exceeded')) } - /** - * @see https://w3c.github.io/FileAPI/#readAsBinaryString - * @param {import('buffer').Blob} blob - */ - readAsBinaryString (blob) { - webidl.brandCheck(this, FileReader) + // 8. Increase request’s redirect count by 1. + request.redirectCount += 1 - webidl.argumentLengthCheck(arguments, 1, { header: 'FileReader.readAsBinaryString' }) + // 9. If request’s mode is "cors", locationURL includes credentials, and + // request’s origin is not same origin with locationURL’s origin, then return + // a network error. + if ( + request.mode === 'cors' && + (locationURL.username || locationURL.password) && + !sameOrigin(request, locationURL) + ) { + return Promise.resolve(makeNetworkError('cross origin not allowed for request mode "cors"')) + } - blob = webidl.converters.Blob(blob, { strict: false }) + // 10. If request’s response tainting is "cors" and locationURL includes + // credentials, then return a network error. + if ( + request.responseTainting === 'cors' && + (locationURL.username || locationURL.password) + ) { + return Promise.resolve(makeNetworkError( + 'URL cannot contain credentials for request mode "cors"' + )) + } - // The readAsBinaryString(blob) method, when invoked, - // must initiate a read operation for blob with BinaryString. - readOperation(this, blob, 'BinaryString') + // 11. If actualResponse’s status is not 303, request’s body is non-null, + // and request’s body’s source is null, then return a network error. + if ( + actualResponse.status !== 303 && + request.body != null && + request.body.source == null + ) { + return Promise.resolve(makeNetworkError()) } - /** - * @see https://w3c.github.io/FileAPI/#readAsDataText - * @param {import('buffer').Blob} blob - * @param {string?} encoding - */ - readAsText (blob, encoding = undefined) { - webidl.brandCheck(this, FileReader) + // 12. If one of the following is true + // - actualResponse’s status is 301 or 302 and request’s method is `POST` + // - actualResponse’s status is 303 and request’s method is not `GET` or `HEAD` + if ( + ([301, 302].includes(actualResponse.status) && request.method === 'POST') || + (actualResponse.status === 303 && + !GET_OR_HEAD.includes(request.method)) + ) { + // then: + // 1. Set request’s method to `GET` and request’s body to null. + request.method = 'GET' + request.body = null - webidl.argumentLengthCheck(arguments, 1, { header: 'FileReader.readAsText' }) + // 2. For each headerName of request-body-header name, delete headerName from + // request’s header list. + for (const headerName of requestBodyHeader) { + request.headersList.delete(headerName) + } + } - blob = webidl.converters.Blob(blob, { strict: false }) + // 13. If request’s current URL’s origin is not same origin with locationURL’s + // origin, then for each headerName of CORS non-wildcard request-header name, + // delete headerName from request’s header list. + if (!sameOrigin(requestCurrentURL(request), locationURL)) { + // https://fetch.spec.whatwg.org/#cors-non-wildcard-request-header-name + request.headersList.delete('authorization', true) - if (encoding !== undefined) { - encoding = webidl.converters.DOMString(encoding) - } + // https://fetch.spec.whatwg.org/#authentication-entries + request.headersList.delete('proxy-authorization', true) - // The readAsText(blob, encoding) method, when invoked, - // must initiate a read operation for blob with Text and encoding. - readOperation(this, blob, 'Text', encoding) + // "Cookie" and "Host" are forbidden request-headers, which undici doesn't implement. + request.headersList.delete('cookie', true) + request.headersList.delete('host', true) } - /** - * @see https://w3c.github.io/FileAPI/#dfn-readAsDataURL - * @param {import('buffer').Blob} blob - */ - readAsDataURL (blob) { - webidl.brandCheck(this, FileReader) + // 14. If request’s body is non-null, then set request’s body to the first return + // value of safely extracting request’s body’s source. + if (request.body != null) { + assert(request.body.source != null) + request.body = safelyExtractBody(request.body.source)[0] + } - webidl.argumentLengthCheck(arguments, 1, { header: 'FileReader.readAsDataURL' }) + // 15. Let timingInfo be fetchParams’s timing info. + const timingInfo = fetchParams.timingInfo - blob = webidl.converters.Blob(blob, { strict: false }) + // 16. Set timingInfo’s redirect end time and post-redirect start time to the + // coarsened shared current time given fetchParams’s cross-origin isolated + // capability. + timingInfo.redirectEndTime = timingInfo.postRedirectStartTime = + coarsenedSharedCurrentTime(fetchParams.crossOriginIsolatedCapability) - // The readAsDataURL(blob) method, when invoked, must - // initiate a read operation for blob with DataURL. - readOperation(this, blob, 'DataURL') + // 17. If timingInfo’s redirect start time is 0, then set timingInfo’s + // redirect start time to timingInfo’s start time. + if (timingInfo.redirectStartTime === 0) { + timingInfo.redirectStartTime = timingInfo.startTime } - /** - * @see https://w3c.github.io/FileAPI/#dfn-abort - */ - abort () { - // 1. If this's state is "empty" or if this's state is - // "done" set this's result to null and terminate - // this algorithm. - if (this[kState] === 'empty' || this[kState] === 'done') { - this[kResult] = null - return - } - - // 2. If this's state is "loading" set this's state to - // "done" and set this's result to null. - if (this[kState] === 'loading') { - this[kState] = 'done' - this[kResult] = null - } + // 18. Append locationURL to request’s URL list. + request.urlList.push(locationURL) - // 3. If there are any tasks from this on the file reading - // task source in an affiliated task queue, then remove - // those tasks from that task queue. - this[kAborted] = true + // 19. Invoke set request’s referrer policy on redirect on request and + // actualResponse. + setRequestReferrerPolicyOnRedirect(request, actualResponse) - // 4. Terminate the algorithm for the read method being processed. - // TODO + // 20. Return the result of running main fetch given fetchParams and true. + return mainFetch(fetchParams, true) +} - // 5. Fire a progress event called abort at this. - fireAProgressEvent('abort', this) +// https://fetch.spec.whatwg.org/#http-network-or-cache-fetch +async function httpNetworkOrCacheFetch ( + fetchParams, + isAuthenticationFetch = false, + isNewConnectionFetch = false +) { + // 1. Let request be fetchParams’s request. + const request = fetchParams.request - // 6. If this's state is not "loading", fire a progress - // event called loadend at this. - if (this[kState] !== 'loading') { - fireAProgressEvent('loadend', this) - } - } + // 2. Let httpFetchParams be null. + let httpFetchParams = null - /** - * @see https://w3c.github.io/FileAPI/#dom-filereader-readystate - */ - get readyState () { - webidl.brandCheck(this, FileReader) + // 3. Let httpRequest be null. + let httpRequest = null - switch (this[kState]) { - case 'empty': return this.EMPTY - case 'loading': return this.LOADING - case 'done': return this.DONE - } - } + // 4. Let response be null. + let response = null - /** - * @see https://w3c.github.io/FileAPI/#dom-filereader-result - */ - get result () { - webidl.brandCheck(this, FileReader) + // 5. Let storedResponse be null. + // TODO: cache - // The result attribute’s getter, when invoked, must return - // this's result. - return this[kResult] - } + // 6. Let httpCache be null. + const httpCache = null - /** - * @see https://w3c.github.io/FileAPI/#dom-filereader-error - */ - get error () { - webidl.brandCheck(this, FileReader) + // 7. Let the revalidatingFlag be unset. + const revalidatingFlag = false - // The error attribute’s getter, when invoked, must return - // this's error. - return this[kError] - } + // 8. Run these steps, but abort when the ongoing fetch is terminated: - get onloadend () { - webidl.brandCheck(this, FileReader) + // 1. If request’s window is "no-window" and request’s redirect mode is + // "error", then set httpFetchParams to fetchParams and httpRequest to + // request. + if (request.window === 'no-window' && request.redirect === 'error') { + httpFetchParams = fetchParams + httpRequest = request + } else { + // Otherwise: - return this[kEvents].loadend + // 1. Set httpRequest to a clone of request. + httpRequest = cloneRequest(request) + + // 2. Set httpFetchParams to a copy of fetchParams. + httpFetchParams = { ...fetchParams } + + // 3. Set httpFetchParams’s request to httpRequest. + httpFetchParams.request = httpRequest } - set onloadend (fn) { - webidl.brandCheck(this, FileReader) + // 3. Let includeCredentials be true if one of + const includeCredentials = + request.credentials === 'include' || + (request.credentials === 'same-origin' && + request.responseTainting === 'basic') - if (this[kEvents].loadend) { - this.removeEventListener('loadend', this[kEvents].loadend) - } + // 4. Let contentLength be httpRequest’s body’s length, if httpRequest’s + // body is non-null; otherwise null. + const contentLength = httpRequest.body ? httpRequest.body.length : null - if (typeof fn === 'function') { - this[kEvents].loadend = fn - this.addEventListener('loadend', fn) - } else { - this[kEvents].loadend = null - } - } + // 5. Let contentLengthHeaderValue be null. + let contentLengthHeaderValue = null - get onerror () { - webidl.brandCheck(this, FileReader) + // 6. If httpRequest’s body is null and httpRequest’s method is `POST` or + // `PUT`, then set contentLengthHeaderValue to `0`. + if ( + httpRequest.body == null && + ['POST', 'PUT'].includes(httpRequest.method) + ) { + contentLengthHeaderValue = '0' + } - return this[kEvents].error + // 7. If contentLength is non-null, then set contentLengthHeaderValue to + // contentLength, serialized and isomorphic encoded. + if (contentLength != null) { + contentLengthHeaderValue = isomorphicEncode(`${contentLength}`) } - set onerror (fn) { - webidl.brandCheck(this, FileReader) + // 8. If contentLengthHeaderValue is non-null, then append + // `Content-Length`/contentLengthHeaderValue to httpRequest’s header + // list. + if (contentLengthHeaderValue != null) { + httpRequest.headersList.append('content-length', contentLengthHeaderValue, true) + } - if (this[kEvents].error) { - this.removeEventListener('error', this[kEvents].error) - } + // 9. If contentLengthHeaderValue is non-null, then append (`Content-Length`, + // contentLengthHeaderValue) to httpRequest’s header list. - if (typeof fn === 'function') { - this[kEvents].error = fn - this.addEventListener('error', fn) - } else { - this[kEvents].error = null - } + // 10. If contentLength is non-null and httpRequest’s keepalive is true, + // then: + if (contentLength != null && httpRequest.keepalive) { + // NOTE: keepalive is a noop outside of browser context. } - get onloadstart () { - webidl.brandCheck(this, FileReader) - - return this[kEvents].loadstart + // 11. If httpRequest’s referrer is a URL, then append + // `Referer`/httpRequest’s referrer, serialized and isomorphic encoded, + // to httpRequest’s header list. + if (httpRequest.referrer instanceof URL) { + httpRequest.headersList.append('referer', isomorphicEncode(httpRequest.referrer.href), true) } - set onloadstart (fn) { - webidl.brandCheck(this, FileReader) + // 12. Append a request `Origin` header for httpRequest. + appendRequestOriginHeader(httpRequest) - if (this[kEvents].loadstart) { - this.removeEventListener('loadstart', this[kEvents].loadstart) - } + // 13. Append the Fetch metadata headers for httpRequest. [FETCH-METADATA] + appendFetchMetadata(httpRequest) - if (typeof fn === 'function') { - this[kEvents].loadstart = fn - this.addEventListener('loadstart', fn) - } else { - this[kEvents].loadstart = null - } + // 14. If httpRequest’s header list does not contain `User-Agent`, then + // user agents should append `User-Agent`/default `User-Agent` value to + // httpRequest’s header list. + if (!httpRequest.headersList.contains('user-agent', true)) { + httpRequest.headersList.append('user-agent', defaultUserAgent) } - get onprogress () { - webidl.brandCheck(this, FileReader) - - return this[kEvents].progress + // 15. If httpRequest’s cache mode is "default" and httpRequest’s header + // list contains `If-Modified-Since`, `If-None-Match`, + // `If-Unmodified-Since`, `If-Match`, or `If-Range`, then set + // httpRequest’s cache mode to "no-store". + if ( + httpRequest.cache === 'default' && + (httpRequest.headersList.contains('if-modified-since', true) || + httpRequest.headersList.contains('if-none-match', true) || + httpRequest.headersList.contains('if-unmodified-since', true) || + httpRequest.headersList.contains('if-match', true) || + httpRequest.headersList.contains('if-range', true)) + ) { + httpRequest.cache = 'no-store' } - set onprogress (fn) { - webidl.brandCheck(this, FileReader) + // 16. If httpRequest’s cache mode is "no-cache", httpRequest’s prevent + // no-cache cache-control header modification flag is unset, and + // httpRequest’s header list does not contain `Cache-Control`, then append + // `Cache-Control`/`max-age=0` to httpRequest’s header list. + if ( + httpRequest.cache === 'no-cache' && + !httpRequest.preventNoCacheCacheControlHeaderModification && + !httpRequest.headersList.contains('cache-control', true) + ) { + httpRequest.headersList.append('cache-control', 'max-age=0', true) + } - if (this[kEvents].progress) { - this.removeEventListener('progress', this[kEvents].progress) + // 17. If httpRequest’s cache mode is "no-store" or "reload", then: + if (httpRequest.cache === 'no-store' || httpRequest.cache === 'reload') { + // 1. If httpRequest’s header list does not contain `Pragma`, then append + // `Pragma`/`no-cache` to httpRequest’s header list. + if (!httpRequest.headersList.contains('pragma', true)) { + httpRequest.headersList.append('pragma', 'no-cache', true) } - if (typeof fn === 'function') { - this[kEvents].progress = fn - this.addEventListener('progress', fn) - } else { - this[kEvents].progress = null + // 2. If httpRequest’s header list does not contain `Cache-Control`, + // then append `Cache-Control`/`no-cache` to httpRequest’s header list. + if (!httpRequest.headersList.contains('cache-control', true)) { + httpRequest.headersList.append('cache-control', 'no-cache', true) } } - get onload () { - webidl.brandCheck(this, FileReader) - - return this[kEvents].load + // 18. If httpRequest’s header list contains `Range`, then append + // `Accept-Encoding`/`identity` to httpRequest’s header list. + if (httpRequest.headersList.contains('range', true)) { + httpRequest.headersList.append('accept-encoding', 'identity', true) } - set onload (fn) { - webidl.brandCheck(this, FileReader) - - if (this[kEvents].load) { - this.removeEventListener('load', this[kEvents].load) - } - - if (typeof fn === 'function') { - this[kEvents].load = fn - this.addEventListener('load', fn) + // 19. Modify httpRequest’s header list per HTTP. Do not append a given + // header if httpRequest’s header list contains that header’s name. + // TODO: https://github.com/whatwg/fetch/issues/1285#issuecomment-896560129 + if (!httpRequest.headersList.contains('accept-encoding', true)) { + if (urlHasHttpsScheme(requestCurrentURL(httpRequest))) { + httpRequest.headersList.append('accept-encoding', 'br, gzip, deflate', true) } else { - this[kEvents].load = null + httpRequest.headersList.append('accept-encoding', 'gzip, deflate', true) } } - get onabort () { - webidl.brandCheck(this, FileReader) + httpRequest.headersList.delete('host', true) - return this[kEvents].abort + // 20. If includeCredentials is true, then: + if (includeCredentials) { + // 1. If the user agent is not configured to block cookies for httpRequest + // (see section 7 of [COOKIES]), then: + // TODO: credentials + // 2. If httpRequest’s header list does not contain `Authorization`, then: + // TODO: credentials } - set onabort (fn) { - webidl.brandCheck(this, FileReader) + // 21. If there’s a proxy-authentication entry, use it as appropriate. + // TODO: proxy-authentication - if (this[kEvents].abort) { - this.removeEventListener('abort', this[kEvents].abort) - } + // 22. Set httpCache to the result of determining the HTTP cache + // partition, given httpRequest. + // TODO: cache - if (typeof fn === 'function') { - this[kEvents].abort = fn - this.addEventListener('abort', fn) - } else { - this[kEvents].abort = null - } + // 23. If httpCache is null, then set httpRequest’s cache mode to + // "no-store". + if (httpCache == null) { + httpRequest.cache = 'no-store' } -} - -// https://w3c.github.io/FileAPI/#dom-filereader-empty -FileReader.EMPTY = FileReader.prototype.EMPTY = 0 -// https://w3c.github.io/FileAPI/#dom-filereader-loading -FileReader.LOADING = FileReader.prototype.LOADING = 1 -// https://w3c.github.io/FileAPI/#dom-filereader-done -FileReader.DONE = FileReader.prototype.DONE = 2 -Object.defineProperties(FileReader.prototype, { - EMPTY: staticPropertyDescriptors, - LOADING: staticPropertyDescriptors, - DONE: staticPropertyDescriptors, - readAsArrayBuffer: kEnumerableProperty, - readAsBinaryString: kEnumerableProperty, - readAsText: kEnumerableProperty, - readAsDataURL: kEnumerableProperty, - abort: kEnumerableProperty, - readyState: kEnumerableProperty, - result: kEnumerableProperty, - error: kEnumerableProperty, - onloadstart: kEnumerableProperty, - onprogress: kEnumerableProperty, - onload: kEnumerableProperty, - onabort: kEnumerableProperty, - onerror: kEnumerableProperty, - onloadend: kEnumerableProperty, - [Symbol.toStringTag]: { - value: 'FileReader', - writable: false, - enumerable: false, - configurable: true + // 24. If httpRequest’s cache mode is neither "no-store" nor "reload", + // then: + if (httpRequest.cache !== 'no-store' && httpRequest.cache !== 'reload') { + // TODO: cache } -}) -Object.defineProperties(FileReader, { - EMPTY: staticPropertyDescriptors, - LOADING: staticPropertyDescriptors, - DONE: staticPropertyDescriptors -}) + // 9. If aborted, then return the appropriate network error for fetchParams. + // TODO -module.exports = { - FileReader -} + // 10. If response is null, then: + if (response == null) { + // 1. If httpRequest’s cache mode is "only-if-cached", then return a + // network error. + if (httpRequest.cache === 'only-if-cached') { + return makeNetworkError('only if cached') + } + // 2. Let forwardResponse be the result of running HTTP-network fetch + // given httpFetchParams, includeCredentials, and isNewConnectionFetch. + const forwardResponse = await httpNetworkFetch( + httpFetchParams, + includeCredentials, + isNewConnectionFetch + ) -/***/ }), + // 3. If httpRequest’s method is unsafe and forwardResponse’s status is + // in the range 200 to 399, inclusive, invalidate appropriate stored + // responses in httpCache, as per the "Invalidation" chapter of HTTP + // Caching, and set storedResponse to null. [HTTP-CACHING] + if ( + !safeMethodsSet.has(httpRequest.method) && + forwardResponse.status >= 200 && + forwardResponse.status <= 399 + ) { + // TODO: cache + } -/***/ 5753: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // 4. If the revalidatingFlag is set and forwardResponse’s status is 304, + // then: + if (revalidatingFlag && forwardResponse.status === 304) { + // TODO: cache + } -"use strict"; + // 5. If response is null, then: + if (response == null) { + // 1. Set response to forwardResponse. + response = forwardResponse + // 2. Store httpRequest and forwardResponse in httpCache, as per the + // "Storing Responses in Caches" chapter of HTTP Caching. [HTTP-CACHING] + // TODO: cache + } + } -const { webidl } = __nccwpck_require__(8201) + // 11. Set response’s URL list to a clone of httpRequest’s URL list. + response.urlList = [...httpRequest.urlList] -const kState = Symbol('ProgressEvent state') + // 12. If httpRequest’s header list contains `Range`, then set response’s + // range-requested flag. + if (httpRequest.headersList.contains('range', true)) { + response.rangeRequested = true + } -/** - * @see https://xhr.spec.whatwg.org/#progressevent - */ -class ProgressEvent extends Event { - constructor (type, eventInitDict = {}) { - type = webidl.converters.DOMString(type) - eventInitDict = webidl.converters.ProgressEventInit(eventInitDict ?? {}) + // 13. Set response’s request-includes-credentials to includeCredentials. + response.requestIncludesCredentials = includeCredentials - super(type, eventInitDict) + // 14. If response’s status is 401, httpRequest’s response tainting is not + // "cors", includeCredentials is true, and request’s window is an environment + // settings object, then: + // TODO - this[kState] = { - lengthComputable: eventInitDict.lengthComputable, - loaded: eventInitDict.loaded, - total: eventInitDict.total + // 15. If response’s status is 407, then: + if (response.status === 407) { + // 1. If request’s window is "no-window", then return a network error. + if (request.window === 'no-window') { + return makeNetworkError() } - } - get lengthComputable () { - webidl.brandCheck(this, ProgressEvent) + // 2. ??? - return this[kState].lengthComputable - } + // 3. If fetchParams is canceled, then return the appropriate network error for fetchParams. + if (isCancelled(fetchParams)) { + return makeAppropriateNetworkError(fetchParams) + } - get loaded () { - webidl.brandCheck(this, ProgressEvent) + // 4. Prompt the end user as appropriate in request’s window and store + // the result as a proxy-authentication entry. [HTTP-AUTH] + // TODO: Invoke some kind of callback? - return this[kState].loaded + // 5. Set response to the result of running HTTP-network-or-cache fetch given + // fetchParams. + // TODO + return makeNetworkError('proxy authentication required') } - get total () { - webidl.brandCheck(this, ProgressEvent) + // 16. If all of the following are true + if ( + // response’s status is 421 + response.status === 421 && + // isNewConnectionFetch is false + !isNewConnectionFetch && + // request’s body is null, or request’s body is non-null and request’s body’s source is non-null + (request.body == null || request.body.source != null) + ) { + // then: - return this[kState].total + // 1. If fetchParams is canceled, then return the appropriate network error for fetchParams. + if (isCancelled(fetchParams)) { + return makeAppropriateNetworkError(fetchParams) + } + + // 2. Set response to the result of running HTTP-network-or-cache + // fetch given fetchParams, isAuthenticationFetch, and true. + + // TODO (spec): The spec doesn't specify this but we need to cancel + // the active response before we can start a new one. + // https://github.com/whatwg/fetch/issues/1293 + fetchParams.controller.connection.destroy() + + response = await httpNetworkOrCacheFetch( + fetchParams, + isAuthenticationFetch, + true + ) } -} -webidl.converters.ProgressEventInit = webidl.dictionaryConverter([ - { - key: 'lengthComputable', - converter: webidl.converters.boolean, - defaultValue: false - }, - { - key: 'loaded', - converter: webidl.converters['unsigned long long'], - defaultValue: 0 - }, - { - key: 'total', - converter: webidl.converters['unsigned long long'], - defaultValue: 0 - }, - { - key: 'bubbles', - converter: webidl.converters.boolean, - defaultValue: false - }, - { - key: 'cancelable', - converter: webidl.converters.boolean, - defaultValue: false - }, - { - key: 'composed', - converter: webidl.converters.boolean, - defaultValue: false + // 17. If isAuthenticationFetch is true, then create an authentication entry + if (isAuthenticationFetch) { + // TODO } -]) -module.exports = { - ProgressEvent + // 18. Return response. + return response } +// https://fetch.spec.whatwg.org/#http-network-fetch +async function httpNetworkFetch ( + fetchParams, + includeCredentials = false, + forceNewConnection = false +) { + assert(!fetchParams.controller.connection || fetchParams.controller.connection.destroyed) -/***/ }), + fetchParams.controller.connection = { + abort: null, + destroyed: false, + destroy (err, abort = true) { + if (!this.destroyed) { + this.destroyed = true + if (abort) { + this.abort?.(err ?? new DOMException('The operation was aborted.', 'AbortError')) + } + } + } + } -/***/ 9042: -/***/ ((module) => { + // 1. Let request be fetchParams’s request. + const request = fetchParams.request -"use strict"; + // 2. Let response be null. + let response = null + // 3. Let timingInfo be fetchParams’s timing info. + const timingInfo = fetchParams.timingInfo -module.exports = { - kState: Symbol('FileReader state'), - kResult: Symbol('FileReader result'), - kError: Symbol('FileReader error'), - kLastProgressEventFired: Symbol('FileReader last progress event fired timestamp'), - kEvents: Symbol('FileReader events'), - kAborted: Symbol('FileReader aborted') -} + // 4. Let httpCache be the result of determining the HTTP cache partition, + // given request. + // TODO: cache + const httpCache = null + // 5. If httpCache is null, then set request’s cache mode to "no-store". + if (httpCache == null) { + request.cache = 'no-store' + } -/***/ }), + // 6. Let networkPartitionKey be the result of determining the network + // partition key given request. + // TODO -/***/ 2214: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // 7. Let newConnection be "yes" if forceNewConnection is true; otherwise + // "no". + const newConnection = forceNewConnection ? 'yes' : 'no' // eslint-disable-line no-unused-vars -"use strict"; + // 8. Switch on request’s mode: + if (request.mode === 'websocket') { + // Let connection be the result of obtaining a WebSocket connection, + // given request’s current URL. + // TODO + } else { + // Let connection be the result of obtaining a connection, given + // networkPartitionKey, request’s current URL’s origin, + // includeCredentials, and forceNewConnection. + // TODO + } + // 9. Run these steps, but abort when the ongoing fetch is terminated: -const { - kState, - kError, - kResult, - kAborted, - kLastProgressEventFired -} = __nccwpck_require__(9042) -const { ProgressEvent } = __nccwpck_require__(5753) -const { getEncoding } = __nccwpck_require__(7043) -const { DOMException } = __nccwpck_require__(3283) -const { serializeAMimeType, parseMIMEType } = __nccwpck_require__(4955) -const { types } = __nccwpck_require__(9023) -const { StringDecoder } = __nccwpck_require__(3193) -const { btoa } = __nccwpck_require__(181) + // 1. If connection is failure, then return a network error. -/** @type {PropertyDescriptor} */ -const staticPropertyDescriptors = { - enumerable: true, - writable: false, - configurable: false -} + // 2. Set timingInfo’s final connection timing info to the result of + // calling clamp and coarsen connection timing info with connection’s + // timing info, timingInfo’s post-redirect start time, and fetchParams’s + // cross-origin isolated capability. -/** - * @see https://w3c.github.io/FileAPI/#readOperation - * @param {import('./filereader').FileReader} fr - * @param {import('buffer').Blob} blob - * @param {string} type - * @param {string?} encodingName - */ -function readOperation (fr, blob, type, encodingName) { - // 1. If fr’s state is "loading", throw an InvalidStateError - // DOMException. - if (fr[kState] === 'loading') { - throw new DOMException('Invalid state', 'InvalidStateError') - } + // 3. If connection is not an HTTP/2 connection, request’s body is non-null, + // and request’s body’s source is null, then append (`Transfer-Encoding`, + // `chunked`) to request’s header list. - // 2. Set fr’s state to "loading". - fr[kState] = 'loading' + // 4. Set timingInfo’s final network-request start time to the coarsened + // shared current time given fetchParams’s cross-origin isolated + // capability. - // 3. Set fr’s result to null. - fr[kResult] = null + // 5. Set response to the result of making an HTTP request over connection + // using request with the following caveats: - // 4. Set fr’s error to null. - fr[kError] = null + // - Follow the relevant requirements from HTTP. [HTTP] [HTTP-SEMANTICS] + // [HTTP-COND] [HTTP-CACHING] [HTTP-AUTH] - // 5. Let stream be the result of calling get stream on blob. - /** @type {import('stream/web').ReadableStream} */ - const stream = blob.stream() + // - If request’s body is non-null, and request’s body’s source is null, + // then the user agent may have a buffer of up to 64 kibibytes and store + // a part of request’s body in that buffer. If the user agent reads from + // request’s body beyond that buffer’s size and the user agent needs to + // resend request, then instead return a network error. - // 6. Let reader be the result of getting a reader from stream. - const reader = stream.getReader() + // - Set timingInfo’s final network-response start time to the coarsened + // shared current time given fetchParams’s cross-origin isolated capability, + // immediately after the user agent’s HTTP parser receives the first byte + // of the response (e.g., frame header bytes for HTTP/2 or response status + // line for HTTP/1.x). - // 7. Let bytes be an empty byte sequence. - /** @type {Uint8Array[]} */ - const bytes = [] + // - Wait until all the headers are transmitted. - // 8. Let chunkPromise be the result of reading a chunk from - // stream with reader. - let chunkPromise = reader.read() + // - Any responses whose status is in the range 100 to 199, inclusive, + // and is not 101, are to be ignored, except for the purposes of setting + // timingInfo’s final network-response start time above. - // 9. Let isFirstChunk be true. - let isFirstChunk = true + // - If request’s header list contains `Transfer-Encoding`/`chunked` and + // response is transferred via HTTP/1.0 or older, then return a network + // error. - // 10. In parallel, while true: - // Note: "In parallel" just means non-blocking - // Note 2: readOperation itself cannot be async as double - // reading the body would then reject the promise, instead - // of throwing an error. - ;(async () => { - while (!fr[kAborted]) { - // 1. Wait for chunkPromise to be fulfilled or rejected. - try { - const { done, value } = await chunkPromise + // - If the HTTP request results in a TLS client certificate dialog, then: - // 2. If chunkPromise is fulfilled, and isFirstChunk is - // true, queue a task to fire a progress event called - // loadstart at fr. - if (isFirstChunk && !fr[kAborted]) { - queueMicrotask(() => { - fireAProgressEvent('loadstart', fr) - }) - } + // 1. If request’s window is an environment settings object, make the + // dialog available in request’s window. - // 3. Set isFirstChunk to false. - isFirstChunk = false + // 2. Otherwise, return a network error. - // 4. If chunkPromise is fulfilled with an object whose - // done property is false and whose value property is - // a Uint8Array object, run these steps: - if (!done && types.isUint8Array(value)) { - // 1. Let bs be the byte sequence represented by the - // Uint8Array object. + // To transmit request’s body body, run these steps: + let requestBody = null + // 1. If body is null and fetchParams’s process request end-of-body is + // non-null, then queue a fetch task given fetchParams’s process request + // end-of-body and fetchParams’s task destination. + if (request.body == null && fetchParams.processRequestEndOfBody) { + queueMicrotask(() => fetchParams.processRequestEndOfBody()) + } else if (request.body != null) { + // 2. Otherwise, if body is non-null: - // 2. Append bs to bytes. - bytes.push(value) + // 1. Let processBodyChunk given bytes be these steps: + const processBodyChunk = async function * (bytes) { + // 1. If the ongoing fetch is terminated, then abort these steps. + if (isCancelled(fetchParams)) { + return + } - // 3. If roughly 50ms have passed since these steps - // were last invoked, queue a task to fire a - // progress event called progress at fr. - if ( - ( - fr[kLastProgressEventFired] === undefined || - Date.now() - fr[kLastProgressEventFired] >= 50 - ) && - !fr[kAborted] - ) { - fr[kLastProgressEventFired] = Date.now() - queueMicrotask(() => { - fireAProgressEvent('progress', fr) - }) - } + // 2. Run this step in parallel: transmit bytes. + yield bytes - // 4. Set chunkPromise to the result of reading a - // chunk from stream with reader. - chunkPromise = reader.read() - } else if (done) { - // 5. Otherwise, if chunkPromise is fulfilled with an - // object whose done property is true, queue a task - // to run the following steps and abort this algorithm: - queueMicrotask(() => { - // 1. Set fr’s state to "done". - fr[kState] = 'done' + // 3. If fetchParams’s process request body is non-null, then run + // fetchParams’s process request body given bytes’s length. + fetchParams.processRequestBodyChunkLength?.(bytes.byteLength) + } - // 2. Let result be the result of package data given - // bytes, type, blob’s type, and encodingName. - try { - const result = packageData(bytes, type, blob.type, encodingName) + // 2. Let processEndOfBody be these steps: + const processEndOfBody = () => { + // 1. If fetchParams is canceled, then abort these steps. + if (isCancelled(fetchParams)) { + return + } - // 4. Else: + // 2. If fetchParams’s process request end-of-body is non-null, + // then run fetchParams’s process request end-of-body. + if (fetchParams.processRequestEndOfBody) { + fetchParams.processRequestEndOfBody() + } + } - if (fr[kAborted]) { - return - } + // 3. Let processBodyError given e be these steps: + const processBodyError = (e) => { + // 1. If fetchParams is canceled, then abort these steps. + if (isCancelled(fetchParams)) { + return + } - // 1. Set fr’s result to result. - fr[kResult] = result + // 2. If e is an "AbortError" DOMException, then abort fetchParams’s controller. + if (e.name === 'AbortError') { + fetchParams.controller.abort() + } else { + fetchParams.controller.terminate(e) + } + } - // 2. Fire a progress event called load at the fr. - fireAProgressEvent('load', fr) - } catch (error) { - // 3. If package data threw an exception error: + // 4. Incrementally read request’s body given processBodyChunk, processEndOfBody, + // processBodyError, and fetchParams’s task destination. + requestBody = (async function * () { + try { + for await (const bytes of request.body.stream) { + yield * processBodyChunk(bytes) + } + processEndOfBody() + } catch (err) { + processBodyError(err) + } + })() + } - // 1. Set fr’s error to error. - fr[kError] = error + try { + // socket is only provided for websockets + const { body, status, statusText, headersList, socket } = await dispatch({ body: requestBody }) - // 2. Fire a progress event called error at fr. - fireAProgressEvent('error', fr) - } + if (socket) { + response = makeResponse({ status, statusText, headersList, socket }) + } else { + const iterator = body[Symbol.asyncIterator]() + fetchParams.controller.next = () => iterator.next() - // 5. If fr’s state is not "loading", fire a progress - // event called loadend at the fr. - if (fr[kState] !== 'loading') { - fireAProgressEvent('loadend', fr) - } - }) + response = makeResponse({ status, statusText, headersList }) + } + } catch (err) { + // 10. If aborted, then: + if (err.name === 'AbortError') { + // 1. If connection uses HTTP/2, then transmit an RST_STREAM frame. + fetchParams.controller.connection.destroy() - break - } - } catch (error) { - if (fr[kAborted]) { - return - } + // 2. Return the appropriate network error for fetchParams. + return makeAppropriateNetworkError(fetchParams, err) + } - // 6. Otherwise, if chunkPromise is rejected with an - // error error, queue a task to run the following - // steps and abort this algorithm: - queueMicrotask(() => { - // 1. Set fr’s state to "done". - fr[kState] = 'done' + return makeNetworkError(err) + } - // 2. Set fr’s error to error. - fr[kError] = error + // 11. Let pullAlgorithm be an action that resumes the ongoing fetch + // if it is suspended. + const pullAlgorithm = async () => { + await fetchParams.controller.resume() + } - // 3. Fire a progress event called error at fr. - fireAProgressEvent('error', fr) + // 12. Let cancelAlgorithm be an algorithm that aborts fetchParams’s + // controller with reason, given reason. + const cancelAlgorithm = (reason) => { + // If the aborted fetch was already terminated, then we do not + // need to do anything. + if (!isCancelled(fetchParams)) { + fetchParams.controller.abort(reason) + } + } - // 4. If fr’s state is not "loading", fire a progress - // event called loadend at fr. - if (fr[kState] !== 'loading') { - fireAProgressEvent('loadend', fr) - } - }) + // 13. Let highWaterMark be a non-negative, non-NaN number, chosen by + // the user agent. + // TODO - break - } + // 14. Let sizeAlgorithm be an algorithm that accepts a chunk object + // and returns a non-negative, non-NaN, non-infinite number, chosen by the user agent. + // TODO + + // 15. Let stream be a new ReadableStream. + // 16. Set up stream with byte reading support with pullAlgorithm set to pullAlgorithm, + // cancelAlgorithm set to cancelAlgorithm. + const stream = new ReadableStream( + { + async start (controller) { + fetchParams.controller.controller = controller + }, + async pull (controller) { + await pullAlgorithm(controller) + }, + async cancel (reason) { + await cancelAlgorithm(reason) + }, + type: 'bytes' } - })() -} + ) -/** - * @see https://w3c.github.io/FileAPI/#fire-a-progress-event - * @see https://dom.spec.whatwg.org/#concept-event-fire - * @param {string} e The name of the event - * @param {import('./filereader').FileReader} reader - */ -function fireAProgressEvent (e, reader) { - // The progress event e does not bubble. e.bubbles must be false - // The progress event e is NOT cancelable. e.cancelable must be false - const event = new ProgressEvent(e, { - bubbles: false, - cancelable: false - }) + // 17. Run these steps, but abort when the ongoing fetch is terminated: - reader.dispatchEvent(event) -} + // 1. Set response’s body to a new body whose stream is stream. + response.body = { stream, source: null, length: null } -/** - * @see https://w3c.github.io/FileAPI/#blob-package-data - * @param {Uint8Array[]} bytes - * @param {string} type - * @param {string?} mimeType - * @param {string?} encodingName - */ -function packageData (bytes, type, mimeType, encodingName) { - // 1. A Blob has an associated package data algorithm, given - // bytes, a type, a optional mimeType, and a optional - // encodingName, which switches on type and runs the - // associated steps: + // 2. If response is not a network error and request’s cache mode is + // not "no-store", then update response in httpCache for request. + // TODO - switch (type) { - case 'DataURL': { - // 1. Return bytes as a DataURL [RFC2397] subject to - // the considerations below: - // * Use mimeType as part of the Data URL if it is - // available in keeping with the Data URL - // specification [RFC2397]. - // * If mimeType is not available return a Data URL - // without a media-type. [RFC2397]. + // 3. If includeCredentials is true and the user agent is not configured + // to block cookies for request (see section 7 of [COOKIES]), then run the + // "set-cookie-string" parsing algorithm (see section 5.2 of [COOKIES]) on + // the value of each header whose name is a byte-case-insensitive match for + // `Set-Cookie` in response’s header list, if any, and request’s current URL. + // TODO - // https://datatracker.ietf.org/doc/html/rfc2397#section-3 - // dataurl := "data:" [ mediatype ] [ ";base64" ] "," data - // mediatype := [ type "/" subtype ] *( ";" parameter ) - // data := *urlchar - // parameter := attribute "=" value - let dataURL = 'data:' + // 18. If aborted, then: + // TODO - const parsed = parseMIMEType(mimeType || 'application/octet-stream') + // 19. Run these steps in parallel: - if (parsed !== 'failure') { - dataURL += serializeAMimeType(parsed) - } + // 1. Run these steps, but abort when fetchParams is canceled: + fetchParams.controller.onAborted = onAborted + fetchParams.controller.on('terminated', onAborted) + fetchParams.controller.resume = async () => { + // 1. While true + while (true) { + // 1-3. See onData... - dataURL += ';base64,' + // 4. Set bytes to the result of handling content codings given + // codings and bytes. + let bytes + let isFailure + try { + const { done, value } = await fetchParams.controller.next() - const decoder = new StringDecoder('latin1') + if (isAborted(fetchParams)) { + break + } - for (const chunk of bytes) { - dataURL += btoa(decoder.write(chunk)) + bytes = done ? undefined : value + } catch (err) { + if (fetchParams.controller.ended && !timingInfo.encodedBodySize) { + // zlib doesn't like empty streams. + bytes = undefined + } else { + bytes = err + + // err may be propagated from the result of calling readablestream.cancel, + // which might not be an error. https://github.com/nodejs/undici/issues/2009 + isFailure = true + } } - dataURL += btoa(decoder.end()) + if (bytes === undefined) { + // 2. Otherwise, if the bytes transmission for response’s message + // body is done normally and stream is readable, then close + // stream, finalize response for fetchParams and response, and + // abort these in-parallel steps. + readableStreamClose(fetchParams.controller.controller) - return dataURL - } - case 'Text': { - // 1. Let encoding be failure - let encoding = 'failure' + finalizeResponse(fetchParams, response) - // 2. If the encodingName is present, set encoding to the - // result of getting an encoding from encodingName. - if (encodingName) { - encoding = getEncoding(encodingName) + return } - // 3. If encoding is failure, and mimeType is present: - if (encoding === 'failure' && mimeType) { - // 1. Let type be the result of parse a MIME type - // given mimeType. - const type = parseMIMEType(mimeType) + // 5. Increase timingInfo’s decoded body size by bytes’s length. + timingInfo.decodedBodySize += bytes?.byteLength ?? 0 - // 2. If type is not failure, set encoding to the result - // of getting an encoding from type’s parameters["charset"]. - if (type !== 'failure') { - encoding = getEncoding(type.parameters.get('charset')) - } + // 6. If bytes is failure, then terminate fetchParams’s controller. + if (isFailure) { + fetchParams.controller.terminate(bytes) + return } - // 4. If encoding is failure, then set encoding to UTF-8. - if (encoding === 'failure') { - encoding = 'UTF-8' + // 7. Enqueue a Uint8Array wrapping an ArrayBuffer containing bytes + // into stream. + const buffer = new Uint8Array(bytes) + if (buffer.byteLength) { + fetchParams.controller.controller.enqueue(buffer) } - // 5. Decode bytes using fallback encoding encoding, and - // return the result. - return decode(bytes, encoding) - } - case 'ArrayBuffer': { - // Return a new ArrayBuffer whose contents are bytes. - const sequence = combineByteSequences(bytes) - - return sequence.buffer - } - case 'BinaryString': { - // Return bytes as a binary string, in which every byte - // is represented by a code unit of equal value [0..255]. - let binaryString = '' - - const decoder = new StringDecoder('latin1') - - for (const chunk of bytes) { - binaryString += decoder.write(chunk) + // 8. If stream is errored, then terminate the ongoing fetch. + if (isErrored(stream)) { + fetchParams.controller.terminate() + return } - binaryString += decoder.end() - - return binaryString + // 9. If stream doesn’t need more data ask the user agent to suspend + // the ongoing fetch. + if (fetchParams.controller.controller.desiredSize <= 0) { + return + } } } -} -/** - * @see https://encoding.spec.whatwg.org/#decode - * @param {Uint8Array[]} ioQueue - * @param {string} encoding - */ -function decode (ioQueue, encoding) { - const bytes = combineByteSequences(ioQueue) + // 2. If aborted, then: + function onAborted (reason) { + // 2. If fetchParams is aborted, then: + if (isAborted(fetchParams)) { + // 1. Set response’s aborted flag. + response.aborted = true - // 1. Let BOMEncoding be the result of BOM sniffing ioQueue. - const BOMEncoding = BOMSniffing(bytes) + // 2. If stream is readable, then error stream with the result of + // deserialize a serialized abort reason given fetchParams’s + // controller’s serialized abort reason and an + // implementation-defined realm. + if (isReadable(stream)) { + fetchParams.controller.controller.error( + fetchParams.controller.serializedAbortReason + ) + } + } else { + // 3. Otherwise, if stream is readable, error stream with a TypeError. + if (isReadable(stream)) { + fetchParams.controller.controller.error(new TypeError('terminated', { + cause: isErrorLike(reason) ? reason : undefined + })) + } + } - let slice = 0 + // 4. If connection uses HTTP/2, then transmit an RST_STREAM frame. + // 5. Otherwise, the user agent should close connection unless it would be bad for performance to do so. + fetchParams.controller.connection.destroy() + } - // 2. If BOMEncoding is non-null: - if (BOMEncoding !== null) { - // 1. Set encoding to BOMEncoding. - encoding = BOMEncoding + // 20. Return response. + return response - // 2. Read three bytes from ioQueue, if BOMEncoding is - // UTF-8; otherwise read two bytes. - // (Do nothing with those bytes.) - slice = BOMEncoding === 'UTF-8' ? 3 : 2 - } + function dispatch ({ body }) { + const url = requestCurrentURL(request) + /** @type {import('../..').Agent} */ + const agent = fetchParams.controller.dispatcher - // 3. Process a queue with an instance of encoding’s - // decoder, ioQueue, output, and "replacement". + return new Promise((resolve, reject) => agent.dispatch( + { + path: url.pathname + url.search, + origin: url.origin, + method: request.method, + body: agent.isMockActive ? request.body && (request.body.source || request.body.stream) : body, + headers: request.headersList.entries, + maxRedirections: 0, + upgrade: request.mode === 'websocket' ? 'websocket' : undefined + }, + { + body: null, + abort: null, - // 4. Return output. + onConnect (abort) { + // TODO (fix): Do we need connection here? + const { connection } = fetchParams.controller - const sliced = bytes.slice(slice) - return new TextDecoder(encoding).decode(sliced) -} + // Set timingInfo’s final connection timing info to the result of calling clamp and coarsen + // connection timing info with connection’s timing info, timingInfo’s post-redirect start + // time, and fetchParams’s cross-origin isolated capability. + // TODO: implement connection timing + timingInfo.finalConnectionTimingInfo = clampAndCoarsenConnectionTimingInfo(undefined, timingInfo.postRedirectStartTime, fetchParams.crossOriginIsolatedCapability) -/** - * @see https://encoding.spec.whatwg.org/#bom-sniff - * @param {Uint8Array} ioQueue - */ -function BOMSniffing (ioQueue) { - // 1. Let BOM be the result of peeking 3 bytes from ioQueue, - // converted to a byte sequence. - const [a, b, c] = ioQueue + if (connection.destroyed) { + abort(new DOMException('The operation was aborted.', 'AbortError')) + } else { + fetchParams.controller.on('terminated', abort) + this.abort = connection.abort = abort + } - // 2. For each of the rows in the table below, starting with - // the first one and going down, if BOM starts with the - // bytes given in the first column, then return the - // encoding given in the cell in the second column of that - // row. Otherwise, return null. - if (a === 0xEF && b === 0xBB && c === 0xBF) { - return 'UTF-8' - } else if (a === 0xFE && b === 0xFF) { - return 'UTF-16BE' - } else if (a === 0xFF && b === 0xFE) { - return 'UTF-16LE' - } + // Set timingInfo’s final network-request start time to the coarsened shared current time given + // fetchParams’s cross-origin isolated capability. + timingInfo.finalNetworkRequestStartTime = coarsenedSharedCurrentTime(fetchParams.crossOriginIsolatedCapability) + }, - return null -} + onResponseStarted () { + // Set timingInfo’s final network-response start time to the coarsened shared current + // time given fetchParams’s cross-origin isolated capability, immediately after the + // user agent’s HTTP parser receives the first byte of the response (e.g., frame header + // bytes for HTTP/2 or response status line for HTTP/1.x). + timingInfo.finalNetworkResponseStartTime = coarsenedSharedCurrentTime(fetchParams.crossOriginIsolatedCapability) + }, -/** - * @param {Uint8Array[]} sequences - */ -function combineByteSequences (sequences) { - const size = sequences.reduce((a, b) => { - return a + b.byteLength - }, 0) + onHeaders (status, rawHeaders, resume, statusText) { + if (status < 200) { + return + } - let offset = 0 + let location = '' - return sequences.reduce((a, b) => { - a.set(b, offset) - offset += b.byteLength - return a - }, new Uint8Array(size)) -} + const headersList = new HeadersList() -module.exports = { - staticPropertyDescriptors, - readOperation, - fireAProgressEvent -} + for (let i = 0; i < rawHeaders.length; i += 2) { + headersList.append(bufferToLowerCasedHeaderName(rawHeaders[i]), rawHeaders[i + 1].toString('latin1'), true) + } + location = headersList.get('location', true) + this.body = new Readable({ read: resume }) -/***/ }), + const decoders = [] -/***/ 5334: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + const willFollow = location && request.redirect === 'follow' && + redirectStatusSet.has(status) -"use strict"; + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding + if (request.method !== 'HEAD' && request.method !== 'CONNECT' && !nullBodyStatus.includes(status) && !willFollow) { + // https://www.rfc-editor.org/rfc/rfc7231#section-3.1.2.1 + const contentEncoding = headersList.get('content-encoding', true) + // "All content-coding values are case-insensitive..." + /** @type {string[]} */ + const codings = contentEncoding ? contentEncoding.toLowerCase().split(',') : [] + // Limit the number of content-encodings to prevent resource exhaustion. + // CVE fix similar to urllib3 (GHSA-gm62-xv2j-4w53) and curl (CVE-2022-32206). + const maxContentEncodings = 5 + if (codings.length > maxContentEncodings) { + reject(new Error(`too many content-encodings in response: ${codings.length}, maximum allowed is ${maxContentEncodings}`)) + return true + } -// We include a version number for the Dispatcher API. In case of breaking changes, -// this version number must be increased to avoid conflicts. -const globalDispatcher = Symbol.for('undici.globalDispatcher.1') -const { InvalidArgumentError } = __nccwpck_require__(6738) -const Agent = __nccwpck_require__(2308) + for (let i = codings.length - 1; i >= 0; --i) { + const coding = codings[i].trim() + // https://www.rfc-editor.org/rfc/rfc9112.html#section-7.2 + if (coding === 'x-gzip' || coding === 'gzip') { + decoders.push(zlib.createGunzip({ + // Be less strict when decoding compressed responses, since sometimes + // servers send slightly invalid responses that are still accepted + // by common browsers. + // Always using Z_SYNC_FLUSH is what cURL does. + flush: zlib.constants.Z_SYNC_FLUSH, + finishFlush: zlib.constants.Z_SYNC_FLUSH + })) + } else if (coding === 'deflate') { + decoders.push(createInflate({ + flush: zlib.constants.Z_SYNC_FLUSH, + finishFlush: zlib.constants.Z_SYNC_FLUSH + })) + } else if (coding === 'br') { + decoders.push(zlib.createBrotliDecompress({ + flush: zlib.constants.BROTLI_OPERATION_FLUSH, + finishFlush: zlib.constants.BROTLI_OPERATION_FLUSH + })) + } else { + decoders.length = 0 + break + } + } + } -if (getGlobalDispatcher() === undefined) { - setGlobalDispatcher(new Agent()) -} + const onError = this.onError.bind(this) -function setGlobalDispatcher (agent) { - if (!agent || typeof agent.dispatch !== 'function') { - throw new InvalidArgumentError('Argument agent must implement Agent') - } - Object.defineProperty(globalThis, globalDispatcher, { - value: agent, - writable: true, - enumerable: false, - configurable: false - }) -} + resolve({ + status, + statusText, + headersList, + body: decoders.length + ? pipeline(this.body, ...decoders, (err) => { + if (err) { + this.onError(err) + } + }).on('error', onError) + : this.body.on('error', onError) + }) -function getGlobalDispatcher () { - return globalThis[globalDispatcher] -} + return true + }, -module.exports = { - setGlobalDispatcher, - getGlobalDispatcher -} + onData (chunk) { + if (fetchParams.controller.dump) { + return + } + // 1. If one or more bytes have been transmitted from response’s + // message body, then: -/***/ }), + // 1. Let bytes be the transmitted bytes. + const bytes = chunk -/***/ 507: -/***/ ((module) => { + // 2. Let codings be the result of extracting header list values + // given `Content-Encoding` and response’s header list. + // See pullAlgorithm. -"use strict"; + // 3. Increase timingInfo’s encoded body size by bytes’s length. + timingInfo.encodedBodySize += bytes.byteLength + // 4. See pullAlgorithm... -module.exports = class DecoratorHandler { - constructor (handler) { - this.handler = handler - } + return this.body.push(bytes) + }, - onConnect (...args) { - return this.handler.onConnect(...args) - } + onComplete () { + if (this.abort) { + fetchParams.controller.off('terminated', this.abort) + } - onError (...args) { - return this.handler.onError(...args) - } + if (fetchParams.controller.onAborted) { + fetchParams.controller.off('terminated', fetchParams.controller.onAborted) + } - onUpgrade (...args) { - return this.handler.onUpgrade(...args) - } + fetchParams.controller.ended = true - onHeaders (...args) { - return this.handler.onHeaders(...args) - } + this.body.push(null) + }, - onData (...args) { - return this.handler.onData(...args) - } + onError (error) { + if (this.abort) { + fetchParams.controller.off('terminated', this.abort) + } - onComplete (...args) { - return this.handler.onComplete(...args) - } + this.body?.destroy(error) - onBodySent (...args) { - return this.handler.onBodySent(...args) + fetchParams.controller.terminate(error) + + reject(error) + }, + + onUpgrade (status, rawHeaders, socket) { + if (status !== 101) { + return + } + + const headersList = new HeadersList() + + for (let i = 0; i < rawHeaders.length; i += 2) { + headersList.append(bufferToLowerCasedHeaderName(rawHeaders[i]), rawHeaders[i + 1].toString('latin1'), true) + } + + resolve({ + status, + statusText: STATUS_CODES[status], + headersList, + socket + }) + + return true + } + } + )) } } +module.exports = { + fetch, + Fetch, + fetching, + finalizeAndReportTiming +} + /***/ }), -/***/ 6858: +/***/ 5417: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; +/* globals AbortController */ -const util = __nccwpck_require__(5069) -const { kBodyUsed } = __nccwpck_require__(1028) -const assert = __nccwpck_require__(2613) -const { InvalidArgumentError } = __nccwpck_require__(6738) -const EE = __nccwpck_require__(4434) -const redirectableStatusCodes = [300, 301, 302, 303, 307, 308] +const { extractBody, mixinBody, cloneBody, bodyUnusable } = __nccwpck_require__(8106) +const { Headers, fill: fillHeaders, HeadersList, setHeadersGuard, getHeadersGuard, setHeadersList, getHeadersList } = __nccwpck_require__(217) +const { FinalizationRegistry } = __nccwpck_require__(3823)() +const util = __nccwpck_require__(7234) +const nodeUtil = __nccwpck_require__(7975) +const { + isValidHTTPToken, + sameOrigin, + environmentSettingsObject +} = __nccwpck_require__(1046) +const { + forbiddenMethodsSet, + corsSafeListedMethodsSet, + referrerPolicy, + requestRedirect, + requestMode, + requestCredentials, + requestCache, + requestDuplex +} = __nccwpck_require__(6169) +const { kEnumerableProperty, normalizedMethodRecordsBase, normalizedMethodRecords } = util +const { kHeaders, kSignal, kState, kDispatcher } = __nccwpck_require__(1445) +const { webidl } = __nccwpck_require__(4859) +const { URLSerializer } = __nccwpck_require__(6406) +const { kConstruct } = __nccwpck_require__(7417) +const assert = __nccwpck_require__(4589) +const { getMaxListeners, setMaxListeners, getEventListeners, defaultMaxListeners } = __nccwpck_require__(8474) -const kBody = Symbol('body') +const kAbortController = Symbol('abortController') -class BodyAsyncIterable { - constructor (body) { - this[kBody] = body - this[kBodyUsed] = false - } +const requestFinalizer = new FinalizationRegistry(({ signal, abort }) => { + signal.removeEventListener('abort', abort) +}) - async * [Symbol.asyncIterator] () { - assert(!this[kBodyUsed], 'disturbed') - this[kBodyUsed] = true - yield * this[kBody] - } -} +const dependentControllerMap = new WeakMap() -class RedirectHandler { - constructor (dispatch, maxRedirections, opts, handler) { - if (maxRedirections != null && (!Number.isInteger(maxRedirections) || maxRedirections < 0)) { - throw new InvalidArgumentError('maxRedirections must be a positive number') - } +function buildAbort (acRef) { + return abort - util.validateHandler(handler, opts.method, opts.upgrade) + function abort () { + const ac = acRef.deref() + if (ac !== undefined) { + // Currently, there is a problem with FinalizationRegistry. + // https://github.com/nodejs/node/issues/49344 + // https://github.com/nodejs/node/issues/47748 + // In the case of abort, the first step is to unregister from it. + // If the controller can refer to it, it is still registered. + // It will be removed in the future. + requestFinalizer.unregister(abort) - this.dispatch = dispatch - this.location = null - this.abort = null - this.opts = { ...opts, maxRedirections: 0 } // opts must be a copy - this.maxRedirections = maxRedirections - this.handler = handler - this.history = [] + // Unsubscribe a listener. + // FinalizationRegistry will no longer be called, so this must be done. + this.removeEventListener('abort', abort) - if (util.isStream(this.opts.body)) { - // TODO (fix): Provide some way for the user to cache the file to e.g. /tmp - // so that it can be dispatched again? - // TODO (fix): Do we need 100-expect support to provide a way to do this properly? - if (util.bodyLength(this.opts.body) === 0) { - this.opts.body - .on('data', function () { - assert(false) - }) - } + ac.abort(this.reason) - if (typeof this.opts.body.readableDidRead !== 'boolean') { - this.opts.body[kBodyUsed] = false - EE.prototype.on.call(this.opts.body, 'data', function () { - this[kBodyUsed] = true - }) + const controllerList = dependentControllerMap.get(ac.signal) + + if (controllerList !== undefined) { + if (controllerList.size !== 0) { + for (const ref of controllerList) { + const ctrl = ref.deref() + if (ctrl !== undefined) { + ctrl.abort(this.reason) + } + } + controllerList.clear() + } + dependentControllerMap.delete(ac.signal) } - } else if (this.opts.body && typeof this.opts.body.pipeTo === 'function') { - // TODO (fix): We can't access ReadableStream internal state - // to determine whether or not it has been disturbed. This is just - // a workaround. - this.opts.body = new BodyAsyncIterable(this.opts.body) - } else if ( - this.opts.body && - typeof this.opts.body !== 'string' && - !ArrayBuffer.isView(this.opts.body) && - util.isIterable(this.opts.body) - ) { - // TODO: Should we allow re-using iterable if !this.opts.idempotent - // or through some other flag? - this.opts.body = new BodyAsyncIterable(this.opts.body) } } +} - onConnect (abort) { - this.abort = abort - this.handler.onConnect(abort, { history: this.history }) - } - - onUpgrade (statusCode, headers, socket) { - this.handler.onUpgrade(statusCode, headers, socket) - } +let patchMethodWarning = false - onError (error) { - this.handler.onError(error) - } +// https://fetch.spec.whatwg.org/#request-class +class Request { + // https://fetch.spec.whatwg.org/#dom-request + constructor (input, init = {}) { + webidl.util.markAsUncloneable(this) + if (input === kConstruct) { + return + } - onHeaders (statusCode, headers, resume, statusText) { - this.location = this.history.length >= this.maxRedirections || util.isDisturbed(this.opts.body) - ? null - : parseLocation(statusCode, headers) + const prefix = 'Request constructor' + webidl.argumentLengthCheck(arguments, 1, prefix) - if (this.opts.origin) { - this.history.push(new URL(this.opts.path, this.opts.origin)) - } + input = webidl.converters.RequestInfo(input, prefix, 'input') + init = webidl.converters.RequestInit(init, prefix, 'init') - if (!this.location) { - return this.handler.onHeaders(statusCode, headers, resume, statusText) - } + // 1. Let request be null. + let request = null - const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin))) - const path = search ? `${pathname}${search}` : pathname + // 2. Let fallbackMode be null. + let fallbackMode = null - // Remove headers referring to the original URL. - // By default it is Host only, unless it's a 303 (see below), which removes also all Content-* headers. - // https://tools.ietf.org/html/rfc7231#section-6.4 - this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin) - this.opts.path = path - this.opts.origin = origin - this.opts.maxRedirections = 0 - this.opts.query = null + // 3. Let baseURL be this’s relevant settings object’s API base URL. + const baseUrl = environmentSettingsObject.settingsObject.baseUrl - // https://tools.ietf.org/html/rfc7231#section-6.4.4 - // In case of HTTP 303, always replace method to be either HEAD or GET - if (statusCode === 303 && this.opts.method !== 'HEAD') { - this.opts.method = 'GET' - this.opts.body = null - } - } + // 4. Let signal be null. + let signal = null - onData (chunk) { - if (this.location) { - /* - https://tools.ietf.org/html/rfc7231#section-6.4 + // 5. If input is a string, then: + if (typeof input === 'string') { + this[kDispatcher] = init.dispatcher - TLDR: undici always ignores 3xx response bodies. + // 1. Let parsedURL be the result of parsing input with baseURL. + // 2. If parsedURL is failure, then throw a TypeError. + let parsedURL + try { + parsedURL = new URL(input, baseUrl) + } catch (err) { + throw new TypeError('Failed to parse URL from ' + input, { cause: err }) + } - Redirection is used to serve the requested resource from another URL, so it is assumes that - no body is generated (and thus can be ignored). Even though generating a body is not prohibited. + // 3. If parsedURL includes credentials, then throw a TypeError. + if (parsedURL.username || parsedURL.password) { + throw new TypeError( + 'Request cannot be constructed from a URL that includes credentials: ' + + input + ) + } - For status 301, 302, 303, 307 and 308 (the latter from RFC 7238), the specs mention that the body usually - (which means it's optional and not mandated) contain just an hyperlink to the value of - the Location response header, so the body can be ignored safely. + // 4. Set request to a new request whose URL is parsedURL. + request = makeRequest({ urlList: [parsedURL] }) - For status 300, which is "Multiple Choices", the spec mentions both generating a Location - response header AND a response body with the other possible location to follow. - Since the spec explicitily chooses not to specify a format for such body and leave it to - servers and browsers implementors, we ignore the body as there is no specified way to eventually parse it. - */ + // 5. Set fallbackMode to "cors". + fallbackMode = 'cors' } else { - return this.handler.onData(chunk) - } - } + this[kDispatcher] = init.dispatcher || input[kDispatcher] - onComplete (trailers) { - if (this.location) { - /* - https://tools.ietf.org/html/rfc7231#section-6.4 - - TLDR: undici always ignores 3xx response trailers as they are not expected in case of redirections - and neither are useful if present. + // 6. Otherwise: - See comment on onData method above for more detailed informations. - */ + // 7. Assert: input is a Request object. + assert(input instanceof Request) - this.location = null - this.abort = null + // 8. Set request to input’s request. + request = input[kState] - this.dispatch(this.opts, this) - } else { - this.handler.onComplete(trailers) + // 9. Set signal to input’s signal. + signal = input[kSignal] } - } - onBodySent (chunk) { - if (this.handler.onBodySent) { - this.handler.onBodySent(chunk) - } - } -} + // 7. Let origin be this’s relevant settings object’s origin. + const origin = environmentSettingsObject.settingsObject.origin -function parseLocation (statusCode, headers) { - if (redirectableStatusCodes.indexOf(statusCode) === -1) { - return null - } + // 8. Let window be "client". + let window = 'client' - for (let i = 0; i < headers.length; i += 2) { - if (headers[i].toString().toLowerCase() === 'location') { - return headers[i + 1] + // 9. If request’s window is an environment settings object and its origin + // is same origin with origin, then set window to request’s window. + if ( + request.window?.constructor?.name === 'EnvironmentSettingsObject' && + sameOrigin(request.window, origin) + ) { + window = request.window } - } -} - -// https://tools.ietf.org/html/rfc7231#section-6.4.4 -function shouldRemoveHeader (header, removeContent, unknownOrigin) { - if (header.length === 4) { - return util.headerNameToString(header) === 'host' - } - if (removeContent && util.headerNameToString(header).startsWith('content-')) { - return true - } - if (unknownOrigin && (header.length === 13 || header.length === 6 || header.length === 19)) { - const name = util.headerNameToString(header) - return name === 'authorization' || name === 'cookie' || name === 'proxy-authorization' - } - return false -} -// https://tools.ietf.org/html/rfc7231#section-6.4 -function cleanRequestHeaders (headers, removeContent, unknownOrigin) { - const ret = [] - if (Array.isArray(headers)) { - for (let i = 0; i < headers.length; i += 2) { - if (!shouldRemoveHeader(headers[i], removeContent, unknownOrigin)) { - ret.push(headers[i], headers[i + 1]) - } + // 10. If init["window"] exists and is non-null, then throw a TypeError. + if (init.window != null) { + throw new TypeError(`'window' option '${window}' must be null`) } - } else if (headers && typeof headers === 'object') { - for (const key of Object.keys(headers)) { - if (!shouldRemoveHeader(key, removeContent, unknownOrigin)) { - ret.push(key, headers[key]) - } + + // 11. If init["window"] exists, then set window to "no-window". + if ('window' in init) { + window = 'no-window' } - } else { - assert(headers == null, 'headers must be an object or an array') - } - return ret -} -module.exports = RedirectHandler + // 12. Set request to a new request with the following properties: + request = makeRequest({ + // URL request’s URL. + // undici implementation note: this is set as the first item in request's urlList in makeRequest + // method request’s method. + method: request.method, + // header list A copy of request’s header list. + // undici implementation note: headersList is cloned in makeRequest + headersList: request.headersList, + // unsafe-request flag Set. + unsafeRequest: request.unsafeRequest, + // client This’s relevant settings object. + client: environmentSettingsObject.settingsObject, + // window window. + window, + // priority request’s priority. + priority: request.priority, + // origin request’s origin. The propagation of the origin is only significant for navigation requests + // being handled by a service worker. In this scenario a request can have an origin that is different + // from the current client. + origin: request.origin, + // referrer request’s referrer. + referrer: request.referrer, + // referrer policy request’s referrer policy. + referrerPolicy: request.referrerPolicy, + // mode request’s mode. + mode: request.mode, + // credentials mode request’s credentials mode. + credentials: request.credentials, + // cache mode request’s cache mode. + cache: request.cache, + // redirect mode request’s redirect mode. + redirect: request.redirect, + // integrity metadata request’s integrity metadata. + integrity: request.integrity, + // keepalive request’s keepalive. + keepalive: request.keepalive, + // reload-navigation flag request’s reload-navigation flag. + reloadNavigation: request.reloadNavigation, + // history-navigation flag request’s history-navigation flag. + historyNavigation: request.historyNavigation, + // URL list A clone of request’s URL list. + urlList: [...request.urlList] + }) + const initHasKey = Object.keys(init).length !== 0 -/***/ }), + // 13. If init is not empty, then: + if (initHasKey) { + // 1. If request’s mode is "navigate", then set it to "same-origin". + if (request.mode === 'navigate') { + request.mode = 'same-origin' + } -/***/ 1698: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // 2. Unset request’s reload-navigation flag. + request.reloadNavigation = false -const assert = __nccwpck_require__(2613) + // 3. Unset request’s history-navigation flag. + request.historyNavigation = false -const { kRetryHandlerDefaultRetry } = __nccwpck_require__(1028) -const { RequestRetryError } = __nccwpck_require__(6738) -const { isDisturbed, parseHeaders, parseRangeHeader } = __nccwpck_require__(5069) + // 4. Set request’s origin to "client". + request.origin = 'client' -function calculateRetryAfterHeader (retryAfter) { - const current = Date.now() - const diff = new Date(retryAfter).getTime() - current + // 5. Set request’s referrer to "client" + request.referrer = 'client' - return diff -} + // 6. Set request’s referrer policy to the empty string. + request.referrerPolicy = '' -class RetryHandler { - constructor (opts, handlers) { - const { retryOptions, ...dispatchOpts } = opts - const { - // Retry scoped - retry: retryFn, - maxRetries, - maxTimeout, - minTimeout, - timeoutFactor, - // Response scoped - methods, - errorCodes, - retryAfter, - statusCodes - } = retryOptions ?? {} + // 7. Set request’s URL to request’s current URL. + request.url = request.urlList[request.urlList.length - 1] - this.dispatch = handlers.dispatch - this.handler = handlers.handler - this.opts = dispatchOpts - this.abort = null - this.aborted = false - this.retryOpts = { - retry: retryFn ?? RetryHandler[kRetryHandlerDefaultRetry], - retryAfter: retryAfter ?? true, - maxTimeout: maxTimeout ?? 30 * 1000, // 30s, - timeout: minTimeout ?? 500, // .5s - timeoutFactor: timeoutFactor ?? 2, - maxRetries: maxRetries ?? 5, - // What errors we should retry - methods: methods ?? ['GET', 'HEAD', 'OPTIONS', 'PUT', 'DELETE', 'TRACE'], - // Indicates which errors to retry - statusCodes: statusCodes ?? [500, 502, 503, 504, 429], - // List of errors to retry - errorCodes: errorCodes ?? [ - 'ECONNRESET', - 'ECONNREFUSED', - 'ENOTFOUND', - 'ENETDOWN', - 'ENETUNREACH', - 'EHOSTDOWN', - 'EHOSTUNREACH', - 'EPIPE' - ] + // 8. Set request’s URL list to « request’s URL ». + request.urlList = [request.url] } - this.retryCount = 0 - this.start = 0 - this.end = null - this.etag = null - this.resume = null + // 14. If init["referrer"] exists, then: + if (init.referrer !== undefined) { + // 1. Let referrer be init["referrer"]. + const referrer = init.referrer - // Handle possible onConnect duplication - this.handler.onConnect(reason => { - this.aborted = true - if (this.abort) { - this.abort(reason) + // 2. If referrer is the empty string, then set request’s referrer to "no-referrer". + if (referrer === '') { + request.referrer = 'no-referrer' } else { - this.reason = reason - } - }) - } + // 1. Let parsedReferrer be the result of parsing referrer with + // baseURL. + // 2. If parsedReferrer is failure, then throw a TypeError. + let parsedReferrer + try { + parsedReferrer = new URL(referrer, baseUrl) + } catch (err) { + throw new TypeError(`Referrer "${referrer}" is not a valid URL.`, { cause: err }) + } - onRequestSent () { - if (this.handler.onRequestSent) { - this.handler.onRequestSent() + // 3. If one of the following is true + // - parsedReferrer’s scheme is "about" and path is the string "client" + // - parsedReferrer’s origin is not same origin with origin + // then set request’s referrer to "client". + if ( + (parsedReferrer.protocol === 'about:' && parsedReferrer.hostname === 'client') || + (origin && !sameOrigin(parsedReferrer, environmentSettingsObject.settingsObject.baseUrl)) + ) { + request.referrer = 'client' + } else { + // 4. Otherwise, set request’s referrer to parsedReferrer. + request.referrer = parsedReferrer + } + } } - } - onUpgrade (statusCode, headers, socket) { - if (this.handler.onUpgrade) { - this.handler.onUpgrade(statusCode, headers, socket) + // 15. If init["referrerPolicy"] exists, then set request’s referrer policy + // to it. + if (init.referrerPolicy !== undefined) { + request.referrerPolicy = init.referrerPolicy } - } - onConnect (abort) { - if (this.aborted) { - abort(this.reason) + // 16. Let mode be init["mode"] if it exists, and fallbackMode otherwise. + let mode + if (init.mode !== undefined) { + mode = init.mode } else { - this.abort = abort + mode = fallbackMode } - } - - onBodySent (chunk) { - if (this.handler.onBodySent) return this.handler.onBodySent(chunk) - } - static [kRetryHandlerDefaultRetry] (err, { state, opts }, cb) { - const { statusCode, code, headers } = err - const { method, retryOptions } = opts - const { - maxRetries, - timeout, - maxTimeout, - timeoutFactor, - statusCodes, - errorCodes, - methods - } = retryOptions - let { counter, currentTimeout } = state + // 17. If mode is "navigate", then throw a TypeError. + if (mode === 'navigate') { + throw webidl.errors.exception({ + header: 'Request constructor', + message: 'invalid request mode navigate.' + }) + } - currentTimeout = - currentTimeout != null && currentTimeout > 0 ? currentTimeout : timeout + // 18. If mode is non-null, set request’s mode to mode. + if (mode != null) { + request.mode = mode + } - // Any code that is not a Undici's originated and allowed to retry - if ( - code && - code !== 'UND_ERR_REQ_RETRY' && - code !== 'UND_ERR_SOCKET' && - !errorCodes.includes(code) - ) { - cb(err) - return + // 19. If init["credentials"] exists, then set request’s credentials mode + // to it. + if (init.credentials !== undefined) { + request.credentials = init.credentials } - // If a set of method are provided and the current method is not in the list - if (Array.isArray(methods) && !methods.includes(method)) { - cb(err) - return + // 18. If init["cache"] exists, then set request’s cache mode to it. + if (init.cache !== undefined) { + request.cache = init.cache } - // If a set of status code are provided and the current status code is not in the list - if ( - statusCode != null && - Array.isArray(statusCodes) && - !statusCodes.includes(statusCode) - ) { - cb(err) - return + // 21. If request’s cache mode is "only-if-cached" and request’s mode is + // not "same-origin", then throw a TypeError. + if (request.cache === 'only-if-cached' && request.mode !== 'same-origin') { + throw new TypeError( + "'only-if-cached' can be set only with 'same-origin' mode" + ) } - // If we reached the max number of retries - if (counter > maxRetries) { - cb(err) - return + // 22. If init["redirect"] exists, then set request’s redirect mode to it. + if (init.redirect !== undefined) { + request.redirect = init.redirect } - let retryAfterHeader = headers != null && headers['retry-after'] - if (retryAfterHeader) { - retryAfterHeader = Number(retryAfterHeader) - retryAfterHeader = isNaN(retryAfterHeader) - ? calculateRetryAfterHeader(retryAfterHeader) - : retryAfterHeader * 1e3 // Retry-After is in seconds + // 23. If init["integrity"] exists, then set request’s integrity metadata to it. + if (init.integrity != null) { + request.integrity = String(init.integrity) } - const retryTimeout = - retryAfterHeader > 0 - ? Math.min(retryAfterHeader, maxTimeout) - : Math.min(currentTimeout * timeoutFactor ** counter, maxTimeout) + // 24. If init["keepalive"] exists, then set request’s keepalive to it. + if (init.keepalive !== undefined) { + request.keepalive = Boolean(init.keepalive) + } - state.currentTimeout = retryTimeout + // 25. If init["method"] exists, then: + if (init.method !== undefined) { + // 1. Let method be init["method"]. + let method = init.method - setTimeout(() => cb(null), retryTimeout) - } + const mayBeNormalized = normalizedMethodRecords[method] - onHeaders (statusCode, rawHeaders, resume, statusMessage) { - const headers = parseHeaders(rawHeaders) + if (mayBeNormalized !== undefined) { + // Note: Bypass validation DELETE, GET, HEAD, OPTIONS, POST, PUT, PATCH and these lowercase ones + request.method = mayBeNormalized + } else { + // 2. If method is not a method or method is a forbidden method, then + // throw a TypeError. + if (!isValidHTTPToken(method)) { + throw new TypeError(`'${method}' is not a valid HTTP method.`) + } - this.retryCount += 1 + const upperCase = method.toUpperCase() - if (statusCode >= 300) { - this.abort( - new RequestRetryError('Request failed', statusCode, { - headers, - count: this.retryCount - }) - ) - return false - } + if (forbiddenMethodsSet.has(upperCase)) { + throw new TypeError(`'${method}' HTTP method is unsupported.`) + } - // Checkpoint for resume from where we left it - if (this.resume != null) { - this.resume = null + // 3. Normalize method. + // https://fetch.spec.whatwg.org/#concept-method-normalize + // Note: must be in uppercase + method = normalizedMethodRecordsBase[upperCase] ?? method - if (statusCode !== 206) { - return true + // 4. Set request’s method to method. + request.method = method } - const contentRange = parseRangeHeader(headers['content-range']) - // If no content range - if (!contentRange) { - this.abort( - new RequestRetryError('Content-Range mismatch', statusCode, { - headers, - count: this.retryCount - }) - ) - return false - } + if (!patchMethodWarning && request.method === 'patch') { + process.emitWarning('Using `patch` is highly likely to result in a `405 Method Not Allowed`. `PATCH` is much more likely to succeed.', { + code: 'UNDICI-FETCH-patch' + }) - // Let's start with a weak etag check - if (this.etag != null && this.etag !== headers.etag) { - this.abort( - new RequestRetryError('ETag mismatch', statusCode, { - headers, - count: this.retryCount - }) - ) - return false + patchMethodWarning = true } - - const { start, size, end = size } = contentRange - - assert(this.start === start, 'content-range mismatch') - assert(this.end == null || this.end === end, 'content-range mismatch') - - this.resume = resume - return true } - if (this.end == null) { - if (statusCode === 206) { - // First time we receive 206 - const range = parseRangeHeader(headers['content-range']) + // 26. If init["signal"] exists, then set signal to it. + if (init.signal !== undefined) { + signal = init.signal + } - if (range == null) { - return this.handler.onHeaders( - statusCode, - rawHeaders, - resume, - statusMessage - ) - } + // 27. Set this’s request to request. + this[kState] = request - const { start, size, end = size } = range + // 28. Set this’s signal to a new AbortSignal object with this’s relevant + // Realm. + // TODO: could this be simplified with AbortSignal.any + // (https://dom.spec.whatwg.org/#dom-abortsignal-any) + const ac = new AbortController() + this[kSignal] = ac.signal - assert( - start != null && Number.isFinite(start) && this.start !== start, - 'content-range mismatch' - ) - assert(Number.isFinite(start)) - assert( - end != null && Number.isFinite(end) && this.end !== end, - 'invalid content-length' + // 29. If signal is not null, then make this’s signal follow signal. + if (signal != null) { + if ( + !signal || + typeof signal.aborted !== 'boolean' || + typeof signal.addEventListener !== 'function' + ) { + throw new TypeError( + "Failed to construct 'Request': member signal is not of type AbortSignal." ) - - this.start = start - this.end = end } - // We make our best to checkpoint the body for further range headers - if (this.end == null) { - const contentLength = headers['content-length'] - this.end = contentLength != null ? Number(contentLength) : null - } + if (signal.aborted) { + ac.abort(signal.reason) + } else { + // Keep a strong ref to ac while request object + // is alive. This is needed to prevent AbortController + // from being prematurely garbage collected. + // See, https://github.com/nodejs/undici/issues/1926. + this[kAbortController] = ac - assert(Number.isFinite(this.start)) - assert( - this.end == null || Number.isFinite(this.end), - 'invalid content-length' - ) + const acRef = new WeakRef(ac) + const abort = buildAbort(acRef) - this.resume = resume - this.etag = headers.etag != null ? headers.etag : null + // Third-party AbortControllers may not work with these. + // See, https://github.com/nodejs/undici/pull/1910#issuecomment-1464495619. + try { + // If the max amount of listeners is equal to the default, increase it + // This is only available in node >= v19.9.0 + if (typeof getMaxListeners === 'function' && getMaxListeners(signal) === defaultMaxListeners) { + setMaxListeners(1500, signal) + } else if (getEventListeners(signal, 'abort').length >= defaultMaxListeners) { + setMaxListeners(1500, signal) + } + } catch {} - return this.handler.onHeaders( - statusCode, - rawHeaders, - resume, - statusMessage - ) + util.addAbortListener(signal, abort) + // The third argument must be a registry key to be unregistered. + // Without it, you cannot unregister. + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/FinalizationRegistry + // abort is used as the unregister key. (because it is unique) + requestFinalizer.register(ac, { signal, abort }, abort) + } } - const err = new RequestRetryError('Request failed', statusCode, { - headers, - count: this.retryCount - }) - - this.abort(err) - - return false - } + // 30. Set this’s headers to a new Headers object with this’s relevant + // Realm, whose header list is request’s header list and guard is + // "request". + this[kHeaders] = new Headers(kConstruct) + setHeadersList(this[kHeaders], request.headersList) + setHeadersGuard(this[kHeaders], 'request') - onData (chunk) { - this.start += chunk.length + // 31. If this’s request’s mode is "no-cors", then: + if (mode === 'no-cors') { + // 1. If this’s request’s method is not a CORS-safelisted method, + // then throw a TypeError. + if (!corsSafeListedMethodsSet.has(request.method)) { + throw new TypeError( + `'${request.method} is unsupported in no-cors mode.` + ) + } - return this.handler.onData(chunk) - } + // 2. Set this’s headers’s guard to "request-no-cors". + setHeadersGuard(this[kHeaders], 'request-no-cors') + } - onComplete (rawTrailers) { - this.retryCount = 0 - return this.handler.onComplete(rawTrailers) - } - - onError (err) { - if (this.aborted || isDisturbed(this.opts.body)) { - return this.handler.onError(err) - } - - this.retryOpts.retry( - err, - { - state: { counter: this.retryCount++, currentTimeout: this.retryAfter }, - opts: { retryOptions: this.retryOpts, ...this.opts } - }, - onRetry.bind(this) - ) + // 32. If init is not empty, then: + if (initHasKey) { + /** @type {HeadersList} */ + const headersList = getHeadersList(this[kHeaders]) + // 1. Let headers be a copy of this’s headers and its associated header + // list. + // 2. If init["headers"] exists, then set headers to init["headers"]. + const headers = init.headers !== undefined ? init.headers : new HeadersList(headersList) - function onRetry (err) { - if (err != null || this.aborted || isDisturbed(this.opts.body)) { - return this.handler.onError(err) - } + // 3. Empty this’s headers’s header list. + headersList.clear() - if (this.start !== 0) { - this.opts = { - ...this.opts, - headers: { - ...this.opts.headers, - range: `bytes=${this.start}-${this.end ?? ''}` - } + // 4. If headers is a Headers object, then for each header in its header + // list, append header’s name/header’s value to this’s headers. + if (headers instanceof HeadersList) { + for (const { name, value } of headers.rawValues()) { + headersList.append(name, value, false) } - } - - try { - this.dispatch(this.opts, this) - } catch (err) { - this.handler.onError(err) + // Note: Copy the `set-cookie` meta-data. + headersList.cookies = headers.cookies + } else { + // 5. Otherwise, fill this’s headers with headers. + fillHeaders(this[kHeaders], headers) } } - } -} - -module.exports = RetryHandler + // 33. Let inputBody be input’s request’s body if input is a Request + // object; otherwise null. + const inputBody = input instanceof Request ? input[kState].body : null -/***/ }), + // 34. If either init["body"] exists and is non-null or inputBody is + // non-null, and request’s method is `GET` or `HEAD`, then throw a + // TypeError. + if ( + (init.body != null || inputBody != null) && + (request.method === 'GET' || request.method === 'HEAD') + ) { + throw new TypeError('Request with GET/HEAD method cannot have body.') + } -/***/ 7646: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // 35. Let initBody be null. + let initBody = null -"use strict"; + // 36. If init["body"] exists and is non-null, then: + if (init.body != null) { + // 1. Let Content-Type be null. + // 2. Set initBody and Content-Type to the result of extracting + // init["body"], with keepalive set to request’s keepalive. + const [extractedBody, contentType] = extractBody( + init.body, + request.keepalive + ) + initBody = extractedBody + // 3, If Content-Type is non-null and this’s headers’s header list does + // not contain `Content-Type`, then append `Content-Type`/Content-Type to + // this’s headers. + if (contentType && !getHeadersList(this[kHeaders]).contains('content-type', true)) { + this[kHeaders].append('content-type', contentType) + } + } -const RedirectHandler = __nccwpck_require__(6858) + // 37. Let inputOrInitBody be initBody if it is non-null; otherwise + // inputBody. + const inputOrInitBody = initBody ?? inputBody -function createRedirectInterceptor ({ maxRedirections: defaultMaxRedirections }) { - return (dispatch) => { - return function Intercept (opts, handler) { - const { maxRedirections = defaultMaxRedirections } = opts + // 38. If inputOrInitBody is non-null and inputOrInitBody’s source is + // null, then: + if (inputOrInitBody != null && inputOrInitBody.source == null) { + // 1. If initBody is non-null and init["duplex"] does not exist, + // then throw a TypeError. + if (initBody != null && init.duplex == null) { + throw new TypeError('RequestInit: duplex option is required when sending a body.') + } - if (!maxRedirections) { - return dispatch(opts, handler) + // 2. If this’s request’s mode is neither "same-origin" nor "cors", + // then throw a TypeError. + if (request.mode !== 'same-origin' && request.mode !== 'cors') { + throw new TypeError( + 'If request is made from ReadableStream, mode should be "same-origin" or "cors"' + ) } - const redirectHandler = new RedirectHandler(dispatch, maxRedirections, opts, handler) - opts = { ...opts, maxRedirections: 0 } // Stop sub dispatcher from also redirecting. - return dispatch(opts, redirectHandler) + // 3. Set this’s request’s use-CORS-preflight flag. + request.useCORSPreflightFlag = true } - } -} - -module.exports = createRedirectInterceptor + // 39. Let finalBody be inputOrInitBody. + let finalBody = inputOrInitBody -/***/ }), + // 40. If initBody is null and inputBody is non-null, then: + if (initBody == null && inputBody != null) { + // 1. If input is unusable, then throw a TypeError. + if (bodyUnusable(input)) { + throw new TypeError( + 'Cannot construct a Request with a Request object that has already been used.' + ) + } -/***/ 4319: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + // 2. Set finalBody to the result of creating a proxy for inputBody. + // https://streams.spec.whatwg.org/#readablestream-create-a-proxy + const identityTransform = new TransformStream() + inputBody.stream.pipeThrough(identityTransform) + finalBody = { + source: inputBody.source, + length: inputBody.length, + stream: identityTransform.readable + } + } -"use strict"; + // 41. Set this’s request’s body to finalBody. + this[kState].body = finalBody + } -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.SPECIAL_HEADERS = exports.HEADER_STATE = exports.MINOR = exports.MAJOR = exports.CONNECTION_TOKEN_CHARS = exports.HEADER_CHARS = exports.TOKEN = exports.STRICT_TOKEN = exports.HEX = exports.URL_CHAR = exports.STRICT_URL_CHAR = exports.USERINFO_CHARS = exports.MARK = exports.ALPHANUM = exports.NUM = exports.HEX_MAP = exports.NUM_MAP = exports.ALPHA = exports.FINISH = exports.H_METHOD_MAP = exports.METHOD_MAP = exports.METHODS_RTSP = exports.METHODS_ICE = exports.METHODS_HTTP = exports.METHODS = exports.LENIENT_FLAGS = exports.FLAGS = exports.TYPE = exports.ERROR = void 0; -const utils_1 = __nccwpck_require__(4383); -// C headers -var ERROR; -(function (ERROR) { - ERROR[ERROR["OK"] = 0] = "OK"; - ERROR[ERROR["INTERNAL"] = 1] = "INTERNAL"; - ERROR[ERROR["STRICT"] = 2] = "STRICT"; - ERROR[ERROR["LF_EXPECTED"] = 3] = "LF_EXPECTED"; - ERROR[ERROR["UNEXPECTED_CONTENT_LENGTH"] = 4] = "UNEXPECTED_CONTENT_LENGTH"; - ERROR[ERROR["CLOSED_CONNECTION"] = 5] = "CLOSED_CONNECTION"; - ERROR[ERROR["INVALID_METHOD"] = 6] = "INVALID_METHOD"; - ERROR[ERROR["INVALID_URL"] = 7] = "INVALID_URL"; - ERROR[ERROR["INVALID_CONSTANT"] = 8] = "INVALID_CONSTANT"; - ERROR[ERROR["INVALID_VERSION"] = 9] = "INVALID_VERSION"; - ERROR[ERROR["INVALID_HEADER_TOKEN"] = 10] = "INVALID_HEADER_TOKEN"; - ERROR[ERROR["INVALID_CONTENT_LENGTH"] = 11] = "INVALID_CONTENT_LENGTH"; - ERROR[ERROR["INVALID_CHUNK_SIZE"] = 12] = "INVALID_CHUNK_SIZE"; - ERROR[ERROR["INVALID_STATUS"] = 13] = "INVALID_STATUS"; - ERROR[ERROR["INVALID_EOF_STATE"] = 14] = "INVALID_EOF_STATE"; - ERROR[ERROR["INVALID_TRANSFER_ENCODING"] = 15] = "INVALID_TRANSFER_ENCODING"; - ERROR[ERROR["CB_MESSAGE_BEGIN"] = 16] = "CB_MESSAGE_BEGIN"; - ERROR[ERROR["CB_HEADERS_COMPLETE"] = 17] = "CB_HEADERS_COMPLETE"; - ERROR[ERROR["CB_MESSAGE_COMPLETE"] = 18] = "CB_MESSAGE_COMPLETE"; - ERROR[ERROR["CB_CHUNK_HEADER"] = 19] = "CB_CHUNK_HEADER"; - ERROR[ERROR["CB_CHUNK_COMPLETE"] = 20] = "CB_CHUNK_COMPLETE"; - ERROR[ERROR["PAUSED"] = 21] = "PAUSED"; - ERROR[ERROR["PAUSED_UPGRADE"] = 22] = "PAUSED_UPGRADE"; - ERROR[ERROR["PAUSED_H2_UPGRADE"] = 23] = "PAUSED_H2_UPGRADE"; - ERROR[ERROR["USER"] = 24] = "USER"; -})(ERROR = exports.ERROR || (exports.ERROR = {})); -var TYPE; -(function (TYPE) { - TYPE[TYPE["BOTH"] = 0] = "BOTH"; - TYPE[TYPE["REQUEST"] = 1] = "REQUEST"; - TYPE[TYPE["RESPONSE"] = 2] = "RESPONSE"; -})(TYPE = exports.TYPE || (exports.TYPE = {})); -var FLAGS; -(function (FLAGS) { - FLAGS[FLAGS["CONNECTION_KEEP_ALIVE"] = 1] = "CONNECTION_KEEP_ALIVE"; - FLAGS[FLAGS["CONNECTION_CLOSE"] = 2] = "CONNECTION_CLOSE"; - FLAGS[FLAGS["CONNECTION_UPGRADE"] = 4] = "CONNECTION_UPGRADE"; - FLAGS[FLAGS["CHUNKED"] = 8] = "CHUNKED"; - FLAGS[FLAGS["UPGRADE"] = 16] = "UPGRADE"; - FLAGS[FLAGS["CONTENT_LENGTH"] = 32] = "CONTENT_LENGTH"; - FLAGS[FLAGS["SKIPBODY"] = 64] = "SKIPBODY"; - FLAGS[FLAGS["TRAILING"] = 128] = "TRAILING"; - // 1 << 8 is unused - FLAGS[FLAGS["TRANSFER_ENCODING"] = 512] = "TRANSFER_ENCODING"; -})(FLAGS = exports.FLAGS || (exports.FLAGS = {})); -var LENIENT_FLAGS; -(function (LENIENT_FLAGS) { - LENIENT_FLAGS[LENIENT_FLAGS["HEADERS"] = 1] = "HEADERS"; - LENIENT_FLAGS[LENIENT_FLAGS["CHUNKED_LENGTH"] = 2] = "CHUNKED_LENGTH"; - LENIENT_FLAGS[LENIENT_FLAGS["KEEP_ALIVE"] = 4] = "KEEP_ALIVE"; -})(LENIENT_FLAGS = exports.LENIENT_FLAGS || (exports.LENIENT_FLAGS = {})); -var METHODS; -(function (METHODS) { - METHODS[METHODS["DELETE"] = 0] = "DELETE"; - METHODS[METHODS["GET"] = 1] = "GET"; - METHODS[METHODS["HEAD"] = 2] = "HEAD"; - METHODS[METHODS["POST"] = 3] = "POST"; - METHODS[METHODS["PUT"] = 4] = "PUT"; - /* pathological */ - METHODS[METHODS["CONNECT"] = 5] = "CONNECT"; - METHODS[METHODS["OPTIONS"] = 6] = "OPTIONS"; - METHODS[METHODS["TRACE"] = 7] = "TRACE"; - /* WebDAV */ - METHODS[METHODS["COPY"] = 8] = "COPY"; - METHODS[METHODS["LOCK"] = 9] = "LOCK"; - METHODS[METHODS["MKCOL"] = 10] = "MKCOL"; - METHODS[METHODS["MOVE"] = 11] = "MOVE"; - METHODS[METHODS["PROPFIND"] = 12] = "PROPFIND"; - METHODS[METHODS["PROPPATCH"] = 13] = "PROPPATCH"; - METHODS[METHODS["SEARCH"] = 14] = "SEARCH"; - METHODS[METHODS["UNLOCK"] = 15] = "UNLOCK"; - METHODS[METHODS["BIND"] = 16] = "BIND"; - METHODS[METHODS["REBIND"] = 17] = "REBIND"; - METHODS[METHODS["UNBIND"] = 18] = "UNBIND"; - METHODS[METHODS["ACL"] = 19] = "ACL"; - /* subversion */ - METHODS[METHODS["REPORT"] = 20] = "REPORT"; - METHODS[METHODS["MKACTIVITY"] = 21] = "MKACTIVITY"; - METHODS[METHODS["CHECKOUT"] = 22] = "CHECKOUT"; - METHODS[METHODS["MERGE"] = 23] = "MERGE"; - /* upnp */ - METHODS[METHODS["M-SEARCH"] = 24] = "M-SEARCH"; - METHODS[METHODS["NOTIFY"] = 25] = "NOTIFY"; - METHODS[METHODS["SUBSCRIBE"] = 26] = "SUBSCRIBE"; - METHODS[METHODS["UNSUBSCRIBE"] = 27] = "UNSUBSCRIBE"; - /* RFC-5789 */ - METHODS[METHODS["PATCH"] = 28] = "PATCH"; - METHODS[METHODS["PURGE"] = 29] = "PURGE"; - /* CalDAV */ - METHODS[METHODS["MKCALENDAR"] = 30] = "MKCALENDAR"; - /* RFC-2068, section 19.6.1.2 */ - METHODS[METHODS["LINK"] = 31] = "LINK"; - METHODS[METHODS["UNLINK"] = 32] = "UNLINK"; - /* icecast */ - METHODS[METHODS["SOURCE"] = 33] = "SOURCE"; - /* RFC-7540, section 11.6 */ - METHODS[METHODS["PRI"] = 34] = "PRI"; - /* RFC-2326 RTSP */ - METHODS[METHODS["DESCRIBE"] = 35] = "DESCRIBE"; - METHODS[METHODS["ANNOUNCE"] = 36] = "ANNOUNCE"; - METHODS[METHODS["SETUP"] = 37] = "SETUP"; - METHODS[METHODS["PLAY"] = 38] = "PLAY"; - METHODS[METHODS["PAUSE"] = 39] = "PAUSE"; - METHODS[METHODS["TEARDOWN"] = 40] = "TEARDOWN"; - METHODS[METHODS["GET_PARAMETER"] = 41] = "GET_PARAMETER"; - METHODS[METHODS["SET_PARAMETER"] = 42] = "SET_PARAMETER"; - METHODS[METHODS["REDIRECT"] = 43] = "REDIRECT"; - METHODS[METHODS["RECORD"] = 44] = "RECORD"; - /* RAOP */ - METHODS[METHODS["FLUSH"] = 45] = "FLUSH"; -})(METHODS = exports.METHODS || (exports.METHODS = {})); -exports.METHODS_HTTP = [ - METHODS.DELETE, - METHODS.GET, - METHODS.HEAD, - METHODS.POST, - METHODS.PUT, - METHODS.CONNECT, - METHODS.OPTIONS, - METHODS.TRACE, - METHODS.COPY, - METHODS.LOCK, - METHODS.MKCOL, - METHODS.MOVE, - METHODS.PROPFIND, - METHODS.PROPPATCH, - METHODS.SEARCH, - METHODS.UNLOCK, - METHODS.BIND, - METHODS.REBIND, - METHODS.UNBIND, - METHODS.ACL, - METHODS.REPORT, - METHODS.MKACTIVITY, - METHODS.CHECKOUT, - METHODS.MERGE, - METHODS['M-SEARCH'], - METHODS.NOTIFY, - METHODS.SUBSCRIBE, - METHODS.UNSUBSCRIBE, - METHODS.PATCH, - METHODS.PURGE, - METHODS.MKCALENDAR, - METHODS.LINK, - METHODS.UNLINK, - METHODS.PRI, - // TODO(indutny): should we allow it with HTTP? - METHODS.SOURCE, -]; -exports.METHODS_ICE = [ - METHODS.SOURCE, -]; -exports.METHODS_RTSP = [ - METHODS.OPTIONS, - METHODS.DESCRIBE, - METHODS.ANNOUNCE, - METHODS.SETUP, - METHODS.PLAY, - METHODS.PAUSE, - METHODS.TEARDOWN, - METHODS.GET_PARAMETER, - METHODS.SET_PARAMETER, - METHODS.REDIRECT, - METHODS.RECORD, - METHODS.FLUSH, - // For AirPlay - METHODS.GET, - METHODS.POST, -]; -exports.METHOD_MAP = utils_1.enumToMap(METHODS); -exports.H_METHOD_MAP = {}; -Object.keys(exports.METHOD_MAP).forEach((key) => { - if (/^H/.test(key)) { - exports.H_METHOD_MAP[key] = exports.METHOD_MAP[key]; - } -}); -var FINISH; -(function (FINISH) { - FINISH[FINISH["SAFE"] = 0] = "SAFE"; - FINISH[FINISH["SAFE_WITH_CB"] = 1] = "SAFE_WITH_CB"; - FINISH[FINISH["UNSAFE"] = 2] = "UNSAFE"; -})(FINISH = exports.FINISH || (exports.FINISH = {})); -exports.ALPHA = []; -for (let i = 'A'.charCodeAt(0); i <= 'Z'.charCodeAt(0); i++) { - // Upper case - exports.ALPHA.push(String.fromCharCode(i)); - // Lower case - exports.ALPHA.push(String.fromCharCode(i + 0x20)); -} -exports.NUM_MAP = { - 0: 0, 1: 1, 2: 2, 3: 3, 4: 4, - 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, -}; -exports.HEX_MAP = { - 0: 0, 1: 1, 2: 2, 3: 3, 4: 4, - 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, - A: 0XA, B: 0XB, C: 0XC, D: 0XD, E: 0XE, F: 0XF, - a: 0xa, b: 0xb, c: 0xc, d: 0xd, e: 0xe, f: 0xf, -}; -exports.NUM = [ - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', -]; -exports.ALPHANUM = exports.ALPHA.concat(exports.NUM); -exports.MARK = ['-', '_', '.', '!', '~', '*', '\'', '(', ')']; -exports.USERINFO_CHARS = exports.ALPHANUM - .concat(exports.MARK) - .concat(['%', ';', ':', '&', '=', '+', '$', ',']); -// TODO(indutny): use RFC -exports.STRICT_URL_CHAR = [ - '!', '"', '$', '%', '&', '\'', - '(', ')', '*', '+', ',', '-', '.', '/', - ':', ';', '<', '=', '>', - '@', '[', '\\', ']', '^', '_', - '`', - '{', '|', '}', '~', -].concat(exports.ALPHANUM); -exports.URL_CHAR = exports.STRICT_URL_CHAR - .concat(['\t', '\f']); -// All characters with 0x80 bit set to 1 -for (let i = 0x80; i <= 0xff; i++) { - exports.URL_CHAR.push(i); -} -exports.HEX = exports.NUM.concat(['a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F']); -/* Tokens as defined by rfc 2616. Also lowercases them. - * token = 1* - * separators = "(" | ")" | "<" | ">" | "@" - * | "," | ";" | ":" | "\" | <"> - * | "/" | "[" | "]" | "?" | "=" - * | "{" | "}" | SP | HT - */ -exports.STRICT_TOKEN = [ - '!', '#', '$', '%', '&', '\'', - '*', '+', '-', '.', - '^', '_', '`', - '|', '~', -].concat(exports.ALPHANUM); -exports.TOKEN = exports.STRICT_TOKEN.concat([' ']); -/* - * Verify that a char is a valid visible (printable) US-ASCII - * character or %x80-FF - */ -exports.HEADER_CHARS = ['\t']; -for (let i = 32; i <= 255; i++) { - if (i !== 127) { - exports.HEADER_CHARS.push(i); - } -} -// ',' = \x44 -exports.CONNECTION_TOKEN_CHARS = exports.HEADER_CHARS.filter((c) => c !== 44); -exports.MAJOR = exports.NUM_MAP; -exports.MINOR = exports.MAJOR; -var HEADER_STATE; -(function (HEADER_STATE) { - HEADER_STATE[HEADER_STATE["GENERAL"] = 0] = "GENERAL"; - HEADER_STATE[HEADER_STATE["CONNECTION"] = 1] = "CONNECTION"; - HEADER_STATE[HEADER_STATE["CONTENT_LENGTH"] = 2] = "CONTENT_LENGTH"; - HEADER_STATE[HEADER_STATE["TRANSFER_ENCODING"] = 3] = "TRANSFER_ENCODING"; - HEADER_STATE[HEADER_STATE["UPGRADE"] = 4] = "UPGRADE"; - HEADER_STATE[HEADER_STATE["CONNECTION_KEEP_ALIVE"] = 5] = "CONNECTION_KEEP_ALIVE"; - HEADER_STATE[HEADER_STATE["CONNECTION_CLOSE"] = 6] = "CONNECTION_CLOSE"; - HEADER_STATE[HEADER_STATE["CONNECTION_UPGRADE"] = 7] = "CONNECTION_UPGRADE"; - HEADER_STATE[HEADER_STATE["TRANSFER_ENCODING_CHUNKED"] = 8] = "TRANSFER_ENCODING_CHUNKED"; -})(HEADER_STATE = exports.HEADER_STATE || (exports.HEADER_STATE = {})); -exports.SPECIAL_HEADERS = { - 'connection': HEADER_STATE.CONNECTION, - 'content-length': HEADER_STATE.CONTENT_LENGTH, - 'proxy-connection': HEADER_STATE.CONNECTION, - 'transfer-encoding': HEADER_STATE.TRANSFER_ENCODING, - 'upgrade': HEADER_STATE.UPGRADE, -}; -//# sourceMappingURL=constants.js.map + // Returns request’s HTTP method, which is "GET" by default. + get method () { + webidl.brandCheck(this, Request) -/***/ }), + // The method getter steps are to return this’s request’s method. + return this[kState].method + } -/***/ 9753: -/***/ ((module) => { + // Returns the URL of request as a string. + get url () { + webidl.brandCheck(this, Request) -module.exports = 'AGFzbQEAAAABMAhgAX8Bf2ADf39/AX9gBH9/f38Bf2AAAGADf39/AGABfwBgAn9/AGAGf39/f39/AALLAQgDZW52GHdhc21fb25faGVhZGVyc19jb21wbGV0ZQACA2VudhV3YXNtX29uX21lc3NhZ2VfYmVnaW4AAANlbnYLd2FzbV9vbl91cmwAAQNlbnYOd2FzbV9vbl9zdGF0dXMAAQNlbnYUd2FzbV9vbl9oZWFkZXJfZmllbGQAAQNlbnYUd2FzbV9vbl9oZWFkZXJfdmFsdWUAAQNlbnYMd2FzbV9vbl9ib2R5AAEDZW52GHdhc21fb25fbWVzc2FnZV9jb21wbGV0ZQAAA0ZFAwMEAAAFAAAAAAAABQEFAAUFBQAABgAAAAAGBgYGAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAAABAQcAAAUFAwABBAUBcAESEgUDAQACBggBfwFBgNQECwfRBSIGbWVtb3J5AgALX2luaXRpYWxpemUACRlfX2luZGlyZWN0X2Z1bmN0aW9uX3RhYmxlAQALbGxodHRwX2luaXQAChhsbGh0dHBfc2hvdWxkX2tlZXBfYWxpdmUAQQxsbGh0dHBfYWxsb2MADAZtYWxsb2MARgtsbGh0dHBfZnJlZQANBGZyZWUASA9sbGh0dHBfZ2V0X3R5cGUADhVsbGh0dHBfZ2V0X2h0dHBfbWFqb3IADxVsbGh0dHBfZ2V0X2h0dHBfbWlub3IAEBFsbGh0dHBfZ2V0X21ldGhvZAARFmxsaHR0cF9nZXRfc3RhdHVzX2NvZGUAEhJsbGh0dHBfZ2V0X3VwZ3JhZGUAEwxsbGh0dHBfcmVzZXQAFA5sbGh0dHBfZXhlY3V0ZQAVFGxsaHR0cF9zZXR0aW5nc19pbml0ABYNbGxodHRwX2ZpbmlzaAAXDGxsaHR0cF9wYXVzZQAYDWxsaHR0cF9yZXN1bWUAGRtsbGh0dHBfcmVzdW1lX2FmdGVyX3VwZ3JhZGUAGhBsbGh0dHBfZ2V0X2Vycm5vABsXbGxodHRwX2dldF9lcnJvcl9yZWFzb24AHBdsbGh0dHBfc2V0X2Vycm9yX3JlYXNvbgAdFGxsaHR0cF9nZXRfZXJyb3JfcG9zAB4RbGxodHRwX2Vycm5vX25hbWUAHxJsbGh0dHBfbWV0aG9kX25hbWUAIBJs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ADcDACAAQShqQgA3AwAgAEEgakIANwMAIABBEGpCADcDACAAQQhqQgA3AwAgAEHdATYCHEEAC3sBAX8CQCAAKAIMIgMNAAJAIAAoAgRFDQAgACABNgIECwJAIAAgASACEMSAgIAAIgMNACAAKAIMDwsgACADNgIcQQAhAyAAKAIEIgFFDQAgACABIAIgACgCCBGBgICAAAAiAUUNACAAIAI2AhQgACABNgIMIAEhAwsgAwvk8wEDDn8DfgR/I4CAgIAAQRBrIgMkgICAgAAgASEEIAEhBSABIQYgASEHIAEhCCABIQkgASEKIAEhCyABIQwgASENIAEhDiABIQ8CQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgACgCHCIQQX9qDt0B2gEB2QECAwQFBgcICQoLDA0O2AEPENcBERLWARMUFRYXGBkaG+AB3wEcHR7VAR8gISIjJCXUASYnKCkqKyzTAdIBLS7RAdABLzAxMjM0NTY3ODk6Ozw9Pj9AQUJDREVG2wFHSElKzwHOAUvNAUzMAU1OT1BRUlNUVVZXWFlaW1xdXl9gYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH1+f4ABgQGCAYMBhAGFAYYBhwGIAYkB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QAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAC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FCAAIBA2AgxBACEQDLIBCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQp4CAgAAiEA0AIAEhAQxNCyAAQdMANgIcIAAgATYCFCAAIBA2AgxBACEQDLEBCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQp4CAgAAiEA0AIAEhAQxRCyAAQeUANgIcIAAgATYCFCAAIBA2AgxBACEQDLABCyAAQQA2AhwgACABNgIUIABBxoqAgAA2AhAgAEEHNgIMQQAhEAyvAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMSQsgAEHSADYCHCAAIAE2AhQgACAQNgIMQQAhEAyuAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMSQsgAEHTADYCHCAAIAE2AhQgACAQNgIMQQAhEAytAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMTQsgAEHlADYCHCAAIAE2AhQgACAQNgIMQQAhEAysAQsgAEEANgIcIAAgATYCFCAAQdyIgIAANgIQIABBBzYCDEEAIRAMqwELIBBBP0cNASABQQFqIQELQQUhEAyQAQtBACEQIABBADYCHCAAIAE2AhQgAEH9koCAADYCECAAQQc2AgwMqAELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDEILIABB0gA2AhwgACABNgIUIAAgEDYCDEEAIRAMpwELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDEILIABB0wA2AhwgACABNgIUIAAgEDYCDEEAIRAMpgELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDEYLIABB5QA2AhwgACABNgIUIAAgEDYCDEEAIRAMpQELIAAoAgQhASAAQQA2AgQCQCAAIAEgFBCngICAACIBDQAgFCEBDD8LIABB0gA2AhwgACAUNgIUIAAgATYCDEEAIRAMpAELIAAoAgQhASAAQQA2AgQCQCAAIAEgFBCngICAACIBDQAgFCEBDD8LIABB0wA2AhwgACAUNgIUIAAgATYCDEEAIRAMowELIAAoAgQhASAAQQA2AgQCQCAAIAEgFBCngICAACIBDQAgFCEBDEMLIABB5QA2AhwgACAU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YWdlX2JlZ2luYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlYCBjYWxsYmFjayBlcnJvcgBgb25fc3RhdHVzX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fdmVyc2lvbl9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX3VybF9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX2NodW5rX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25faGVhZGVyX3ZhbHVlX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fbWVzc2FnZV9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX21ldGhvZF9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX2hlYWRlcl9maWVsZF9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX2NodW5rX2V4dGVuc2lvbl9uYW1lYCBjYWxsYmFjayBlcnJvcgBVbmV4cGVjdGVkIGNoYXIgaW4gdXJsIHNlcnZlcgBJbnZhbGlkIGhlYWRlciB2YWx1ZSBjaGFyAEludmFsaWQgaGVhZGVyIGZpZWxkIGNoYXIAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl92ZXJzaW9uAEludmFsaWQgbWlub3IgdmVyc2lvbgBJbnZhbGlkIG1ham9yIHZlcnNpb24ARXhwZWN0ZWQgc3BhY2UgYWZ0ZXIgdmVyc2lvbgBFeHBlY3RlZCBDUkxGIGFmdGVyIHZlcnNpb24ASW52YWxpZCBIVFRQIHZlcnNpb24ASW52YWxpZCBoZWFkZXIgdG9rZW4AU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl91cmwASW52YWxpZCBjaGFyYWN0ZXJzIGluIHVybABVbmV4cGVjdGVkIHN0YXJ0IGNoYXIgaW4gdXJsAERvdWJsZSBAIGluIHVybABFbXB0eSBDb250ZW50LUxlbmd0aABJbnZhbGlkIGNoYXJhY3RlciBpbiBDb250ZW50LUxlbmd0aABEdXBsaWNhdGUgQ29udGVudC1MZW5ndGgASW52YWxpZCBjaGFyIGluIHVybCBwYXRoAENvbnRlbnQtTGVuZ3RoIGNhbid0IGJlIHByZXNlbnQgd2l0aCBUcmFuc2Zlci1FbmNvZGluZwBJbnZhbGlkIGNoYXJhY3RlciBpbiBjaHVuayBzaXplAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25faGVhZGVyX3ZhbHVlAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgdmFsdWUATWlzc2luZyBleHBlY3RlZCBMRiBhZnRlciBoZWFkZXIgdmFsdWUASW52YWxpZCBgVHJhbnNmZXItRW5jb2RpbmdgIGhlYWRlciB2YWx1ZQBJbnZhbGlkIGNoYXJhY3RlciBpbiBjaHVuayBleHRlbnNpb25zIHF1b3RlIHZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgcXVvdGVkIHZhbHVlAFBhdXNlZCBieSBvbl9oZWFkZXJzX2NvbXBsZXRlAEludmFsaWQgRU9GIHN0YXRlAG9uX3Jlc2V0IHBhdXNlAG9uX2NodW5rX2hlYWRlciBwYXVzZQBvbl9tZXNzYWdlX2JlZ2luIHBhdXNlAG9uX2NodW5rX2V4dGVuc2lvbl92YWx1ZSBwYXVzZQBvbl9zdGF0dXNfY29tcGxldGUgcGF1c2UAb25fdmVyc2lvbl9jb21wbGV0ZSBwYXVzZQBvbl91cmxfY29tcGxldGUgcGF1c2UAb25fY2h1bmtfY29tcGxldGUgcGF1c2UAb25faGVhZGVyX3ZhbHVlX2NvbXBsZXRlIHBhdXNlAG9uX21lc3NhZ2VfY29tcGxldGUgcGF1c2UAb25fbWV0aG9kX2NvbXBsZXRlIHBhdXNlAG9uX2hlYWRlcl9maWVsZF9jb21wbGV0ZSBwYXVzZQBvbl9jaHVua19leHRlbnNpb25fbmFtZSBwYXVzZQBVbmV4cGVjdGVkIHNwYWNlIGFmdGVyIHN0YXJ0IGxpbmUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9jaHVua19leHRlbnNpb25fbmFtZQBJbnZhbGlkIGNoYXJhY3RlciBpbiBjaHVuayBleHRlbnNpb25zIG5hbWUAUGF1c2Ugb24gQ09OTkVDVC9VcGdyYWRlAFBhdXNlIG9uIFBSSS9VcGdyYWRlAEV4cGVjdGVkIEhUVFAvMiBDb25uZWN0aW9uIFByZWZhY2UAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9tZXRob2QARXhwZWN0ZWQgc3BhY2UgYWZ0ZXIgbWV0aG9kAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25faGVhZGVyX2ZpZWxkAFBhdXNlZABJbnZhbGlkIHdvcmQgZW5jb3VudGVyZWQASW52YWxpZCBtZXRob2QgZW5jb3VudGVyZWQAVW5leHBlY3RlZCBjaGFyIGluIHVybCBzY2hlbWEAUmVxdWVzdCBoYXMgaW52YWxpZCBgVHJhbnNmZXItRW5jb2RpbmdgAFNXSVRDSF9QUk9YWQBVU0VfUFJPWFkATUtBQ1RJVklUWQBVTlBST0NFU1NBQkxFX0VOVElUWQBDT1BZAE1PVkVEX1BFUk1BTkVOVExZAFRPT19FQVJMWQBOT1RJRlkARkFJTEVEX0RFUEVOREVOQ1kAQkFEX0dBVEVXQVkAUExBWQBQVVQAQ0hFQ0tPVVQAR0FURVdBWV9USU1FT1VUAFJFUVVFU1RfVElNRU9VVABORVRXT1JLX0NPTk5FQ1RfVElNRU9VVABDT05ORUNUSU9OX1RJTUVPVVQATE9HSU5fVElNRU9VVABORVRXT1JLX1JFQURfVElNRU9VVABQT1NUAE1JU0RJUkVDVEVEX1JFUVVFU1QAQ0xJRU5UX0NMT1NFRF9SRVFVRVNUAENMSUVOVF9DTE9TRURfTE9BRF9CQUxBTkNFRF9SRVFVRVNUAEJBRF9SRVFVRVNUAEhUVFBfUkVRVUVTVF9TRU5UX1RPX0hUVFBTX1BPUlQAUkVQT1JUAElNX0FfVEVBUE9UAFJFU0VUX0NPTlRFTlQATk9fQ09OVEVOVABQQVJUSUFMX0NPTlRFTlQASFBFX0lOVkFMSURfQ09OU1RBTlQASFBFX0NCX1JFU0VUAEdFVABIUEVfU1RSSUNUAENPTkZMSUNUAFRFTVBPUkFSWV9SRURJUkVDVABQRVJNQU5FTlRfUkVESVJFQ1QAQ09OTkVDVABNVUxUSV9TVEFUVVMASFBFX0lOVkFMSURfU1RBVFVTAFRPT19NQU5ZX1JFUVVFU1RTAEVBUkxZX0hJTlRTAFVOQVZBSUxBQkxFX0ZPUl9MRUdBTF9SRUFTT05TAE9QVElPTlMAU1dJVENISU5HX1BST1RPQ09MUwBWQVJJQU5UX0FMU09fTkVHT1RJQVRFUwBNVUxUSVBMRV9DSE9JQ0VTAElOVEVSTkFMX1NFUlZFUl9FUlJPUgBXRUJfU0VSVkVSX1VOS05PV05fRVJST1IAUkFJTEdVTl9FUlJPUgBJREVOVElUWV9QUk9WSURFUl9BVVRIRU5USUNBVElPTl9FUlJPUgBTU0xfQ0VSVElGSUNBVEVfRVJST1IASU5WQUxJRF9YX0ZPUldBUkRFRF9GT1IAU0VUX1BBUkFNRVRFUgBHRVRfUEFSQU1FVEVSAEhQRV9VU0VSAFNFRV9PVEhFUgBIUEVfQ0JfQ0hVTktfSEVBREVSAE1LQ0FMRU5EQVIAU0VUVVAAV0VCX1NFUlZFUl9JU19ET1dOAFRFQVJET1dOAEhQRV9DTE9TRURfQ09OTkVDVElPTgBIRVVSSVNUSUNfRVhQSVJBVElPTgBESVNDT05ORUNURURfT1BFUkFUSU9OAE5PTl9BVVRIT1JJVEFUSVZFX0lORk9STUFUSU9OAEhQRV9JTlZBTElEX1ZFUlNJT04ASFBFX0NCX01FU1NBR0VfQkVHSU4AU0lURV9JU19GUk9aRU4ASFBFX0lOVkFMSURfSEVBREVSX1RPS0VOAElOVkFMSURfVE9LRU4ARk9SQklEREVOAEVOSEFOQ0VfWU9VUl9DQUxNAEhQRV9JTlZBTElEX1VSTABCTE9DS0VEX0JZX1BBUkVOVEFMX0NPTlRST0wATUtDT0wAQUNMAEhQRV9JTlRFUk5BTABSRVFVRVNUX0hFQURFUl9GSUVMRFNfVE9PX0xBUkdFX1VOT0ZGSUNJQUwASFBFX09LAFVOTElOSwBVTkxPQ0sAUFJJAFJFVFJZX1dJVEgASFBFX0lOVkFMSURfQ09OVEVOVF9MRU5HVEgASFBFX1VORVhQRUNURURfQ09OVEVOVF9MRU5HVEgARkxVU0gAUFJPUFBBVENIAE0tU0VBUkNIAFVSSV9UT09fTE9ORwBQUk9DRVNTSU5HAE1JU0NFTExBTkVPVVNfUEVSU0lTVEVOVF9XQVJOSU5HAE1JU0NFTExBTkVPVVNfV0FSTklORwBIUEVfSU5WQUxJRF9UUkFOU0ZFUl9FTkNPRElORwBFeHBlY3RlZCBDUkxGAEhQRV9JTlZBTElEX0NIVU5LX1NJWkUATU9WRQBDT05USU5VRQBIUEVfQ0JfU1RBVFVTX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJTX0NPTVBMRVRFAEhQRV9DQl9WRVJTSU9OX0NPTVBMRVRFAEhQRV9DQl9VUkxfQ09NUExFVEUASFBFX0NCX0NIVU5LX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJfVkFMVUVfQ09NUExFVEUASFBFX0NCX0NIVU5LX0VYVEVOU0lPTl9WQUxVRV9DT01QTEVURQBIUEVfQ0JfQ0hVTktfRVhURU5TSU9OX05BTUVfQ09NUExFVEUASFBFX0NCX01FU1NBR0VfQ09NUExFVEUASFBFX0NCX01FVEhPRF9DT01QTEVURQBIUEVfQ0JfSEVBREVSX0ZJRUxEX0NPTVBMRVRFAERFTEVURQBIUEVfSU5WQUxJRF9FT0ZfU1RBVEUASU5WQUxJRF9TU0xfQ0VSVElGSUNBVEUAUEFVU0UATk9fUkVTUE9OU0UAVU5TVVBQT1JURURfTUVESUFfVFlQRQBHT05FAE5PVF9BQ0NFUFRBQkxFAFNFUlZJQ0VfVU5BVkFJTEFCTEUAUkFOR0VfTk9UX1NBVElTRklBQkxFAE9SSUdJTl9JU19VTlJFQUNIQUJMRQBSRVNQT05TRV9JU19TVEFMRQBQVVJHRQBNRVJHRQBSRVFVRVNUX0hFQURFUl9GSUVMRFNfVE9PX0xBUkdFAFJFUVVFU1RfSEVBREVSX1RPT19MQVJHRQBQQVlMT0FEX1RPT19MQVJHRQBJTlNVRkZJQ0lFTlRfU1RPUkFHRQBIUEVfUEFVU0VEX1VQR1JBREUASFBFX1BBVVNFRF9IMl9VUEdSQURFAFNPVVJDRQBBTk5PVU5DRQBUUkFDRQBIUEVfVU5FWFBFQ1RFRF9TUEFDRQBERVNDUklCRQBVTlNVQlNDUklCRQBSRUNPUkQASFBFX0lOVkFMSURfTUVUSE9EAE5PVF9GT1VORABQUk9QRklORABVTkJJTkQAUkVCSU5EAFVOQVVUSE9SSVpFRABNRVRIT0RfTk9UX0FMTE9XRUQASFRUUF9WRVJTSU9OX05PVF9TVVBQT1JURUQAQUxSRUFEWV9SRVBPUlRFRABBQ0NFUFRFRABOT1RfSU1QTEVNRU5URUQATE9PUF9ERVRFQ1RFRABIUEVfQ1JfRVhQRUNURUQASFBFX0xGX0VYUEVDVEVEAENSRUFURUQASU1fVVNFRABIUEVfUEFVU0VEAFRJTUVPVVRfT0NDVVJFRABQQVlNRU5UX1JFUVVJUkVEAFBSRUNPTkRJVElPTl9SRVFVSVJFRABQUk9YWV9BVVRIRU5USUNBVElPTl9SRVFVSVJFRABORVRXT1JLX0FVVEhFTlRJQ0FUSU9OX1JFUVVJUkVEAExFTkdUSF9SRVFVSVJFRABTU0xfQ0VSVElGSUNBVEVfUkVRVUlSRUQAVVBHUkFERV9SRVFVSVJFRABQQUdFX0VYUElSRUQAUFJFQ09ORElUSU9OX0ZBSUxFRABFWFBFQ1RBVElPTl9GQUlMRUQAUkVWQUxJREFUSU9OX0ZBSUxFRABTU0xfSEFORFNIQUtFX0ZBSUxFRABMT0NLRUQAVFJBTlNGT1JNQVRJT05fQVBQTElFRABOT1RfTU9ESUZJRUQATk9UX0VYVEVOREVEAEJBTkRXSURUSF9MSU1JVF9FWENFRURFRABTSVRFX0lTX09WRVJMT0FERUQASEVBRABFeHBlY3RlZCBIVFRQLwAAXhMAACYTAAAwEAAA8BcAAJ0TAAAVEgAAORcAAPASAAAKEAAAdRIAAK0SAACCEwAATxQAAH8QAACgFQAAIxQAAIkSAACLFAAATRUAANQRAADPFAAAEBgAAMkWAADcFgAAwREAAOAXAAC7FAAAdBQAAHwVAADlFAAACBcAAB8QAABlFQAAoxQAACgVAAACFQAAmRUAACwQAACLGQAATw8AANQOAABqEAAAzhAAAAIXAACJDgAAbhMAABwTAABmFAAAVhcAAMETAADNEwAAbBMAAGgXAABmFwAAXxcAACITAADODwAAaQ4AANgOAABjFgAAyxMAAKoOAAAoFwAAJhcAAMUTAABdFgAA6BEAAGcTAABlEwAA8hYAAHMTAAAdFwAA+RYAAPMRAADPDgAAzhUAAAwSAACzEQAApREAAGEQAAAyFwAAuxMAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQIBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIDAgICAgIAAAICAAICAAICAgICAgICAgIABAAAAAAAAgICAgICAgICAgICAgICAgICAgICAgICAgIAAAACAgICAgICAgICAgICAgICAgICAgICAgICAgICAgACAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAICAgICAAACAgACAgACAgICAgICAgICAAMABAAAAAICAgICAgICAgICAgICAgICAgICAgICAgICAAAAAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAAgACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbG9zZWVlcC1hbGl2ZQAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQIBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBY2h1bmtlZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEAAQEBAQEAAAEBAAEBAAEBAQEBAQEBAQEAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABlY3Rpb25lbnQtbGVuZ3Rob25yb3h5LWNvbm5lY3Rpb24AAAAAAAAAAAAAAAAAAAByYW5zZmVyLWVuY29kaW5ncGdyYWRlDQoNCg0KU00NCg0KVFRQL0NFL1RTUC8AAAAAAAAAAAAAAAABAgABAwAAAAAAAAAAAAAAAAAAAAAAAAQBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAQIAAQMAAAAAAAAAAAAAAAAAAAAAAAAEAQEFAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAEAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAQAAAgAAAAAAAAAAAAAAAAAAAAAAAAMEAAAEBAQEBAQEBAQEBAUEBAQEBAQEBAQEBAQABAAGBwQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEAAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAEAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAABAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAIAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABOT1VOQ0VFQ0tPVVRORUNURVRFQ1JJQkVMVVNIRVRFQURTRUFSQ0hSR0VDVElWSVRZTEVOREFSVkVPVElGWVBUSU9OU0NIU0VBWVNUQVRDSEdFT1JESVJFQ1RPUlRSQ0hQQVJBTUVURVJVUkNFQlNDUklCRUFSRE9XTkFDRUlORE5LQ0tVQlNDUklCRUhUVFAvQURUUC8=' + // The url getter steps are to return this’s request’s URL, serialized. + return URLSerializer(this[kState].url) + } + // Returns a Headers object consisting of the headers associated with request. + // Note that headers added in the network layer by the user agent will not + // be accounted for in this object, e.g., the "Host" header. + get headers () { + webidl.brandCheck(this, Request) -/***/ }), + // The headers getter steps are to return this’s headers. + return this[kHeaders] + } -/***/ 3387: -/***/ ((module) => { + // Returns the kind of resource requested by request, e.g., "document" + // or "script". + get destination () { + webidl.brandCheck(this, Request) -module.exports = 'AGFzbQEAAAABMAhgAX8Bf2ADf39/AX9gBH9/f38Bf2AAAGADf39/AGABfwBgAn9/AGAGf39/f39/AALLAQgDZW52GHdhc21fb25faGVhZGVyc19jb21wbGV0ZQACA2VudhV3YXNtX29uX21lc3NhZ2VfYmVnaW4AAANlbnYLd2FzbV9vbl91cmwAAQNlbnYOd2FzbV9vbl9zdGF0dXMAAQNlbnYUd2FzbV9vbl9oZWFkZXJfZmllbGQAAQNlbnYUd2FzbV9vbl9oZWFkZXJfdmFsdWUAAQNlbnYMd2FzbV9vbl9ib2R5AAEDZW52GHdhc21fb25fbWVzc2FnZV9jb21wbGV0ZQAAA0ZFAwMEAAAFAAAAAAAABQEFAAUFBQAABgAAAAAGBgYGAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAAABAQcAAAUFAwABBAUBcAESEgUDAQACBggBfwFBgNQECwfRBSIGbWVtb3J5AgALX2luaXRpYWxpemUACRlfX2luZGlyZWN0X2Z1bmN0aW9uX3RhYmxlAQALbGxodHRwX2luaXQAChhsbGh0dHBfc2hvdWxkX2tlZXBfYWxpdmUAQQxsbGh0dHBfYWxsb2MADAZtYWxsb2MARgtsbGh0dHBfZnJlZQANBGZyZWUASA9sbGh0dHBfZ2V0X3R5cGUADhVsbGh0dHBfZ2V0X2h0dHBfbWFqb3IADxVsbGh0dHBfZ2V0X2h0dHBfbWlub3IAEBFsbGh0dHBfZ2V0X21ldGhvZAARFmxsaHR0cF9nZXRfc3RhdHVzX2NvZGUAEhJsbGh0dHBfZ2V0X3VwZ3JhZGUAEwxsbGh0dHBfcmVzZXQAFA5sbGh0dHBfZXhlY3V0ZQAVFGxsaHR0cF9zZXR0aW5nc19pbml0ABYNbGxodHRwX2ZpbmlzaAAXDGxsaHR0cF9wYXVzZQAYDWxsaHR0cF9yZXN1bWUAGRtsbGh0dHBfcmVzdW1lX2FmdGVyX3VwZ3JhZGUAGhBsbGh0dHBfZ2V0X2Vycm5vABsXbGxodHRwX2dldF9lcnJvcl9yZWFzb24AHBdsbGh0dHBfc2V0X2Vycm9yX3JlYXNvbgAdFGxsaHR0cF9nZXRfZXJyb3JfcG9zAB4RbGxodHRwX2Vycm5vX25hbWUAHxJsbGh0dHBfbWV0aG9kX25hbWUAIBJsbGh0dHBfc3RhdHVzX25hbWUAIRpsbGh0dHBfc2V0X2xlbmllbnRfaGVhZGVycwAiIWxsaHR0cF9zZXRfbGVuaWVudF9jaHVua2VkX2xlbmd0aAAjHWxsaHR0cF9zZXRfbGVuaWVudF9rZWVwX2FsaXZlACQkbGxodHRwX3NldF9sZW5pZW50X3RyYW5zZmVyX2VuY29kaW5nACUYbGxodHRwX21lc3NhZ2VfbmVlZHNfZW9mAD8JFwEAQQELEQECAwQFCwYHNTk3MS8tJyspCrLgAkUCAAsIABCIgICAAAsZACAAEMKAgIAAGiAAIAI2AjggACABOgAoCxwAIAAgAC8BMiAALQAuIAAQwYCAgAAQgICAgAALKgEBf0HAABDGgICAACIBEMKAgIAAGiABQYCIgIAANgI4IAEgADoAKCABCwoAIAAQyICAgAALBwAgAC0AKAsHACAALQAqCwcAIAAtACsLBwAgAC0AKQsHACAALwEyCwcAIAAtAC4LRQEEfyAAKAIYIQEgAC0ALSECIAAtACghAyAAKAI4IQQgABDCgICAABogACAENgI4IAAgAzoAKCAAIAI6AC0gACABNgIYCxEAIAAgASABIAJqEMOAgIAACxAAIABBAEHcABDMgICAABoLZwEBf0EAIQECQCAAKAIMDQACQAJAAkACQCAALQAvDgMBAAMCCyAAKAI4IgFFDQAgASgCLCIBRQ0AIAAgARGAgICAAAAiAQ0DC0EADwsQyoCAgAAACyAAQcOWgIAANgIQQQ4hAQsgAQseAAJAIAAoAgwNACAAQdGbgIAANgIQIABBFTYCDAsLFgACQCAAKAIMQRVHDQAgAEEANgIMCwsWAAJAIAAoAgxBFkcNACAAQQA2AgwLCwcAIAAoAgwLBwAgACgCEAsJACAAIAE2AhALBwAgACgCFAsiAAJAIABBJEkNABDKgICAAAALIABBAnRBoLOAgABqKAIACyIAAkAgAEEuSQ0AEMqAgIAAAAsgAEECdEGwtICAAGooAgAL7gsBAX9B66iAgAAhAQJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIABBnH9qDvQDY2IAAWFhYWFhYQIDBAVhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhBgcICQoLDA0OD2FhYWFhEGFhYWFhYWFhYWFhEWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYRITFBUWFxgZGhthYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhHB0eHyAhIiMkJSYnKCkqKywtLi8wMTIzNDU2YTc4OTphYWFhYWFhYTthYWE8YWFhYT0+P2FhYWFhYWFhQGFhQWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYUJDREVGR0hJSktMTU5PUFFSU2FhYWFhYWFhVFVWV1hZWlthXF1hYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFeYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhX2BhC0Hhp4CAAA8LQaShgIAADwtBy6yAgAAPC0H+sYCAAA8LQcCkgIAADwtBq6SAgAAPC0GNqICAAA8LQeKmgIAADwtBgLCAgAAPC0G5r4CAAA8LQdekgIAADwtB75+AgAAPC0Hhn4CAAA8LQfqfgIAADwtB8qCAgAAPC0Gor4CAAA8LQa6ygIAADwtBiLCAgAAPC0Hsp4CAAA8LQYKigIAADwtBjp2AgAAPC0HQroCAAA8LQcqjgIAADwtBxbKAgAAPC0HfnICAAA8LQdKcgIAADwtBxKCAgAAPC0HXoICAAA8LQaKfgIAADwtB7a6AgAAPC0GrsICAAA8LQdSlgIAADwtBzK6AgAAPC0H6roCAAA8LQfyrgIAADwtB0rCAgAAPC0HxnYCAAA8LQbuggIAADwtB96uAgAAPC0GQsYCAAA8LQdexgIAADwtBoq2AgAAPC0HUp4CAAA8LQeCrgIAADwtBn6yAgAAPC0HrsYCAAA8LQdWfgIAADwtByrGAgAAPC0HepYCAAA8LQdSegIAADwtB9JyAgAAPC0GnsoCAAA8LQbGdgIAADwtBoJ2AgAAPC0G5sYCAAA8LQbywgIAADwtBkqGAgAAPC0GzpoCAAA8LQemsgIAADwtBrJ6AgAAPC0HUq4CAAA8LQfemgIAADwtBgKaAgAAPC0GwoYCAAA8LQf6egIAADwtBjaOAgAAPC0GJrYCAAA8LQfeigIAADwtBoLGAgAAPC0Gun4CAAA8LQcalgIAADwtB6J6AgAAPC0GTooCAAA8LQcKvgIAADwtBw52AgAAPC0GLrICAAA8LQeGdgIAADwtBja+AgAAPC0HqoYCAAA8LQbStgIAADwtB0q+AgAAPC0HfsoCAAA8LQdKygIAADwtB8LCAgAAPC0GpooCAAA8LQfmjgIAADwtBmZ6AgAAPC0G1rICAAA8LQZuwgIAADwtBkrKAgAAPC0G2q4CAAA8LQcKigIAADwtB+LKAgAAPC0GepYCAAA8LQdCigIAADwtBup6AgAAPC0GBnoCAAA8LEMqAgIAAAAtB1qGAgAAhAQsgAQsWACAAIAAtAC1B/gFxIAFBAEdyOgAtCxkAIAAgAC0ALUH9AXEgAUEAR0EBdHI6AC0LGQAgACAALQAtQfsBcSABQQBHQQJ0cjoALQsZACAAIAAtAC1B9wFxIAFBAEdBA3RyOgAtCy4BAn9BACEDAkAgACgCOCIERQ0AIAQoAgAiBEUNACAAIAQRgICAgAAAIQMLIAMLSQECf0EAIQMCQCAAKAI4IgRFDQAgBCgCBCIERQ0AIAAgASACIAFrIAQRgYCAgAAAIgNBf0cNACAAQcaRgIAANgIQQRghAwsgAwsuAQJ/QQAhAwJAIAAoAjgiBEUNACAEKAIwIgRFDQAgACAEEYCAgIAAACEDCyADC0kBAn9BACEDAkAgACgCOCIERQ0AIAQoAggiBEUNACAAIAEgAiABayAEEYGAgIAAACIDQX9HDQAgAEH2ioCAADYCEEEYIQMLIAMLLgECf0EAIQMCQCAAKAI4IgRFDQAgBCgCNCIERQ0AIAAgBBGAgICAAAAhAwsgAwtJAQJ/QQAhAwJAIAAoAjgiBEUNACAEKAIMIgRFDQAgACABIAIgAWsgBBGBgICAAAAiA0F/Rw0AIABB7ZqAgAA2AhBBGCEDCyADCy4BAn9BACEDAkAgACgCOCIERQ0AIAQoAjgiBEUNACAAIAQRgICAgAAAIQMLIAMLSQECf0EAIQMCQCAAKAI4IgRFDQAgBCgCECIERQ0AIAAgASACIAFrIAQRgYCAgAAAIgNBf0cNACAAQZWQgIAANgIQQRghAwsgAwsuAQJ/QQAhAwJAIAAoAjgiBEUNACAEKAI8IgRFDQAgACAEEYCAgIAAACEDCyADC0kBAn9BACEDAkAgACgCOCIERQ0AIAQoAhQiBEUNACAAIAEgAiABayAEEYGAgIAAACIDQX9HDQAgAEGqm4CAADYCEEEYIQMLIAMLLgECf0EAIQMCQCAAKAI4IgRFDQAgBCgCQCIERQ0AIAAgBBGAgICAAAAhAwsgAwtJAQJ/QQAhAwJAIAAoAjgiBEUNACAEKAIYIgRFDQAgACABIAIgAWsgBBGBgICAAAAiA0F/Rw0AIABB7ZOAgAA2AhBBGCEDCyADCy4BAn9BACEDAkAgACgCOCIERQ0AIAQoAkQiBEUNACAAIAQRgICAgAAAIQMLIAMLLgECf0EAIQMCQCAAKAI4IgRFDQAgBCgCJCIERQ0AIAAgBBGAgICAAAAhAwsgAwsuAQJ/QQAhAwJAIAAoAjgiBEUNACAEKAIsIgRFDQAgACAEEYCAgIAAACEDCyADC0kBAn9BACEDAkAgACgCOCIERQ0AIAQoAigiBEUNACAAIAEgAiABayAEEYGAgIAAACIDQX9HDQAgAEH2iICAADYCEEEYIQMLIAMLLgECf0EAIQMCQCAAKAI4IgRFDQAgBCgCUCIERQ0AIAAgBBGAgICAAAAhAwsgAwtJAQJ/QQAhAwJAIAAoAjgiBEUNACAEKAIcIgRFDQAgACABIAIgAWsgBBGBgICAAAAiA0F/Rw0AIABBwpmAgAA2AhBBGCEDCyADCy4BAn9BACEDAkAgACgCOCIERQ0AIAQoAkgiBEUNACAAIAQRgICAgAAAIQMLIAMLSQECf0EAIQMCQCAAKAI4IgRFDQAgBCgCICIERQ0AIAAgASACIAFrIAQRgYCAgAAAIgNBf0cNACAAQZSUgIAANgIQQRghAwsgAwsuAQJ/QQAhAwJAIAAoAjgiBEUNACAEKAJMIgRFDQAgACAEEYCAgIAAACEDCyADCy4BAn9BACEDAkAgACgCOCIERQ0AIAQoAlQiBEUNACAAIAQRgICAgAAAIQMLIAMLLgECf0EAIQMCQCAAKAI4IgRFDQAgBCgCWCIERQ0AIAAgBBGAgICAAAAhAwsgAwtFAQF/AkACQCAALwEwQRRxQRRHDQBBASEDIAAtAChBAUYNASAALwEyQeUARiEDDAELIAAtAClBBUYhAwsgACADOgAuQQAL/gEBA39BASEDAkAgAC8BMCIEQQhxDQAgACkDIEIAUiEDCwJAAkAgAC0ALkUNAEEBIQUgAC0AKUEFRg0BQQEhBSAEQcAAcUUgA3FBAUcNAQtBACEFIARBwABxDQBBAiEFIARB//8DcSIDQQhxDQACQCADQYAEcUUNAAJAIAAtAChBAUcNACAALQAtQQpxDQBBBQ8LQQQPCwJAIANBIHENAAJAIAAtAChBAUYNACAALwEyQf//A3EiAEGcf2pB5ABJDQAgAEHMAUYNACAAQbACRg0AQQQhBSAEQShxRQ0CIANBiARxQYAERg0CC0EADwtBAEEDIAApAyBQGyEFCyAFC2IBAn9BACEBAkAgAC0AKEEBRg0AIAAvATJB//8DcSICQZx/akHkAEkNACACQcwBRg0AIAJBsAJGDQAgAC8BMCIAQcAAcQ0AQQEhASAAQYgEcUGABEYNACAAQShxRSEBCyABC6cBAQN/AkACQAJAIAAtACpFDQAgAC0AK0UNAEEAIQMgAC8BMCIEQQJxRQ0BDAILQQAhAyAALwEwIgRBAXFFDQELQQEhAyAALQAoQQFGDQAgAC8BMkH//wNxIgVBnH9qQeQASQ0AIAVBzAFGDQAgBUGwAkYNACAEQcAAcQ0AQQAhAyAEQYgEcUGABEYNACAEQShxQQBHIQMLIABBADsBMCAAQQA6AC8gAwuZAQECfwJAAkACQCAALQAqRQ0AIAAtACtFDQBBACEBIAAvATAiAkECcUUNAQwCC0EAIQEgAC8BMCICQQFxRQ0BC0EBIQEgAC0AKEEBRg0AIAAvATJB//8DcSIAQZx/akHkAEkNACAAQcwBRg0AIABBsAJGDQAgAkHAAHENAEEAIQEgAkGIBHFBgARGDQAgAkEocUEARyEBCyABC0kBAXsgAEEQav0MAAAAAAAAAAAAAAAAAAAAACIB/QsDACAAIAH9CwMAIABBMGogAf0LAwAgAEEgaiAB/QsDACAAQd0BNgIcQQALewEBfwJAIAAoAgwiAw0AAkAgACgCBEUNACAAIAE2AgQLAkAgACABIAIQxICAgAAiAw0AIAAoAgwPCyAAIAM2AhxBACEDIAAoAgQiAUUNACAAIAEgAiAAKAIIEYGAgIAAACIBRQ0AIAAgAjYCFCAAIAE2AgwgASEDCyADC+TzAQMOfwN+BH8jgICAgABBEGsiAySAgICAACABIQQgASEFIAEhBiABIQcgASEIIAEhCSABIQogASELIAEhDCABIQ0gASEOIAEhDwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCAAKAIcIhBBf2oO3QHaAQHZAQIDBAUGBwgJCgsMDQ7YAQ8Q1wEREtYBExQVFhcYGRob4AHfARwdHtUBHyAhIiMkJdQBJicoKSorLNMB0gEtLtEB0AEvMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUbbAUdISUrPAc4BS80BTMwBTU5PUFFSU1RVVldYWVpbXF1eX2BhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ent8fX5/gAGBAYIBgwGEAYUBhgGHAYgBiQGKAYsBjAGNAY4BjwGQAZEB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QAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIBAOxwEAAQID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YWNrIGVycm9yAGBvbl9jaHVua19leHRlbnNpb25fdmFsdWVgIGNhbGxiYWNrIGVycm9yAGBvbl9zdGF0dXNfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl92ZXJzaW9uX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fdXJsX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9oZWFkZXJfdmFsdWVfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9tZXNzYWdlX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fbWV0aG9kX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25faGVhZGVyX2ZpZWxkX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfZXh0ZW5zaW9uX25hbWVgIGNhbGxiYWNrIGVycm9yAFVuZXhwZWN0ZWQgY2hhciBpbiB1cmwgc2VydmVyAEludmFsaWQgaGVhZGVyIHZhbHVlIGNoYXIASW52YWxpZCBoZWFkZXIgZmllbGQgY2hhcgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3ZlcnNpb24ASW52YWxpZCBtaW5vciB2ZXJzaW9uAEludmFsaWQgbWFqb3IgdmVyc2lvbgBFeHBlY3RlZCBzcGFjZSBhZnRlciB2ZXJzaW9uAEV4cGVjdGVkIENSTEYgYWZ0ZXIgdmVyc2lvbgBJbnZhbGlkIEhUVFAgdmVyc2lvbgBJbnZhbGlkIGhlYWRlciB0b2tlbgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3VybABJbnZhbGlkIGNoYXJhY3RlcnMgaW4gdXJsAFVuZXhwZWN0ZWQgc3RhcnQgY2hhciBpbiB1cmwARG91YmxlIEAgaW4gdXJsAEVtcHR5IENvbnRlbnQtTGVuZ3RoAEludmFsaWQgY2hhcmFjdGVyIGluIENvbnRlbnQtTGVuZ3RoAER1cGxpY2F0ZSBDb250ZW50LUxlbmd0aABJbnZhbGlkIGNoYXIgaW4gdXJsIHBhdGgAQ29udGVudC1MZW5ndGggY2FuJ3QgYmUgcHJlc2VudCB3aXRoIFRyYW5zZmVyLUVuY29kaW5nAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIHNpemUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfdmFsdWUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9jaHVua19leHRlbnNpb25fdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyB2YWx1ZQBNaXNzaW5nIGV4cGVjdGVkIExGIGFmdGVyIGhlYWRlciB2YWx1ZQBJbnZhbGlkIGBUcmFuc2Zlci1FbmNvZGluZ2AgaGVhZGVyIHZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgcXVvdGUgdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyBxdW90ZWQgdmFsdWUAUGF1c2VkIGJ5IG9uX2hlYWRlcnNfY29tcGxldGUASW52YWxpZCBFT0Ygc3RhdGUAb25fcmVzZXQgcGF1c2UAb25fY2h1bmtfaGVhZGVyIHBhdXNlAG9uX21lc3NhZ2VfYmVnaW4gcGF1c2UAb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlIHBhdXNlAG9uX3N0YXR1c19jb21wbGV0ZSBwYXVzZQBvbl92ZXJzaW9uX2NvbXBsZXRlIHBhdXNlAG9uX3VybF9jb21wbGV0ZSBwYXVzZQBvbl9jaHVua19jb21wbGV0ZSBwYXVzZQBvbl9oZWFkZXJfdmFsdWVfY29tcGxldGUgcGF1c2UAb25fbWVzc2FnZV9jb21wbGV0ZSBwYXVzZQBvbl9tZXRob2RfY29tcGxldGUgcGF1c2UAb25faGVhZGVyX2ZpZWxkX2NvbXBsZXRlIHBhdXNlAG9uX2NodW5rX2V4dGVuc2lvbl9uYW1lIHBhdXNlAFVuZXhwZWN0ZWQgc3BhY2UgYWZ0ZXIgc3RhcnQgbGluZQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX2NodW5rX2V4dGVuc2lvbl9uYW1lAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgbmFtZQBQYXVzZSBvbiBDT05ORUNUL1VwZ3JhZGUAUGF1c2Ugb24gUFJJL1VwZ3JhZGUARXhwZWN0ZWQgSFRUUC8yIENvbm5lY3Rpb24gUHJlZmFjZQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX21ldGhvZABFeHBlY3RlZCBzcGFjZSBhZnRlciBtZXRob2QAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfZmllbGQAUGF1c2VkAEludmFsaWQgd29yZCBlbmNvdW50ZXJlZABJbnZhbGlkIG1ldGhvZCBlbmNvdW50ZXJlZABVbmV4cGVjdGVkIGNoYXIgaW4gdXJsIHNjaGVtYQBSZXF1ZXN0IGhhcyBpbnZhbGlkIGBUcmFuc2Zlci1FbmNvZGluZ2AAU1dJVENIX1BST1hZAFVTRV9QUk9YWQBNS0FDVElWSVRZAFVOUFJPQ0VTU0FCTEVfRU5USVRZAENPUFkATU9WRURfUEVSTUFORU5UTFkAVE9PX0VBUkxZAE5PVElGWQBGQUlMRURfREVQRU5ERU5DWQBCQURfR0FURVdBWQBQTEFZAFBVVABDSEVDS09VVABHQVRFV0FZX1RJTUVPVVQAUkVRVUVTVF9USU1FT1VUAE5FVFdPUktfQ09OTkVDVF9USU1FT1VUAENPTk5FQ1RJT05fVElNRU9VVABMT0dJTl9USU1FT1VUAE5FVFdPUktfUkVBRF9USU1FT1VUAFBPU1QATUlTRElSRUNURURfUkVRVUVTVABDTElFTlRfQ0xPU0VEX1JFUVVFU1QAQ0xJRU5UX0NMT1NFRF9MT0FEX0JBTEFOQ0VEX1JFUVVFU1QAQkFEX1JFUVVFU1QASFRUUF9SRVFVRVNUX1NFTlRfVE9fSFRUUFNfUE9SVABSRVBPUlQASU1fQV9URUFQT1QAUkVTRVRfQ09OVEVOVABOT19DT05URU5UAFBBUlRJQUxfQ09OVEVOVABIUEVfSU5WQUxJRF9DT05TVEFOVABIUEVfQ0JfUkVTRVQAR0VUAEhQRV9TVFJJQ1QAQ09ORkxJQ1QAVEVNUE9SQVJZX1JFRElSRUNUAFBFUk1BTkVOVF9SRURJUkVDVABDT05ORUNUAE1VTFRJX1NUQVRVUwBIUEVfSU5WQUxJRF9TVEFUVVMAVE9PX01BTllfUkVRVUVTVFMARUFSTFlfSElOVFMAVU5BVkFJTEFCTEVfRk9SX0xFR0FMX1JFQVNPTlMAT1BUSU9OUwBTV0lUQ0hJTkdfUFJPVE9DT0xTAFZBUklBTlRfQUxTT19ORUdPVElBVEVTAE1VTFRJUExFX0NIT0lDRVMASU5URVJOQUxfU0VSVkVSX0VSUk9SAFdFQl9TRVJWRVJfVU5LTk9XTl9FUlJPUgBSQUlMR1VOX0VSUk9SAElERU5USVRZX1BST1ZJREVSX0FVVEhFTlRJQ0FUSU9OX0VSUk9SAFNTTF9DRVJUSUZJQ0FURV9FUlJPUgBJTlZBTElEX1hfRk9SV0FSREVEX0ZPUgBTRVRfUEFSQU1FVEVSAEdFVF9QQVJBTUVURVIASFBFX1VTRVIAU0VFX09USEVSAEhQRV9DQl9DSFVOS19IRUFERVIATUtDQUxFTkRBUgBTRVRVUABXRUJfU0VSVkVSX0lTX0RPV04AVEVBUkRPV04ASFBFX0NMT1NFRF9DT05ORUNUSU9OAEhFVVJJU1RJQ19FWFBJUkFUSU9OAERJU0NPTk5FQ1RFRF9PUEVSQVRJT04ATk9OX0FVVEhPUklUQVRJVkVfSU5GT1JNQVRJT04ASFBFX0lOVkFMSURfVkVSU0lPTgBIUEVfQ0JfTUVTU0FHRV9CRUdJTgBTSVRFX0lTX0ZST1pFTgBIUEVfSU5WQUxJRF9IRUFERVJfVE9LRU4ASU5WQUxJRF9UT0tFTgBGT1JCSURERU4ARU5IQU5DRV9ZT1VSX0NBTE0ASFBFX0lOVkFMSURfVVJMAEJMT0NLRURfQllfUEFSRU5UQUxfQ09OVFJPTABNS0NPTABBQ0wASFBFX0lOVEVSTkFMAFJFUVVFU1RfSEVBREVSX0ZJRUxEU19UT09fTEFSR0VfVU5PRkZJQ0lBTABIUEVfT0sAVU5MSU5LAFVOTE9DSwBQUkkAUkVUUllfV0lUSABIUEVfSU5WQUxJRF9DT05URU5UX0xFTkdUSABIUEVfVU5FWFBFQ1RFRF9DT05URU5UX0xFTkdUSABGTFVTSABQUk9QUEFUQ0gATS1TRUFSQ0gAVVJJX1RPT19MT05HAFBST0NFU1NJTkcATUlTQ0VMTEFORU9VU19QRVJTSVNURU5UX1dBUk5JTkcATUlTQ0VMTEFORU9VU19XQVJOSU5HAEhQRV9JTlZBTElEX1RSQU5TRkVSX0VOQ09ESU5HAEV4cGVjdGVkIENSTEYASFBFX0lOVkFMSURfQ0hVTktfU0laRQBNT1ZFAENPTlRJTlVFAEhQRV9DQl9TVEFUVVNfQ09NUExFVEUASFBFX0NCX0hFQURFUlNfQ09NUExFVEUASFBFX0NCX1ZFUlNJT05fQ09NUExFVEUASFBFX0NCX1VSTF9DT01QTEVURQBIUEVfQ0JfQ0hVTktfQ09NUExFVEUASFBFX0NCX0hFQURFUl9WQUxVRV9DT01QTEVURQBIUEVfQ0JfQ0hVTktfRVhURU5TSU9OX1ZBTFVFX0NPTVBMRVRFAEhQRV9DQl9DSFVOS19FWFRFTlNJT05fTkFNRV9DT01QTEVURQBIUEVfQ0JfTUVTU0FHRV9DT01QTEVURQBIUEVfQ0JfTUVUSE9EX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJfRklFTERfQ09NUExFVEUAREVMRVRFAEhQRV9JTlZBTElEX0VPRl9TVEFURQBJTlZBTElEX1NTTF9DRVJUSUZJQ0FURQBQQVVTRQBOT19SRVNQT05TRQBVTlNVUFBPUlRFRF9NRURJQV9UWVBFAEdPTkUATk9UX0FDQ0VQVEFCTEUAU0VSVklDRV9VTkFWQUlMQUJMRQBSQU5HRV9OT1RfU0FUSVNGSUFCTEUAT1JJR0lOX0lTX1VOUkVBQ0hBQkxFAFJFU1BPTlNFX0lTX1NUQUxFAFBVUkdFAE1FUkdFAFJFUVVFU1RfSEVBREVSX0ZJRUxEU19UT09fTEFSR0UAUkVRVUVTVF9IRUFERVJfVE9PX0xBUkdFAFBBWUxPQURfVE9PX0xBUkdFAElOU1VGRklDSUVOVF9TVE9SQUdFAEhQRV9QQVVTRURfVVBHUkFERQBIUEVfUEFVU0VEX0gyX1VQR1JBREUAU09VUkNFAEFOTk9VTkNFAFRSQUNFAEhQRV9VTkVYUEVDVEVEX1NQQUNFAERFU0NSSUJFAFVOU1VCU0NSSUJFAFJFQ09SRABIUEVfSU5WQUxJRF9NRVRIT0QATk9UX0ZPVU5EAFBST1BGSU5EAFVOQklORABSRUJJTkQAVU5BVVRIT1JJWkVEAE1FVEhPRF9OT1RfQUxMT1dFRABIVFRQX1ZFUlNJT05fTk9UX1NVUFBPUlRFRABBTFJFQURZX1JFUE9SVEVEAEFDQ0VQVEVEAE5PVF9JTVBMRU1FTlRFRABMT09QX0RFVEVDVEVEAEhQRV9DUl9FWFBFQ1RFRABIUEVfTEZfRVhQRUNURUQAQ1JFQVRFRABJTV9VU0VEAEhQRV9QQVVTRUQAVElNRU9VVF9PQ0NVUkVEAFBBWU1FTlRfUkVRVUlSRUQAUFJFQ09ORElUSU9OX1JFUVVJUkVEAFBST1hZX0FVVEhFTlRJQ0FUSU9OX1JFUVVJUkVEAE5FVFdPUktfQVVUSEVOVElDQVRJT05fUkVRVUlSRUQATEVOR1RIX1JFUVVJUkVEAFNTTF9DRVJUSUZJQ0FURV9SRVFVSVJFRABVUEdSQURFX1JFUVVJUkVEAFBBR0VfRVhQSVJFRABQUkVDT05ESVRJT05fRkFJTEVEAEVYUEVDVEFUSU9OX0ZBSUxFRABSRVZBTElEQVRJT05fRkFJTEVEAFNTTF9IQU5EU0hBS0VfRkFJTEVEAExPQ0tFRABUUkFOU0ZPUk1BVElPTl9BUFBMSUVEAE5PVF9NT0RJRklFRABOT1RfRVhURU5ERUQAQkFORFdJRFRIX0xJTUlUX0VYQ0VFREVEAFNJVEVfSVNfT1ZFUkxPQURFRABIRUFEAEV4cGVjdGVkIEhUVFAvAABeEwAAJhMAADAQAADwFwAAnRMAABUSAAA5FwAA8BIAAAoQAAB1EgAArRIAAIITAABPFAAAfxAAAKAVAAAjFAAAiRIAAIsUAABNFQAA1BEAAM8UAAAQGAAAyRYAANwWAADBEQAA4BcAALsUAAB0FAAAfBUAAOUUAAAIFwAAHxAAAGUVAACjFAAAKBUAAAIVAACZFQAALBAAAIsZAABPDwAA1A4AAGoQAADOEAAAAhcAAIkOAABuEwAAHBMAAGYUAABWFwAAwRMAAM0TAABsEwAAaBcAAGYXAABfFwAAIhMAAM4PAABpDgAA2A4AAGMWAADLEwAAqg4AACgXAAAmFwAAxRMAAF0WAADoEQAAZxMAAGUTAADyFgAAcxMAAB0XAAD5FgAA8xEAAM8OAADOFQAADBIAALMRAAClEQAAYRAAADIXAAC7EwAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgMCAgICAgAAAgIAAgIAAgICAgICAgICAgAEAAAAAAACAgICAgICAgICAgICAgICAgICAgICAgICAgAAAAICAgICAgICAgICAgICAgICAgICAgICAgICAgICAAIAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAgICAgIAAAICAAICAAICAgICAgICAgIAAwAEAAAAAgICAgICAgICAgICAgICAgICAgICAgICAgIAAAACAgICAgICAgICAgICAgICAgICAgICAgICAgICAgACAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABsb3NlZWVwLWFsaXZlAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAgEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQFjaHVua2VkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQABAQEBAQAAAQEAAQEAAQEBAQEBAQEBAQAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGVjdGlvbmVudC1sZW5ndGhvbnJveHktY29ubmVjdGlvbgAAAAAAAAAAAAAAAAAAAHJhbnNmZXItZW5jb2RpbmdwZ3JhZGUNCg0KDQpTTQ0KDQpUVFAvQ0UvVFNQLwAAAAAAAAAAAAAAAAECAAEDAAAAAAAAAAAAAAAAAAAAAAAABAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAABAgABAwAAAAAAAAAAAAAAAAAAAAAAAAQBAQUBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAQAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAABAAACAAAAAAAAAAAAAAAAAAAAAAAAAwQAAAQEBAQEBAQEBAQEBQQEBAQEBAQEBAQEBAAEAAYHBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQABAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAQAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAEAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAgAAAAACAAAAAAAAAAAAAAAAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE5PVU5DRUVDS09VVE5FQ1RFVEVDUklCRUxVU0hFVEVBRFNFQVJDSFJHRUNUSVZJVFlMRU5EQVJWRU9USUZZUFRJT05TQ0hTRUFZU1RBVENIR0VPUkRJUkVDVE9SVFJDSFBBUkFNRVRFUlVSQ0VCU0NSSUJFQVJET1dOQUNFSU5ETktDS1VCU0NSSUJFSFRUUC9BRFRQLw==' + // The destination getter are to return this’s request’s destination. + return this[kState].destination + } + // Returns the referrer of request. Its value can be a same-origin URL if + // explicitly set in init, the empty string to indicate no referrer, and + // "about:client" when defaulting to the global’s default. This is used + // during fetching to determine the value of the `Referer` header of the + // request being made. + get referrer () { + webidl.brandCheck(this, Request) -/***/ }), + // 1. If this’s request’s referrer is "no-referrer", then return the + // empty string. + if (this[kState].referrer === 'no-referrer') { + return '' + } -/***/ 4383: -/***/ ((__unused_webpack_module, exports) => { + // 2. If this’s request’s referrer is "client", then return + // "about:client". + if (this[kState].referrer === 'client') { + return 'about:client' + } -"use strict"; + // Return this’s request’s referrer, serialized. + return this[kState].referrer.toString() + } -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.enumToMap = void 0; -function enumToMap(obj) { - const res = {}; - Object.keys(obj).forEach((key) => { - const value = obj[key]; - if (typeof value === 'number') { - res[key] = value; - } - }); - return res; -} -exports.enumToMap = enumToMap; -//# sourceMappingURL=utils.js.map + // Returns the referrer policy associated with request. + // This is used during fetching to compute the value of the request’s + // referrer. + get referrerPolicy () { + webidl.brandCheck(this, Request) -/***/ }), + // The referrerPolicy getter steps are to return this’s request’s referrer policy. + return this[kState].referrerPolicy + } -/***/ 2280: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // Returns the mode associated with request, which is a string indicating + // whether the request will use CORS, or will be restricted to same-origin + // URLs. + get mode () { + webidl.brandCheck(this, Request) -"use strict"; + // The mode getter steps are to return this’s request’s mode. + return this[kState].mode + } + // Returns the credentials mode associated with request, + // which is a string indicating whether credentials will be sent with the + // request always, never, or only when sent to a same-origin URL. + get credentials () { + // The credentials getter steps are to return this’s request’s credentials mode. + return this[kState].credentials + } -const { kClients } = __nccwpck_require__(1028) -const Agent = __nccwpck_require__(2308) -const { - kAgent, - kMockAgentSet, - kMockAgentGet, - kDispatches, - kIsMockActive, - kNetConnect, - kGetNetConnect, - kOptions, - kFactory -} = __nccwpck_require__(1820) -const MockClient = __nccwpck_require__(9518) -const MockPool = __nccwpck_require__(2947) -const { matchValue, buildMockOptions } = __nccwpck_require__(7056) -const { InvalidArgumentError, UndiciError } = __nccwpck_require__(6738) -const Dispatcher = __nccwpck_require__(8016) -const Pluralizer = __nccwpck_require__(32) -const PendingInterceptorsFormatter = __nccwpck_require__(4727) - -class FakeWeakRef { - constructor (value) { - this.value = value - } + // Returns the cache mode associated with request, + // which is a string indicating how the request will + // interact with the browser’s cache when fetching. + get cache () { + webidl.brandCheck(this, Request) - deref () { - return this.value + // The cache getter steps are to return this’s request’s cache mode. + return this[kState].cache } -} -class MockAgent extends Dispatcher { - constructor (opts) { - super(opts) + // Returns the redirect mode associated with request, + // which is a string indicating how redirects for the + // request will be handled during fetching. A request + // will follow redirects by default. + get redirect () { + webidl.brandCheck(this, Request) - this[kNetConnect] = true - this[kIsMockActive] = true + // The redirect getter steps are to return this’s request’s redirect mode. + return this[kState].redirect + } - // Instantiate Agent and encapsulate - if ((opts && opts.agent && typeof opts.agent.dispatch !== 'function')) { - throw new InvalidArgumentError('Argument opts.agent must implement Agent') - } - const agent = opts && opts.agent ? opts.agent : new Agent(opts) - this[kAgent] = agent + // Returns request’s subresource integrity metadata, which is a + // cryptographic hash of the resource being fetched. Its value + // consists of multiple hashes separated by whitespace. [SRI] + get integrity () { + webidl.brandCheck(this, Request) - this[kClients] = agent[kClients] - this[kOptions] = buildMockOptions(opts) + // The integrity getter steps are to return this’s request’s integrity + // metadata. + return this[kState].integrity } - get (origin) { - let dispatcher = this[kMockAgentGet](origin) + // Returns a boolean indicating whether or not request can outlive the + // global in which it was created. + get keepalive () { + webidl.brandCheck(this, Request) - if (!dispatcher) { - dispatcher = this[kFactory](origin) - this[kMockAgentSet](origin, dispatcher) - } - return dispatcher + // The keepalive getter steps are to return this’s request’s keepalive. + return this[kState].keepalive } - dispatch (opts, handler) { - // Call MockAgent.get to perform additional setup before dispatching as normal - this.get(opts.origin) - return this[kAgent].dispatch(opts, handler) - } + // Returns a boolean indicating whether or not request is for a reload + // navigation. + get isReloadNavigation () { + webidl.brandCheck(this, Request) - async close () { - await this[kAgent].close() - this[kClients].clear() + // The isReloadNavigation getter steps are to return true if this’s + // request’s reload-navigation flag is set; otherwise false. + return this[kState].reloadNavigation } - deactivate () { - this[kIsMockActive] = false - } + // Returns a boolean indicating whether or not request is for a history + // navigation (a.k.a. back-forward navigation). + get isHistoryNavigation () { + webidl.brandCheck(this, Request) - activate () { - this[kIsMockActive] = true + // The isHistoryNavigation getter steps are to return true if this’s request’s + // history-navigation flag is set; otherwise false. + return this[kState].historyNavigation } - enableNetConnect (matcher) { - if (typeof matcher === 'string' || typeof matcher === 'function' || matcher instanceof RegExp) { - if (Array.isArray(this[kNetConnect])) { - this[kNetConnect].push(matcher) - } else { - this[kNetConnect] = [matcher] - } - } else if (typeof matcher === 'undefined') { - this[kNetConnect] = true - } else { - throw new InvalidArgumentError('Unsupported matcher. Must be one of String|Function|RegExp.') - } - } + // Returns the signal associated with request, which is an AbortSignal + // object indicating whether or not request has been aborted, and its + // abort event handler. + get signal () { + webidl.brandCheck(this, Request) - disableNetConnect () { - this[kNetConnect] = false + // The signal getter steps are to return this’s signal. + return this[kSignal] } - // This is required to bypass issues caused by using global symbols - see: - // https://github.com/nodejs/undici/issues/1447 - get isMockActive () { - return this[kIsMockActive] + get body () { + webidl.brandCheck(this, Request) + + return this[kState].body ? this[kState].body.stream : null } - [kMockAgentSet] (origin, dispatcher) { - this[kClients].set(origin, new FakeWeakRef(dispatcher)) + get bodyUsed () { + webidl.brandCheck(this, Request) + + return !!this[kState].body && util.isDisturbed(this[kState].body.stream) } - [kFactory] (origin) { - const mockOptions = Object.assign({ agent: this }, this[kOptions]) - return this[kOptions] && this[kOptions].connections === 1 - ? new MockClient(origin, mockOptions) - : new MockPool(origin, mockOptions) + get duplex () { + webidl.brandCheck(this, Request) + + return 'half' } - [kMockAgentGet] (origin) { - // First check if we can immediately find it - const ref = this[kClients].get(origin) - if (ref) { - return ref.deref() - } + // Returns a clone of request. + clone () { + webidl.brandCheck(this, Request) - // If the origin is not a string create a dummy parent pool and return to user - if (typeof origin !== 'string') { - const dispatcher = this[kFactory]('http://localhost:9999') - this[kMockAgentSet](origin, dispatcher) - return dispatcher + // 1. If this is unusable, then throw a TypeError. + if (bodyUnusable(this)) { + throw new TypeError('unusable') } - // If we match, create a pool and assign the same dispatches - for (const [keyMatcher, nonExplicitRef] of Array.from(this[kClients])) { - const nonExplicitDispatcher = nonExplicitRef.deref() - if (nonExplicitDispatcher && typeof keyMatcher !== 'string' && matchValue(keyMatcher, origin)) { - const dispatcher = this[kFactory](origin) - this[kMockAgentSet](origin, dispatcher) - dispatcher[kDispatches] = nonExplicitDispatcher[kDispatches] - return dispatcher + // 2. Let clonedRequest be the result of cloning this’s request. + const clonedRequest = cloneRequest(this[kState]) + + // 3. Let clonedRequestObject be the result of creating a Request object, + // given clonedRequest, this’s headers’s guard, and this’s relevant Realm. + // 4. Make clonedRequestObject’s signal follow this’s signal. + const ac = new AbortController() + if (this.signal.aborted) { + ac.abort(this.signal.reason) + } else { + let list = dependentControllerMap.get(this.signal) + if (list === undefined) { + list = new Set() + dependentControllerMap.set(this.signal, list) } + const acRef = new WeakRef(ac) + list.add(acRef) + util.addAbortListener( + ac.signal, + buildAbort(acRef) + ) } - } - - [kGetNetConnect] () { - return this[kNetConnect] - } - - pendingInterceptors () { - const mockAgentClients = this[kClients] - return Array.from(mockAgentClients.entries()) - .flatMap(([origin, scope]) => scope.deref()[kDispatches].map(dispatch => ({ ...dispatch, origin }))) - .filter(({ pending }) => pending) + // 4. Return clonedRequestObject. + return fromInnerRequest(clonedRequest, ac.signal, getHeadersGuard(this[kHeaders])) } - assertNoPendingInterceptors ({ pendingInterceptorsFormatter = new PendingInterceptorsFormatter() } = {}) { - const pending = this.pendingInterceptors() - - if (pending.length === 0) { - return + [nodeUtil.inspect.custom] (depth, options) { + if (options.depth === null) { + options.depth = 2 } - const pluralizer = new Pluralizer('interceptor', 'interceptors').pluralize(pending.length) + options.colors ??= true - throw new UndiciError(` -${pluralizer.count} ${pluralizer.noun} ${pluralizer.is} pending: + const properties = { + method: this.method, + url: this.url, + headers: this.headers, + destination: this.destination, + referrer: this.referrer, + referrerPolicy: this.referrerPolicy, + mode: this.mode, + credentials: this.credentials, + cache: this.cache, + redirect: this.redirect, + integrity: this.integrity, + keepalive: this.keepalive, + isReloadNavigation: this.isReloadNavigation, + isHistoryNavigation: this.isHistoryNavigation, + signal: this.signal + } -${pendingInterceptorsFormatter.format(pending)} -`.trim()) + return `Request ${nodeUtil.formatWithOptions(options, properties)}` } } -module.exports = MockAgent - +mixinBody(Request) -/***/ }), +// https://fetch.spec.whatwg.org/#requests +function makeRequest (init) { + return { + method: init.method ?? 'GET', + localURLsOnly: init.localURLsOnly ?? false, + unsafeRequest: init.unsafeRequest ?? false, + body: init.body ?? null, + client: init.client ?? null, + reservedClient: init.reservedClient ?? null, + replacesClientId: init.replacesClientId ?? '', + window: init.window ?? 'client', + keepalive: init.keepalive ?? false, + serviceWorkers: init.serviceWorkers ?? 'all', + initiator: init.initiator ?? '', + destination: init.destination ?? '', + priority: init.priority ?? null, + origin: init.origin ?? 'client', + policyContainer: init.policyContainer ?? 'client', + referrer: init.referrer ?? 'client', + referrerPolicy: init.referrerPolicy ?? '', + mode: init.mode ?? 'no-cors', + useCORSPreflightFlag: init.useCORSPreflightFlag ?? false, + credentials: init.credentials ?? 'same-origin', + useCredentials: init.useCredentials ?? false, + cache: init.cache ?? 'default', + redirect: init.redirect ?? 'follow', + integrity: init.integrity ?? '', + cryptoGraphicsNonceMetadata: init.cryptoGraphicsNonceMetadata ?? '', + parserMetadata: init.parserMetadata ?? '', + reloadNavigation: init.reloadNavigation ?? false, + historyNavigation: init.historyNavigation ?? false, + userActivation: init.userActivation ?? false, + taintedOrigin: init.taintedOrigin ?? false, + redirectCount: init.redirectCount ?? 0, + responseTainting: init.responseTainting ?? 'basic', + preventNoCacheCacheControlHeaderModification: init.preventNoCacheCacheControlHeaderModification ?? false, + done: init.done ?? false, + timingAllowFailed: init.timingAllowFailed ?? false, + urlList: init.urlList, + url: init.urlList[0], + headersList: init.headersList + ? new HeadersList(init.headersList) + : new HeadersList() + } +} -/***/ 9518: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +// https://fetch.spec.whatwg.org/#concept-request-clone +function cloneRequest (request) { + // To clone a request request, run these steps: -"use strict"; + // 1. Let newRequest be a copy of request, except for its body. + const newRequest = makeRequest({ ...request, body: null }) + // 2. If request’s body is non-null, set newRequest’s body to the + // result of cloning request’s body. + if (request.body != null) { + newRequest.body = cloneBody(newRequest, request.body) + } -const { promisify } = __nccwpck_require__(9023) -const Client = __nccwpck_require__(6466) -const { buildMockDispatch } = __nccwpck_require__(7056) -const { - kDispatches, - kMockAgent, - kClose, - kOriginalClose, - kOrigin, - kOriginalDispatch, - kConnected -} = __nccwpck_require__(1820) -const { MockInterceptor } = __nccwpck_require__(8450) -const Symbols = __nccwpck_require__(1028) -const { InvalidArgumentError } = __nccwpck_require__(6738) + // 3. Return newRequest. + return newRequest +} /** - * MockClient provides an API that extends the Client to influence the mockDispatches. + * @see https://fetch.spec.whatwg.org/#request-create + * @param {any} innerRequest + * @param {AbortSignal} signal + * @param {'request' | 'immutable' | 'request-no-cors' | 'response' | 'none'} guard + * @returns {Request} */ -class MockClient extends Client { - constructor (origin, opts) { - super(origin, opts) +function fromInnerRequest (innerRequest, signal, guard) { + const request = new Request(kConstruct) + request[kState] = innerRequest + request[kSignal] = signal + request[kHeaders] = new Headers(kConstruct) + setHeadersList(request[kHeaders], innerRequest.headersList) + setHeadersGuard(request[kHeaders], guard) + return request +} - if (!opts || !opts.agent || typeof opts.agent.dispatch !== 'function') { - throw new InvalidArgumentError('Argument opts.agent must implement Agent') - } +Object.defineProperties(Request.prototype, { + method: kEnumerableProperty, + url: kEnumerableProperty, + headers: kEnumerableProperty, + redirect: kEnumerableProperty, + clone: kEnumerableProperty, + signal: kEnumerableProperty, + duplex: kEnumerableProperty, + destination: kEnumerableProperty, + body: kEnumerableProperty, + bodyUsed: kEnumerableProperty, + isHistoryNavigation: kEnumerableProperty, + isReloadNavigation: kEnumerableProperty, + keepalive: kEnumerableProperty, + integrity: kEnumerableProperty, + cache: kEnumerableProperty, + credentials: kEnumerableProperty, + attribute: kEnumerableProperty, + referrerPolicy: kEnumerableProperty, + referrer: kEnumerableProperty, + mode: kEnumerableProperty, + [Symbol.toStringTag]: { + value: 'Request', + configurable: true + } +}) - this[kMockAgent] = opts.agent - this[kOrigin] = origin - this[kDispatches] = [] - this[kConnected] = 1 - this[kOriginalDispatch] = this.dispatch - this[kOriginalClose] = this.close.bind(this) +webidl.converters.Request = webidl.interfaceConverter( + Request +) - this.dispatch = buildMockDispatch.call(this) - this.close = this[kClose] +// https://fetch.spec.whatwg.org/#requestinfo +webidl.converters.RequestInfo = function (V, prefix, argument) { + if (typeof V === 'string') { + return webidl.converters.USVString(V, prefix, argument) } - get [Symbols.kConnected] () { - return this[kConnected] + if (V instanceof Request) { + return webidl.converters.Request(V, prefix, argument) } - /** - * Sets up the base interceptor for mocking replies from undici. - */ - intercept (opts) { - return new MockInterceptor(opts, this[kDispatches]) - } + return webidl.converters.USVString(V, prefix, argument) +} - async [kClose] () { - await promisify(this[kOriginalClose])() - this[kConnected] = 0 - this[kMockAgent][Symbols.kClients].delete(this[kOrigin]) +webidl.converters.AbortSignal = webidl.interfaceConverter( + AbortSignal +) + +// https://fetch.spec.whatwg.org/#requestinit +webidl.converters.RequestInit = webidl.dictionaryConverter([ + { + key: 'method', + converter: webidl.converters.ByteString + }, + { + key: 'headers', + converter: webidl.converters.HeadersInit + }, + { + key: 'body', + converter: webidl.nullableConverter( + webidl.converters.BodyInit + ) + }, + { + key: 'referrer', + converter: webidl.converters.USVString + }, + { + key: 'referrerPolicy', + converter: webidl.converters.DOMString, + // https://w3c.github.io/webappsec-referrer-policy/#referrer-policy + allowedValues: referrerPolicy + }, + { + key: 'mode', + converter: webidl.converters.DOMString, + // https://fetch.spec.whatwg.org/#concept-request-mode + allowedValues: requestMode + }, + { + key: 'credentials', + converter: webidl.converters.DOMString, + // https://fetch.spec.whatwg.org/#requestcredentials + allowedValues: requestCredentials + }, + { + key: 'cache', + converter: webidl.converters.DOMString, + // https://fetch.spec.whatwg.org/#requestcache + allowedValues: requestCache + }, + { + key: 'redirect', + converter: webidl.converters.DOMString, + // https://fetch.spec.whatwg.org/#requestredirect + allowedValues: requestRedirect + }, + { + key: 'integrity', + converter: webidl.converters.DOMString + }, + { + key: 'keepalive', + converter: webidl.converters.boolean + }, + { + key: 'signal', + converter: webidl.nullableConverter( + (signal) => webidl.converters.AbortSignal( + signal, + 'RequestInit', + 'signal', + { strict: false } + ) + ) + }, + { + key: 'window', + converter: webidl.converters.any + }, + { + key: 'duplex', + converter: webidl.converters.DOMString, + allowedValues: requestDuplex + }, + { + key: 'dispatcher', // undici specific option + converter: webidl.converters.any } -} +]) -module.exports = MockClient +module.exports = { Request, makeRequest, fromInnerRequest, cloneRequest } /***/ }), -/***/ 3866: +/***/ 4317: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -const { UndiciError } = __nccwpck_require__(6738) +const { Headers, HeadersList, fill, getHeadersGuard, setHeadersGuard, setHeadersList } = __nccwpck_require__(217) +const { extractBody, cloneBody, mixinBody, hasFinalizationRegistry, streamRegistry, bodyUnusable } = __nccwpck_require__(8106) +const util = __nccwpck_require__(7234) +const nodeUtil = __nccwpck_require__(7975) +const { kEnumerableProperty } = util +const { + isValidReasonPhrase, + isCancelled, + isAborted, + isBlobLike, + serializeJavascriptValueToJSONString, + isErrorLike, + isomorphicEncode, + environmentSettingsObject: relevantRealm +} = __nccwpck_require__(1046) +const { + redirectStatusSet, + nullBodyStatus +} = __nccwpck_require__(6169) +const { kState, kHeaders } = __nccwpck_require__(1445) +const { webidl } = __nccwpck_require__(4859) +const { FormData } = __nccwpck_require__(9411) +const { URLSerializer } = __nccwpck_require__(6406) +const { kConstruct } = __nccwpck_require__(7417) +const assert = __nccwpck_require__(4589) +const { types } = __nccwpck_require__(7975) + +const textEncoder = new TextEncoder('utf-8') + +// https://fetch.spec.whatwg.org/#response-class +class Response { + // Creates network error Response. + static error () { + // The static error() method steps are to return the result of creating a + // Response object, given a new network error, "immutable", and this’s + // relevant Realm. + const responseObject = fromInnerResponse(makeNetworkError(), 'immutable') -class MockNotMatchedError extends UndiciError { - constructor (message) { - super(message) - Error.captureStackTrace(this, MockNotMatchedError) - this.name = 'MockNotMatchedError' - this.message = message || 'The request does not match any registered mock dispatches' - this.code = 'UND_MOCK_ERR_MOCK_NOT_MATCHED' + return responseObject } -} -module.exports = { - MockNotMatchedError -} + // https://fetch.spec.whatwg.org/#dom-response-json + static json (data, init = {}) { + webidl.argumentLengthCheck(arguments, 1, 'Response.json') + if (init !== null) { + init = webidl.converters.ResponseInit(init) + } -/***/ }), + // 1. Let bytes the result of running serialize a JavaScript value to JSON bytes on data. + const bytes = textEncoder.encode( + serializeJavascriptValueToJSONString(data) + ) -/***/ 8450: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // 2. Let body be the result of extracting bytes. + const body = extractBody(bytes) -"use strict"; + // 3. Let responseObject be the result of creating a Response object, given a new response, + // "response", and this’s relevant Realm. + const responseObject = fromInnerResponse(makeResponse({}), 'response') + // 4. Perform initialize a response given responseObject, init, and (body, "application/json"). + initializeResponse(responseObject, init, { body: body[0], type: 'application/json' }) -const { getResponseData, buildKey, addMockDispatch } = __nccwpck_require__(7056) -const { - kDispatches, - kDispatchKey, - kDefaultHeaders, - kDefaultTrailers, - kContentLength, - kMockDispatch -} = __nccwpck_require__(1820) -const { InvalidArgumentError } = __nccwpck_require__(6738) -const { buildURL } = __nccwpck_require__(5069) + // 5. Return responseObject. + return responseObject + } -/** - * Defines the scope API for an interceptor reply - */ -class MockScope { - constructor (mockDispatch) { - this[kMockDispatch] = mockDispatch - } - - /** - * Delay a reply by a set amount in ms. - */ - delay (waitInMs) { - if (typeof waitInMs !== 'number' || !Number.isInteger(waitInMs) || waitInMs <= 0) { - throw new InvalidArgumentError('waitInMs must be a valid integer > 0') - } + // Creates a redirect Response that redirects to url with status status. + static redirect (url, status = 302) { + webidl.argumentLengthCheck(arguments, 1, 'Response.redirect') - this[kMockDispatch].delay = waitInMs - return this - } + url = webidl.converters.USVString(url) + status = webidl.converters['unsigned short'](status) - /** - * For a defined reply, never mark as consumed. - */ - persist () { - this[kMockDispatch].persist = true - return this - } + // 1. Let parsedURL be the result of parsing url with current settings + // object’s API base URL. + // 2. If parsedURL is failure, then throw a TypeError. + // TODO: base-URL? + let parsedURL + try { + parsedURL = new URL(url, relevantRealm.settingsObject.baseUrl) + } catch (err) { + throw new TypeError(`Failed to parse URL from ${url}`, { cause: err }) + } - /** - * Allow one to define a reply for a set amount of matching requests. - */ - times (repeatTimes) { - if (typeof repeatTimes !== 'number' || !Number.isInteger(repeatTimes) || repeatTimes <= 0) { - throw new InvalidArgumentError('repeatTimes must be a valid integer > 0') + // 3. If status is not a redirect status, then throw a RangeError. + if (!redirectStatusSet.has(status)) { + throw new RangeError(`Invalid status code ${status}`) } - this[kMockDispatch].times = repeatTimes - return this - } -} + // 4. Let responseObject be the result of creating a Response object, + // given a new response, "immutable", and this’s relevant Realm. + const responseObject = fromInnerResponse(makeResponse({}), 'immutable') -/** - * Defines an interceptor for a Mock - */ -class MockInterceptor { - constructor (opts, mockDispatches) { - if (typeof opts !== 'object') { - throw new InvalidArgumentError('opts must be an object') - } - if (typeof opts.path === 'undefined') { - throw new InvalidArgumentError('opts.path must be defined') - } - if (typeof opts.method === 'undefined') { - opts.method = 'GET' - } - // See https://github.com/nodejs/undici/issues/1245 - // As per RFC 3986, clients are not supposed to send URI - // fragments to servers when they retrieve a document, - if (typeof opts.path === 'string') { - if (opts.query) { - opts.path = buildURL(opts.path, opts.query) - } else { - // Matches https://github.com/nodejs/undici/blob/main/lib/fetch/index.js#L1811 - const parsedURL = new URL(opts.path, 'data://') - opts.path = parsedURL.pathname + parsedURL.search - } - } - if (typeof opts.method === 'string') { - opts.method = opts.method.toUpperCase() - } + // 5. Set responseObject’s response’s status to status. + responseObject[kState].status = status - this[kDispatchKey] = buildKey(opts) - this[kDispatches] = mockDispatches - this[kDefaultHeaders] = {} - this[kDefaultTrailers] = {} - this[kContentLength] = false - } + // 6. Let value be parsedURL, serialized and isomorphic encoded. + const value = isomorphicEncode(URLSerializer(parsedURL)) - createMockScopeDispatchData (statusCode, data, responseOptions = {}) { - const responseData = getResponseData(data) - const contentLength = this[kContentLength] ? { 'content-length': responseData.length } : {} - const headers = { ...this[kDefaultHeaders], ...contentLength, ...responseOptions.headers } - const trailers = { ...this[kDefaultTrailers], ...responseOptions.trailers } + // 7. Append `Location`/value to responseObject’s response’s header list. + responseObject[kState].headersList.append('location', value, true) - return { statusCode, data, headers, trailers } + // 8. Return responseObject. + return responseObject } - validateReplyParameters (statusCode, data, responseOptions) { - if (typeof statusCode === 'undefined') { - throw new InvalidArgumentError('statusCode must be defined') - } - if (typeof data === 'undefined') { - throw new InvalidArgumentError('data must be defined') - } - if (typeof responseOptions !== 'object') { - throw new InvalidArgumentError('responseOptions must be an object') + // https://fetch.spec.whatwg.org/#dom-response + constructor (body = null, init = {}) { + webidl.util.markAsUncloneable(this) + if (body === kConstruct) { + return } - } - - /** - * Mock an undici request with a defined reply. - */ - reply (replyData) { - // Values of reply aren't available right now as they - // can only be available when the reply callback is invoked. - if (typeof replyData === 'function') { - // We'll first wrap the provided callback in another function, - // this function will properly resolve the data from the callback - // when invoked. - const wrappedDefaultsCallback = (opts) => { - // Our reply options callback contains the parameter for statusCode, data and options. - const resolvedData = replyData(opts) - - // Check if it is in the right format - if (typeof resolvedData !== 'object') { - throw new InvalidArgumentError('reply options callback must return an object') - } - - const { statusCode, data = '', responseOptions = {} } = resolvedData - this.validateReplyParameters(statusCode, data, responseOptions) - // Since the values can be obtained immediately we return them - // from this higher order function that will be resolved later. - return { - ...this.createMockScopeDispatchData(statusCode, data, responseOptions) - } - } - // Add usual dispatch data, but this time set the data parameter to function that will eventually provide data. - const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], wrappedDefaultsCallback) - return new MockScope(newMockDispatch) + if (body !== null) { + body = webidl.converters.BodyInit(body) } - // We can have either one or three parameters, if we get here, - // we should have 1-3 parameters. So we spread the arguments of - // this function to obtain the parameters, since replyData will always - // just be the statusCode. - const [statusCode, data = '', responseOptions = {}] = [...arguments] - this.validateReplyParameters(statusCode, data, responseOptions) + init = webidl.converters.ResponseInit(init) - // Send in-already provided data like usual - const dispatchData = this.createMockScopeDispatchData(statusCode, data, responseOptions) - const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], dispatchData) - return new MockScope(newMockDispatch) - } + // 1. Set this’s response to a new response. + this[kState] = makeResponse({}) - /** - * Mock an undici request with a defined error. - */ - replyWithError (error) { - if (typeof error === 'undefined') { - throw new InvalidArgumentError('error must be defined') - } + // 2. Set this’s headers to a new Headers object with this’s relevant + // Realm, whose header list is this’s response’s header list and guard + // is "response". + this[kHeaders] = new Headers(kConstruct) + setHeadersGuard(this[kHeaders], 'response') + setHeadersList(this[kHeaders], this[kState].headersList) - const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], { error }) - return new MockScope(newMockDispatch) - } + // 3. Let bodyWithType be null. + let bodyWithType = null - /** - * Set default reply headers on the interceptor for subsequent replies - */ - defaultReplyHeaders (headers) { - if (typeof headers === 'undefined') { - throw new InvalidArgumentError('headers must be defined') + // 4. If body is non-null, then set bodyWithType to the result of extracting body. + if (body != null) { + const [extractedBody, type] = extractBody(body) + bodyWithType = { body: extractedBody, type } } - this[kDefaultHeaders] = headers - return this + // 5. Perform initialize a response given this, init, and bodyWithType. + initializeResponse(this, init, bodyWithType) } - /** - * Set default reply trailers on the interceptor for subsequent replies - */ - defaultReplyTrailers (trailers) { - if (typeof trailers === 'undefined') { - throw new InvalidArgumentError('trailers must be defined') - } - - this[kDefaultTrailers] = trailers - return this - } + // Returns response’s type, e.g., "cors". + get type () { + webidl.brandCheck(this, Response) - /** - * Set reply content length header for replies on the interceptor - */ - replyContentLength () { - this[kContentLength] = true - return this + // The type getter steps are to return this’s response’s type. + return this[kState].type } -} - -module.exports.MockInterceptor = MockInterceptor -module.exports.MockScope = MockScope - - -/***/ }), - -/***/ 2947: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -"use strict"; + // Returns response’s URL, if it has one; otherwise the empty string. + get url () { + webidl.brandCheck(this, Response) -const { promisify } = __nccwpck_require__(9023) -const Pool = __nccwpck_require__(7279) -const { buildMockDispatch } = __nccwpck_require__(7056) -const { - kDispatches, - kMockAgent, - kClose, - kOriginalClose, - kOrigin, - kOriginalDispatch, - kConnected -} = __nccwpck_require__(1820) -const { MockInterceptor } = __nccwpck_require__(8450) -const Symbols = __nccwpck_require__(1028) -const { InvalidArgumentError } = __nccwpck_require__(6738) + const urlList = this[kState].urlList -/** - * MockPool provides an API that extends the Pool to influence the mockDispatches. - */ -class MockPool extends Pool { - constructor (origin, opts) { - super(origin, opts) + // The url getter steps are to return the empty string if this’s + // response’s URL is null; otherwise this’s response’s URL, + // serialized with exclude fragment set to true. + const url = urlList[urlList.length - 1] ?? null - if (!opts || !opts.agent || typeof opts.agent.dispatch !== 'function') { - throw new InvalidArgumentError('Argument opts.agent must implement Agent') + if (url === null) { + return '' } - this[kMockAgent] = opts.agent - this[kOrigin] = origin - this[kDispatches] = [] - this[kConnected] = 1 - this[kOriginalDispatch] = this.dispatch - this[kOriginalClose] = this.close.bind(this) - - this.dispatch = buildMockDispatch.call(this) - this.close = this[kClose] + return URLSerializer(url, true) } - get [Symbols.kConnected] () { - return this[kConnected] + // Returns whether response was obtained through a redirect. + get redirected () { + webidl.brandCheck(this, Response) + + // The redirected getter steps are to return true if this’s response’s URL + // list has more than one item; otherwise false. + return this[kState].urlList.length > 1 } - /** - * Sets up the base interceptor for mocking replies from undici. - */ - intercept (opts) { - return new MockInterceptor(opts, this[kDispatches]) + // Returns response’s status. + get status () { + webidl.brandCheck(this, Response) + + // The status getter steps are to return this’s response’s status. + return this[kState].status } - async [kClose] () { - await promisify(this[kOriginalClose])() - this[kConnected] = 0 - this[kMockAgent][Symbols.kClients].delete(this[kOrigin]) + // Returns whether response’s status is an ok status. + get ok () { + webidl.brandCheck(this, Response) + + // The ok getter steps are to return true if this’s response’s status is an + // ok status; otherwise false. + return this[kState].status >= 200 && this[kState].status <= 299 } -} -module.exports = MockPool + // Returns response’s status message. + get statusText () { + webidl.brandCheck(this, Response) + // The statusText getter steps are to return this’s response’s status + // message. + return this[kState].statusText + } -/***/ }), + // Returns response’s headers as Headers. + get headers () { + webidl.brandCheck(this, Response) -/***/ 1820: -/***/ ((module) => { + // The headers getter steps are to return this’s headers. + return this[kHeaders] + } -"use strict"; + get body () { + webidl.brandCheck(this, Response) + return this[kState].body ? this[kState].body.stream : null + } -module.exports = { - kAgent: Symbol('agent'), - kOptions: Symbol('options'), - kFactory: Symbol('factory'), - kDispatches: Symbol('dispatches'), - kDispatchKey: Symbol('dispatch key'), - kDefaultHeaders: Symbol('default headers'), - kDefaultTrailers: Symbol('default trailers'), - kContentLength: Symbol('content length'), - kMockAgent: Symbol('mock agent'), - kMockAgentSet: Symbol('mock agent set'), - kMockAgentGet: Symbol('mock agent get'), - kMockDispatch: Symbol('mock dispatch'), - kClose: Symbol('close'), - kOriginalClose: Symbol('original agent close'), - kOrigin: Symbol('origin'), - kIsMockActive: Symbol('is mock active'), - kNetConnect: Symbol('net connect'), - kGetNetConnect: Symbol('get net connect'), - kConnected: Symbol('connected') -} + get bodyUsed () { + webidl.brandCheck(this, Response) + return !!this[kState].body && util.isDisturbed(this[kState].body.stream) + } -/***/ }), + // Returns a clone of response. + clone () { + webidl.brandCheck(this, Response) -/***/ 7056: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // 1. If this is unusable, then throw a TypeError. + if (bodyUnusable(this)) { + throw webidl.errors.exception({ + header: 'Response.clone', + message: 'Body has already been consumed.' + }) + } -"use strict"; + // 2. Let clonedResponse be the result of cloning this’s response. + const clonedResponse = cloneResponse(this[kState]) + // Note: To re-register because of a new stream. + if (hasFinalizationRegistry && this[kState].body?.stream) { + streamRegistry.register(this, new WeakRef(this[kState].body.stream)) + } -const { MockNotMatchedError } = __nccwpck_require__(3866) -const { - kDispatches, - kMockAgent, - kOriginalDispatch, - kOrigin, - kGetNetConnect -} = __nccwpck_require__(1820) -const { buildURL, nop } = __nccwpck_require__(5069) -const { STATUS_CODES } = __nccwpck_require__(8611) -const { - types: { - isPromise + // 3. Return the result of creating a Response object, given + // clonedResponse, this’s headers’s guard, and this’s relevant Realm. + return fromInnerResponse(clonedResponse, getHeadersGuard(this[kHeaders])) } -} = __nccwpck_require__(9023) -function matchValue (match, value) { - if (typeof match === 'string') { - return match === value - } - if (match instanceof RegExp) { - return match.test(value) - } - if (typeof match === 'function') { - return match(value) === true - } - return false -} + [nodeUtil.inspect.custom] (depth, options) { + if (options.depth === null) { + options.depth = 2 + } -function lowerCaseEntries (headers) { - return Object.fromEntries( - Object.entries(headers).map(([headerName, headerValue]) => { - return [headerName.toLocaleLowerCase(), headerValue] - }) - ) -} + options.colors ??= true -/** - * @param {import('../../index').Headers|string[]|Record} headers - * @param {string} key - */ -function getHeaderByName (headers, key) { - if (Array.isArray(headers)) { - for (let i = 0; i < headers.length; i += 2) { - if (headers[i].toLocaleLowerCase() === key.toLocaleLowerCase()) { - return headers[i + 1] - } + const properties = { + status: this.status, + statusText: this.statusText, + headers: this.headers, + body: this.body, + bodyUsed: this.bodyUsed, + ok: this.ok, + redirected: this.redirected, + type: this.type, + url: this.url } - return undefined - } else if (typeof headers.get === 'function') { - return headers.get(key) - } else { - return lowerCaseEntries(headers)[key.toLocaleLowerCase()] + return `Response ${nodeUtil.formatWithOptions(options, properties)}` } } -/** @param {string[]} headers */ -function buildHeadersFromArray (headers) { // fetch HeadersList - const clone = headers.slice() - const entries = [] - for (let index = 0; index < clone.length; index += 2) { - entries.push([clone[index], clone[index + 1]]) - } - return Object.fromEntries(entries) -} +mixinBody(Response) -function matchHeaders (mockDispatch, headers) { - if (typeof mockDispatch.headers === 'function') { - if (Array.isArray(headers)) { // fetch HeadersList - headers = buildHeadersFromArray(headers) - } - return mockDispatch.headers(headers ? lowerCaseEntries(headers) : {}) - } - if (typeof mockDispatch.headers === 'undefined') { - return true - } - if (typeof headers !== 'object' || typeof mockDispatch.headers !== 'object') { - return false +Object.defineProperties(Response.prototype, { + type: kEnumerableProperty, + url: kEnumerableProperty, + status: kEnumerableProperty, + ok: kEnumerableProperty, + redirected: kEnumerableProperty, + statusText: kEnumerableProperty, + headers: kEnumerableProperty, + clone: kEnumerableProperty, + body: kEnumerableProperty, + bodyUsed: kEnumerableProperty, + [Symbol.toStringTag]: { + value: 'Response', + configurable: true } +}) - for (const [matchHeaderName, matchHeaderValue] of Object.entries(mockDispatch.headers)) { - const headerValue = getHeaderByName(headers, matchHeaderName) +Object.defineProperties(Response, { + json: kEnumerableProperty, + redirect: kEnumerableProperty, + error: kEnumerableProperty +}) - if (!matchValue(matchHeaderValue, headerValue)) { - return false - } - } - return true -} +// https://fetch.spec.whatwg.org/#concept-response-clone +function cloneResponse (response) { + // To clone a response response, run these steps: -function safeUrl (path) { - if (typeof path !== 'string') { - return path + // 1. If response is a filtered response, then return a new identical + // filtered response whose internal response is a clone of response’s + // internal response. + if (response.internalResponse) { + return filterResponse( + cloneResponse(response.internalResponse), + response.type + ) } - const pathSegments = path.split('?') + // 2. Let newResponse be a copy of response, except for its body. + const newResponse = makeResponse({ ...response, body: null }) - if (pathSegments.length !== 2) { - return path + // 3. If response’s body is non-null, then set newResponse’s body to the + // result of cloning response’s body. + if (response.body != null) { + newResponse.body = cloneBody(newResponse, response.body) } - const qp = new URLSearchParams(pathSegments.pop()) - qp.sort() - return [...pathSegments, qp.toString()].join('?') -} - -function matchKey (mockDispatch, { path, method, body, headers }) { - const pathMatch = matchValue(mockDispatch.path, path) - const methodMatch = matchValue(mockDispatch.method, method) - const bodyMatch = typeof mockDispatch.body !== 'undefined' ? matchValue(mockDispatch.body, body) : true - const headersMatch = matchHeaders(mockDispatch, headers) - return pathMatch && methodMatch && bodyMatch && headersMatch + // 4. Return newResponse. + return newResponse } -function getResponseData (data) { - if (Buffer.isBuffer(data)) { - return data - } else if (typeof data === 'object') { - return JSON.stringify(data) - } else { - return data.toString() +function makeResponse (init) { + return { + aborted: false, + rangeRequested: false, + timingAllowPassed: false, + requestIncludesCredentials: false, + type: 'default', + status: 200, + timingInfo: null, + cacheState: '', + statusText: '', + ...init, + headersList: init?.headersList + ? new HeadersList(init?.headersList) + : new HeadersList(), + urlList: init?.urlList ? [...init.urlList] : [] } } -function getMockDispatch (mockDispatches, key) { - const basePath = key.query ? buildURL(key.path, key.query) : key.path - const resolvedPath = typeof basePath === 'string' ? safeUrl(basePath) : basePath - - // Match path - let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path }) => matchValue(safeUrl(path), resolvedPath)) - if (matchedMockDispatches.length === 0) { - throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`) - } +function makeNetworkError (reason) { + const isError = isErrorLike(reason) + return makeResponse({ + type: 'error', + status: 0, + error: isError + ? reason + : new Error(reason ? String(reason) : reason), + aborted: reason && reason.name === 'AbortError' + }) +} - // Match method - matchedMockDispatches = matchedMockDispatches.filter(({ method }) => matchValue(method, key.method)) - if (matchedMockDispatches.length === 0) { - throw new MockNotMatchedError(`Mock dispatch not matched for method '${key.method}'`) - } +// @see https://fetch.spec.whatwg.org/#concept-network-error +function isNetworkError (response) { + return ( + // A network error is a response whose type is "error", + response.type === 'error' && + // status is 0 + response.status === 0 + ) +} - // Match body - matchedMockDispatches = matchedMockDispatches.filter(({ body }) => typeof body !== 'undefined' ? matchValue(body, key.body) : true) - if (matchedMockDispatches.length === 0) { - throw new MockNotMatchedError(`Mock dispatch not matched for body '${key.body}'`) +function makeFilteredResponse (response, state) { + state = { + internalResponse: response, + ...state } - // Match headers - matchedMockDispatches = matchedMockDispatches.filter((mockDispatch) => matchHeaders(mockDispatch, key.headers)) - if (matchedMockDispatches.length === 0) { - throw new MockNotMatchedError(`Mock dispatch not matched for headers '${typeof key.headers === 'object' ? JSON.stringify(key.headers) : key.headers}'`) - } + return new Proxy(response, { + get (target, p) { + return p in state ? state[p] : target[p] + }, + set (target, p, value) { + assert(!(p in state)) + target[p] = value + return true + } + }) +} - return matchedMockDispatches[0] +// https://fetch.spec.whatwg.org/#concept-filtered-response +function filterResponse (response, type) { + // Set response to the following filtered response with response as its + // internal response, depending on request’s response tainting: + if (type === 'basic') { + // A basic filtered response is a filtered response whose type is "basic" + // and header list excludes any headers in internal response’s header list + // whose name is a forbidden response-header name. + + // Note: undici does not implement forbidden response-header names + return makeFilteredResponse(response, { + type: 'basic', + headersList: response.headersList + }) + } else if (type === 'cors') { + // A CORS filtered response is a filtered response whose type is "cors" + // and header list excludes any headers in internal response’s header + // list whose name is not a CORS-safelisted response-header name, given + // internal response’s CORS-exposed header-name list. + + // Note: undici does not implement CORS-safelisted response-header names + return makeFilteredResponse(response, { + type: 'cors', + headersList: response.headersList + }) + } else if (type === 'opaque') { + // An opaque filtered response is a filtered response whose type is + // "opaque", URL list is the empty list, status is 0, status message + // is the empty byte sequence, header list is empty, and body is null. + + return makeFilteredResponse(response, { + type: 'opaque', + urlList: Object.freeze([]), + status: 0, + statusText: '', + body: null + }) + } else if (type === 'opaqueredirect') { + // An opaque-redirect filtered response is a filtered response whose type + // is "opaqueredirect", status is 0, status message is the empty byte + // sequence, header list is empty, and body is null. + + return makeFilteredResponse(response, { + type: 'opaqueredirect', + status: 0, + statusText: '', + headersList: [], + body: null + }) + } else { + assert(false) + } } -function addMockDispatch (mockDispatches, key, data) { - const baseData = { timesInvoked: 0, times: 1, persist: false, consumed: false } - const replyData = typeof data === 'function' ? { callback: data } : { ...data } - const newMockDispatch = { ...baseData, ...key, pending: true, data: { error: null, ...replyData } } - mockDispatches.push(newMockDispatch) - return newMockDispatch +// https://fetch.spec.whatwg.org/#appropriate-network-error +function makeAppropriateNetworkError (fetchParams, err = null) { + // 1. Assert: fetchParams is canceled. + assert(isCancelled(fetchParams)) + + // 2. Return an aborted network error if fetchParams is aborted; + // otherwise return a network error. + return isAborted(fetchParams) + ? makeNetworkError(Object.assign(new DOMException('The operation was aborted.', 'AbortError'), { cause: err })) + : makeNetworkError(Object.assign(new DOMException('Request was cancelled.'), { cause: err })) } -function deleteMockDispatch (mockDispatches, key) { - const index = mockDispatches.findIndex(dispatch => { - if (!dispatch.consumed) { - return false +// https://whatpr.org/fetch/1392.html#initialize-a-response +function initializeResponse (response, init, body) { + // 1. If init["status"] is not in the range 200 to 599, inclusive, then + // throw a RangeError. + if (init.status !== null && (init.status < 200 || init.status > 599)) { + throw new RangeError('init["status"] must be in the range of 200 to 599, inclusive.') + } + + // 2. If init["statusText"] does not match the reason-phrase token production, + // then throw a TypeError. + if ('statusText' in init && init.statusText != null) { + // See, https://datatracker.ietf.org/doc/html/rfc7230#section-3.1.2: + // reason-phrase = *( HTAB / SP / VCHAR / obs-text ) + if (!isValidReasonPhrase(String(init.statusText))) { + throw new TypeError('Invalid statusText') } - return matchKey(dispatch, key) - }) - if (index !== -1) { - mockDispatches.splice(index, 1) } -} -function buildKey (opts) { - const { path, method, body, headers, query } = opts - return { - path, - method, - body, - headers, - query + // 3. Set response’s response’s status to init["status"]. + if ('status' in init && init.status != null) { + response[kState].status = init.status } -} -function generateKeyValues (data) { - return Object.entries(data).reduce((keyValuePairs, [key, value]) => [ - ...keyValuePairs, - Buffer.from(`${key}`), - Array.isArray(value) ? value.map(x => Buffer.from(`${x}`)) : Buffer.from(`${value}`) - ], []) -} + // 4. Set response’s response’s status message to init["statusText"]. + if ('statusText' in init && init.statusText != null) { + response[kState].statusText = init.statusText + } -/** - * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Status - * @param {number} statusCode - */ -function getStatusText (statusCode) { - return STATUS_CODES[statusCode] || 'unknown' -} + // 5. If init["headers"] exists, then fill response’s headers with init["headers"]. + if ('headers' in init && init.headers != null) { + fill(response[kHeaders], init.headers) + } -async function getResponse (body) { - const buffers = [] - for await (const data of body) { - buffers.push(data) + // 6. If body was given, then: + if (body) { + // 1. If response's status is a null body status, then throw a TypeError. + if (nullBodyStatus.includes(response.status)) { + throw webidl.errors.exception({ + header: 'Response constructor', + message: `Invalid response status code ${response.status}` + }) + } + + // 2. Set response's body to body's body. + response[kState].body = body.body + + // 3. If body's type is non-null and response's header list does not contain + // `Content-Type`, then append (`Content-Type`, body's type) to response's header list. + if (body.type != null && !response[kState].headersList.contains('content-type', true)) { + response[kState].headersList.append('content-type', body.type, true) + } } - return Buffer.concat(buffers).toString('utf8') } /** - * Mock dispatch function used to simulate undici dispatches + * @see https://fetch.spec.whatwg.org/#response-create + * @param {any} innerResponse + * @param {'request' | 'immutable' | 'request-no-cors' | 'response' | 'none'} guard + * @returns {Response} */ -function mockDispatch (opts, handler) { - // Get mock dispatch from built key - const key = buildKey(opts) - const mockDispatch = getMockDispatch(this[kDispatches], key) - - mockDispatch.timesInvoked++ +function fromInnerResponse (innerResponse, guard) { + const response = new Response(kConstruct) + response[kState] = innerResponse + response[kHeaders] = new Headers(kConstruct) + setHeadersList(response[kHeaders], innerResponse.headersList) + setHeadersGuard(response[kHeaders], guard) - // Here's where we resolve a callback if a callback is present for the dispatch data. - if (mockDispatch.data.callback) { - mockDispatch.data = { ...mockDispatch.data, ...mockDispatch.data.callback(opts) } + if (hasFinalizationRegistry && innerResponse.body?.stream) { + // If the target (response) is reclaimed, the cleanup callback may be called at some point with + // the held value provided for it (innerResponse.body.stream). The held value can be any value: + // a primitive or an object, even undefined. If the held value is an object, the registry keeps + // a strong reference to it (so it can pass it to the cleanup callback later). Reworded from + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/FinalizationRegistry + streamRegistry.register(response, new WeakRef(innerResponse.body.stream)) } - // Parse mockDispatch data - const { data: { statusCode, data, headers, trailers, error }, delay, persist } = mockDispatch - const { timesInvoked, times } = mockDispatch + return response +} - // If it's used up and not persistent, mark as consumed - mockDispatch.consumed = !persist && timesInvoked >= times - mockDispatch.pending = timesInvoked < times +webidl.converters.ReadableStream = webidl.interfaceConverter( + ReadableStream +) - // If specified, trigger dispatch error - if (error !== null) { - deleteMockDispatch(this[kDispatches], key) - handler.onError(error) - return true - } +webidl.converters.FormData = webidl.interfaceConverter( + FormData +) - // Handle the request with a delay if necessary - if (typeof delay === 'number' && delay > 0) { - setTimeout(() => { - handleReply(this[kDispatches]) - }, delay) - } else { - handleReply(this[kDispatches]) - } +webidl.converters.URLSearchParams = webidl.interfaceConverter( + URLSearchParams +) - function handleReply (mockDispatches, _data = data) { - // fetch's HeadersList is a 1D string array - const optsHeaders = Array.isArray(opts.headers) - ? buildHeadersFromArray(opts.headers) - : opts.headers - const body = typeof _data === 'function' - ? _data({ ...opts, headers: optsHeaders }) - : _data +// https://fetch.spec.whatwg.org/#typedefdef-xmlhttprequestbodyinit +webidl.converters.XMLHttpRequestBodyInit = function (V, prefix, name) { + if (typeof V === 'string') { + return webidl.converters.USVString(V, prefix, name) + } - // util.types.isPromise is likely needed for jest. - if (isPromise(body)) { - // If handleReply is asynchronous, throwing an error - // in the callback will reject the promise, rather than - // synchronously throw the error, which breaks some tests. - // Rather, we wait for the callback to resolve if it is a - // promise, and then re-run handleReply with the new body. - body.then((newData) => handleReply(mockDispatches, newData)) - return - } + if (isBlobLike(V)) { + return webidl.converters.Blob(V, prefix, name, { strict: false }) + } - const responseData = getResponseData(body) - const responseHeaders = generateKeyValues(headers) - const responseTrailers = generateKeyValues(trailers) + if (ArrayBuffer.isView(V) || types.isArrayBuffer(V)) { + return webidl.converters.BufferSource(V, prefix, name) + } - handler.abort = nop - handler.onHeaders(statusCode, responseHeaders, resume, getStatusText(statusCode)) - handler.onData(Buffer.from(responseData)) - handler.onComplete(responseTrailers) - deleteMockDispatch(mockDispatches, key) + if (util.isFormDataLike(V)) { + return webidl.converters.FormData(V, prefix, name, { strict: false }) } - function resume () {} + if (V instanceof URLSearchParams) { + return webidl.converters.URLSearchParams(V, prefix, name) + } - return true + return webidl.converters.DOMString(V, prefix, name) } -function buildMockDispatch () { - const agent = this[kMockAgent] - const origin = this[kOrigin] - const originalDispatch = this[kOriginalDispatch] - - return function dispatch (opts, handler) { - if (agent.isMockActive) { - try { - mockDispatch.call(this, opts, handler) - } catch (error) { - if (error instanceof MockNotMatchedError) { - const netConnect = agent[kGetNetConnect]() - if (netConnect === false) { - throw new MockNotMatchedError(`${error.message}: subsequent request to origin ${origin} was not allowed (net.connect disabled)`) - } - if (checkNetConnect(netConnect, origin)) { - originalDispatch.call(this, opts, handler) - } else { - throw new MockNotMatchedError(`${error.message}: subsequent request to origin ${origin} was not allowed (net.connect is not enabled for this origin)`) - } - } else { - throw error - } - } - } else { - originalDispatch.call(this, opts, handler) - } +// https://fetch.spec.whatwg.org/#bodyinit +webidl.converters.BodyInit = function (V, prefix, argument) { + if (V instanceof ReadableStream) { + return webidl.converters.ReadableStream(V, prefix, argument) } -} -function checkNetConnect (netConnect, origin) { - const url = new URL(origin) - if (netConnect === true) { - return true - } else if (Array.isArray(netConnect) && netConnect.some((matcher) => matchValue(matcher, url.host))) { - return true + // Note: the spec doesn't include async iterables, + // this is an undici extension. + if (V?.[Symbol.asyncIterator]) { + return V } - return false + + return webidl.converters.XMLHttpRequestBodyInit(V, prefix, argument) } -function buildMockOptions (opts) { - if (opts) { - const { agent, ...mockOptions } = opts - return mockOptions +webidl.converters.ResponseInit = webidl.dictionaryConverter([ + { + key: 'status', + converter: webidl.converters['unsigned short'], + defaultValue: () => 200 + }, + { + key: 'statusText', + converter: webidl.converters.ByteString, + defaultValue: () => '' + }, + { + key: 'headers', + converter: webidl.converters.HeadersInit } -} +]) module.exports = { - getResponseData, - getMockDispatch, - addMockDispatch, - deleteMockDispatch, - buildKey, - generateKeyValues, - matchValue, - getResponse, - getStatusText, - mockDispatch, - buildMockDispatch, - checkNetConnect, - buildMockOptions, - getHeaderByName + isNetworkError, + makeNetworkError, + makeResponse, + makeAppropriateNetworkError, + filterResponse, + Response, + cloneResponse, + fromInnerResponse } /***/ }), -/***/ 4727: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -"use strict"; +/***/ 1445: +/***/ ((module) => { -const { Transform } = __nccwpck_require__(2203) -const { Console } = __nccwpck_require__(4236) -/** - * Gets the output of `console.table(…)` as a string. - */ -module.exports = class PendingInterceptorsFormatter { - constructor ({ disableColors } = {}) { - this.transform = new Transform({ - transform (chunk, _enc, cb) { - cb(null, chunk) - } - }) +module.exports = { + kUrl: Symbol('url'), + kHeaders: Symbol('headers'), + kSignal: Symbol('signal'), + kState: Symbol('state'), + kDispatcher: Symbol('dispatcher') +} - this.logger = new Console({ - stdout: this.transform, - inspectOptions: { - colors: !disableColors && !process.env.CI - } - }) - } - format (pendingInterceptors) { - const withPrettyHeaders = pendingInterceptors.map( - ({ method, path, data: { statusCode }, persist, times, timesInvoked, origin }) => ({ - Method: method, - Origin: origin, - Path: path, - 'Status code': statusCode, - Persistent: persist ? '✅' : '❌', - Invocations: timesInvoked, - Remaining: persist ? Infinity : times - timesInvoked - })) +/***/ }), - this.logger.table(withPrettyHeaders) - return this.transform.read().toString() - } -} +/***/ 1046: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -/***/ }), -/***/ 32: -/***/ ((module) => { +const { Transform } = __nccwpck_require__(7075) +const zlib = __nccwpck_require__(8522) +const { redirectStatusSet, referrerPolicySet: referrerPolicyTokens, badPortsSet } = __nccwpck_require__(6169) +const { getGlobalOrigin } = __nccwpck_require__(7786) +const { collectASequenceOfCodePoints, collectAnHTTPQuotedString, removeChars, parseMIMEType } = __nccwpck_require__(6406) +const { performance } = __nccwpck_require__(643) +const { isBlobLike, ReadableStreamFrom, isValidHTTPToken, normalizedMethodRecordsBase } = __nccwpck_require__(7234) +const assert = __nccwpck_require__(4589) +const { isUint8Array } = __nccwpck_require__(3429) +const { webidl } = __nccwpck_require__(4859) -"use strict"; +let supportedHashes = [] +// https://nodejs.org/api/crypto.html#determining-if-crypto-support-is-unavailable +/** @type {import('crypto')} */ +let crypto +try { + crypto = __nccwpck_require__(7598) + const possibleRelevantHashes = ['sha256', 'sha384', 'sha512'] + supportedHashes = crypto.getHashes().filter((hash) => possibleRelevantHashes.includes(hash)) +/* c8 ignore next 3 */ +} catch { -const singulars = { - pronoun: 'it', - is: 'is', - was: 'was', - this: 'this' } -const plurals = { - pronoun: 'they', - is: 'are', - was: 'were', - this: 'these' +function responseURL (response) { + // https://fetch.spec.whatwg.org/#responses + // A response has an associated URL. It is a pointer to the last URL + // in response’s URL list and null if response’s URL list is empty. + const urlList = response.urlList + const length = urlList.length + return length === 0 ? null : urlList[length - 1].toString() } -module.exports = class Pluralizer { - constructor (singular, plural) { - this.singular = singular - this.plural = plural +// https://fetch.spec.whatwg.org/#concept-response-location-url +function responseLocationURL (response, requestFragment) { + // 1. If response’s status is not a redirect status, then return null. + if (!redirectStatusSet.has(response.status)) { + return null } - pluralize (count) { - const one = count === 1 - const keys = one ? singulars : plurals - const noun = one ? this.singular : this.plural - return { ...keys, count, noun } + // 2. Let location be the result of extracting header list values given + // `Location` and response’s header list. + let location = response.headersList.get('location', true) + + // 3. If location is a header value, then set location to the result of + // parsing location with response’s URL. + if (location !== null && isValidHeaderValue(location)) { + if (!isValidEncodedURL(location)) { + // Some websites respond location header in UTF-8 form without encoding them as ASCII + // and major browsers redirect them to correctly UTF-8 encoded addresses. + // Here, we handle that behavior in the same way. + location = normalizeBinaryStringToUtf8(location) + } + location = new URL(location, responseURL(response)) } -} + // 4. If location is a URL whose fragment is null, then set location’s + // fragment to requestFragment. + if (location && !location.hash) { + location.hash = requestFragment + } -/***/ }), + // 5. Return location. + return location +} -/***/ 8666: -/***/ ((module) => { +/** + * @see https://www.rfc-editor.org/rfc/rfc1738#section-2.2 + * @param {string} url + * @returns {boolean} + */ +function isValidEncodedURL (url) { + for (let i = 0; i < url.length; ++i) { + const code = url.charCodeAt(i) -"use strict"; -/* eslint-disable */ + if ( + code > 0x7E || // Non-US-ASCII + DEL + code < 0x20 // Control characters NUL - US + ) { + return false + } + } + return true +} +/** + * If string contains non-ASCII characters, assumes it's UTF-8 encoded and decodes it. + * Since UTF-8 is a superset of ASCII, this will work for ASCII strings as well. + * @param {string} value + * @returns {string} + */ +function normalizeBinaryStringToUtf8 (value) { + return Buffer.from(value, 'binary').toString('utf8') +} +/** @returns {URL} */ +function requestCurrentURL (request) { + return request.urlList[request.urlList.length - 1] +} -// Extracted from node/lib/internal/fixed_queue.js - -// Currently optimal queue size, tested on V8 6.0 - 6.6. Must be power of two. -const kSize = 2048; -const kMask = kSize - 1; - -// The FixedQueue is implemented as a singly-linked list of fixed-size -// circular buffers. It looks something like this: -// -// head tail -// | | -// v v -// +-----------+ <-----\ +-----------+ <------\ +-----------+ -// | [null] | \----- | next | \------- | next | -// +-----------+ +-----------+ +-----------+ -// | item | <-- bottom | item | <-- bottom | [empty] | -// | item | | item | | [empty] | -// | item | | item | | [empty] | -// | item | | item | | [empty] | -// | item | | item | bottom --> | item | -// | item | | item | | item | -// | ... | | ... | | ... | -// | item | | item | | item | -// | item | | item | | item | -// | [empty] | <-- top | item | | item | -// | [empty] | | item | | item | -// | [empty] | | [empty] | <-- top top --> | [empty] | -// +-----------+ +-----------+ +-----------+ -// -// Or, if there is only one circular buffer, it looks something -// like either of these: -// -// head tail head tail -// | | | | -// v v v v -// +-----------+ +-----------+ -// | [null] | | [null] | -// +-----------+ +-----------+ -// | [empty] | | item | -// | [empty] | | item | -// | item | <-- bottom top --> | [empty] | -// | item | | [empty] | -// | [empty] | <-- top bottom --> | item | -// | [empty] | | item | -// +-----------+ +-----------+ -// -// Adding a value means moving `top` forward by one, removing means -// moving `bottom` forward by one. After reaching the end, the queue -// wraps around. -// -// When `top === bottom` the current queue is empty and when -// `top + 1 === bottom` it's full. This wastes a single space of storage -// but allows much quicker checks. +function requestBadPort (request) { + // 1. Let url be request’s current URL. + const url = requestCurrentURL(request) -class FixedCircularBuffer { - constructor() { - this.bottom = 0; - this.top = 0; - this.list = new Array(kSize); - this.next = null; + // 2. If url’s scheme is an HTTP(S) scheme and url’s port is a bad port, + // then return blocked. + if (urlIsHttpHttpsScheme(url) && badPortsSet.has(url.port)) { + return 'blocked' } - isEmpty() { - return this.top === this.bottom; - } + // 3. Return allowed. + return 'allowed' +} - isFull() { - return ((this.top + 1) & kMask) === this.bottom; - } +function isErrorLike (object) { + return object instanceof Error || ( + object?.constructor?.name === 'Error' || + object?.constructor?.name === 'DOMException' + ) +} - push(data) { - this.list[this.top] = data; - this.top = (this.top + 1) & kMask; +// Check whether |statusText| is a ByteString and +// matches the Reason-Phrase token production. +// RFC 2616: https://tools.ietf.org/html/rfc2616 +// RFC 7230: https://tools.ietf.org/html/rfc7230 +// "reason-phrase = *( HTAB / SP / VCHAR / obs-text )" +// https://github.com/chromium/chromium/blob/94.0.4604.1/third_party/blink/renderer/core/fetch/response.cc#L116 +function isValidReasonPhrase (statusText) { + for (let i = 0; i < statusText.length; ++i) { + const c = statusText.charCodeAt(i) + if ( + !( + ( + c === 0x09 || // HTAB + (c >= 0x20 && c <= 0x7e) || // SP / VCHAR + (c >= 0x80 && c <= 0xff) + ) // obs-text + ) + ) { + return false + } } + return true +} - shift() { - const nextItem = this.list[this.bottom]; - if (nextItem === undefined) - return null; - this.list[this.bottom] = undefined; - this.bottom = (this.bottom + 1) & kMask; - return nextItem; - } +/** + * @see https://fetch.spec.whatwg.org/#header-name + * @param {string} potentialValue + */ +const isValidHeaderName = isValidHTTPToken + +/** + * @see https://fetch.spec.whatwg.org/#header-value + * @param {string} potentialValue + */ +function isValidHeaderValue (potentialValue) { + // - Has no leading or trailing HTTP tab or space bytes. + // - Contains no 0x00 (NUL) or HTTP newline bytes. + return ( + potentialValue[0] === '\t' || + potentialValue[0] === ' ' || + potentialValue[potentialValue.length - 1] === '\t' || + potentialValue[potentialValue.length - 1] === ' ' || + potentialValue.includes('\n') || + potentialValue.includes('\r') || + potentialValue.includes('\0') + ) === false } -module.exports = class FixedQueue { - constructor() { - this.head = this.tail = new FixedCircularBuffer(); - } +// https://w3c.github.io/webappsec-referrer-policy/#set-requests-referrer-policy-on-redirect +function setRequestReferrerPolicyOnRedirect (request, actualResponse) { + // Given a request request and a response actualResponse, this algorithm + // updates request’s referrer policy according to the Referrer-Policy + // header (if any) in actualResponse. - isEmpty() { - return this.head.isEmpty(); - } + // 1. Let policy be the result of executing § 8.1 Parse a referrer policy + // from a Referrer-Policy header on actualResponse. - push(data) { - if (this.head.isFull()) { - // Head is full: Creates a new queue, sets the old queue's `.next` to it, - // and sets it as the new main queue. - this.head = this.head.next = new FixedCircularBuffer(); - } - this.head.push(data); - } + // 8.1 Parse a referrer policy from a Referrer-Policy header + // 1. Let policy-tokens be the result of extracting header list values given `Referrer-Policy` and response’s header list. + const { headersList } = actualResponse + // 2. Let policy be the empty string. + // 3. For each token in policy-tokens, if token is a referrer policy and token is not the empty string, then set policy to token. + // 4. Return policy. + const policyHeader = (headersList.get('referrer-policy', true) ?? '').split(',') - shift() { - const tail = this.tail; - const next = tail.shift(); - if (tail.isEmpty() && tail.next !== null) { - // If there is another queue, it forms the new tail. - this.tail = tail.next; + // Note: As the referrer-policy can contain multiple policies + // separated by comma, we need to loop through all of them + // and pick the first valid one. + // Ref: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy#specify_a_fallback_policy + let policy = '' + if (policyHeader.length > 0) { + // The right-most policy takes precedence. + // The left-most policy is the fallback. + for (let i = policyHeader.length; i !== 0; i--) { + const token = policyHeader[i - 1].trim() + if (referrerPolicyTokens.has(token)) { + policy = token + break + } } - return next; } -}; - -/***/ }), + // 2. If policy is not the empty string, then set request’s referrer policy to policy. + if (policy !== '') { + request.referrerPolicy = policy + } +} -/***/ 9237: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +// https://fetch.spec.whatwg.org/#cross-origin-resource-policy-check +function crossOriginResourcePolicyCheck () { + // TODO + return 'allowed' +} -"use strict"; +// https://fetch.spec.whatwg.org/#concept-cors-check +function corsCheck () { + // TODO + return 'success' +} +// https://fetch.spec.whatwg.org/#concept-tao-check +function TAOCheck () { + // TODO + return 'success' +} -const DispatcherBase = __nccwpck_require__(7172) -const FixedQueue = __nccwpck_require__(8666) -const { kConnected, kSize, kRunning, kPending, kQueued, kBusy, kFree, kUrl, kClose, kDestroy, kDispatch } = __nccwpck_require__(1028) -const PoolStats = __nccwpck_require__(9653) +function appendFetchMetadata (httpRequest) { + // https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-dest-header + // TODO -const kClients = Symbol('clients') -const kNeedDrain = Symbol('needDrain') -const kQueue = Symbol('queue') -const kClosedResolve = Symbol('closed resolve') -const kOnDrain = Symbol('onDrain') -const kOnConnect = Symbol('onConnect') -const kOnDisconnect = Symbol('onDisconnect') -const kOnConnectionError = Symbol('onConnectionError') -const kGetDispatcher = Symbol('get dispatcher') -const kAddClient = Symbol('add client') -const kRemoveClient = Symbol('remove client') -const kStats = Symbol('stats') + // https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-mode-header -class PoolBase extends DispatcherBase { - constructor () { - super() + // 1. Assert: r’s url is a potentially trustworthy URL. + // TODO - this[kQueue] = new FixedQueue() - this[kClients] = [] - this[kQueued] = 0 + // 2. Let header be a Structured Header whose value is a token. + let header = null - const pool = this + // 3. Set header’s value to r’s mode. + header = httpRequest.mode - this[kOnDrain] = function onDrain (origin, targets) { - const queue = pool[kQueue] + // 4. Set a structured field value `Sec-Fetch-Mode`/header in r’s header list. + httpRequest.headersList.set('sec-fetch-mode', header, true) - let needDrain = false + // https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-site-header + // TODO - while (!needDrain) { - const item = queue.shift() - if (!item) { - break - } - pool[kQueued]-- - needDrain = !this.dispatch(item.opts, item.handler) - } + // https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-user-header + // TODO +} - this[kNeedDrain] = needDrain +// https://fetch.spec.whatwg.org/#append-a-request-origin-header +function appendRequestOriginHeader (request) { + // 1. Let serializedOrigin be the result of byte-serializing a request origin + // with request. + // TODO: implement "byte-serializing a request origin" + let serializedOrigin = request.origin - if (!this[kNeedDrain] && pool[kNeedDrain]) { - pool[kNeedDrain] = false - pool.emit('drain', origin, [pool, ...targets]) - } + // - "'client' is changed to an origin during fetching." + // This doesn't happen in undici (in most cases) because undici, by default, + // has no concept of origin. + // - request.origin can also be set to request.client.origin (client being + // an environment settings object), which is undefined without using + // setGlobalOrigin. + if (serializedOrigin === 'client' || serializedOrigin === undefined) { + return + } - if (pool[kClosedResolve] && queue.isEmpty()) { - Promise - .all(pool[kClients].map(c => c.close())) - .then(pool[kClosedResolve]) - } + // 2. If request’s response tainting is "cors" or request’s mode is "websocket", + // then append (`Origin`, serializedOrigin) to request’s header list. + // 3. Otherwise, if request’s method is neither `GET` nor `HEAD`, then: + if (request.responseTainting === 'cors' || request.mode === 'websocket') { + request.headersList.append('origin', serializedOrigin, true) + } else if (request.method !== 'GET' && request.method !== 'HEAD') { + // 1. Switch on request’s referrer policy: + switch (request.referrerPolicy) { + case 'no-referrer': + // Set serializedOrigin to `null`. + serializedOrigin = null + break + case 'no-referrer-when-downgrade': + case 'strict-origin': + case 'strict-origin-when-cross-origin': + // If request’s origin is a tuple origin, its scheme is "https", and + // request’s current URL’s scheme is not "https", then set + // serializedOrigin to `null`. + if (request.origin && urlHasHttpsScheme(request.origin) && !urlHasHttpsScheme(requestCurrentURL(request))) { + serializedOrigin = null + } + break + case 'same-origin': + // If request’s origin is not same origin with request’s current URL’s + // origin, then set serializedOrigin to `null`. + if (!sameOrigin(request, requestCurrentURL(request))) { + serializedOrigin = null + } + break + default: + // Do nothing. } - this[kOnConnect] = (origin, targets) => { - pool.emit('connect', origin, [pool, ...targets]) - } + // 2. Append (`Origin`, serializedOrigin) to request’s header list. + request.headersList.append('origin', serializedOrigin, true) + } +} - this[kOnDisconnect] = (origin, targets, err) => { - pool.emit('disconnect', origin, [pool, ...targets], err) - } +// https://w3c.github.io/hr-time/#dfn-coarsen-time +function coarsenTime (timestamp, crossOriginIsolatedCapability) { + // TODO + return timestamp +} - this[kOnConnectionError] = (origin, targets, err) => { - pool.emit('connectionError', origin, [pool, ...targets], err) +// https://fetch.spec.whatwg.org/#clamp-and-coarsen-connection-timing-info +function clampAndCoarsenConnectionTimingInfo (connectionTimingInfo, defaultStartTime, crossOriginIsolatedCapability) { + if (!connectionTimingInfo?.startTime || connectionTimingInfo.startTime < defaultStartTime) { + return { + domainLookupStartTime: defaultStartTime, + domainLookupEndTime: defaultStartTime, + connectionStartTime: defaultStartTime, + connectionEndTime: defaultStartTime, + secureConnectionStartTime: defaultStartTime, + ALPNNegotiatedProtocol: connectionTimingInfo?.ALPNNegotiatedProtocol } - - this[kStats] = new PoolStats(this) } - get [kBusy] () { - return this[kNeedDrain] + return { + domainLookupStartTime: coarsenTime(connectionTimingInfo.domainLookupStartTime, crossOriginIsolatedCapability), + domainLookupEndTime: coarsenTime(connectionTimingInfo.domainLookupEndTime, crossOriginIsolatedCapability), + connectionStartTime: coarsenTime(connectionTimingInfo.connectionStartTime, crossOriginIsolatedCapability), + connectionEndTime: coarsenTime(connectionTimingInfo.connectionEndTime, crossOriginIsolatedCapability), + secureConnectionStartTime: coarsenTime(connectionTimingInfo.secureConnectionStartTime, crossOriginIsolatedCapability), + ALPNNegotiatedProtocol: connectionTimingInfo.ALPNNegotiatedProtocol } +} - get [kConnected] () { - return this[kClients].filter(client => client[kConnected]).length - } +// https://w3c.github.io/hr-time/#dfn-coarsened-shared-current-time +function coarsenedSharedCurrentTime (crossOriginIsolatedCapability) { + return coarsenTime(performance.now(), crossOriginIsolatedCapability) +} - get [kFree] () { - return this[kClients].filter(client => client[kConnected] && !client[kNeedDrain]).length +// https://fetch.spec.whatwg.org/#create-an-opaque-timing-info +function createOpaqueTimingInfo (timingInfo) { + return { + startTime: timingInfo.startTime ?? 0, + redirectStartTime: 0, + redirectEndTime: 0, + postRedirectStartTime: timingInfo.startTime ?? 0, + finalServiceWorkerStartTime: 0, + finalNetworkResponseStartTime: 0, + finalNetworkRequestStartTime: 0, + endTime: 0, + encodedBodySize: 0, + decodedBodySize: 0, + finalConnectionTimingInfo: null } +} - get [kPending] () { - let ret = this[kQueued] - for (const { [kPending]: pending } of this[kClients]) { - ret += pending - } - return ret +// https://html.spec.whatwg.org/multipage/origin.html#policy-container +function makePolicyContainer () { + // Note: the fetch spec doesn't make use of embedder policy or CSP list + return { + referrerPolicy: 'strict-origin-when-cross-origin' } +} - get [kRunning] () { - let ret = 0 - for (const { [kRunning]: running } of this[kClients]) { - ret += running - } - return ret +// https://html.spec.whatwg.org/multipage/origin.html#clone-a-policy-container +function clonePolicyContainer (policyContainer) { + return { + referrerPolicy: policyContainer.referrerPolicy } +} - get [kSize] () { - let ret = this[kQueued] - for (const { [kSize]: size } of this[kClients]) { - ret += size - } - return ret - } +// https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer +function determineRequestsReferrer (request) { + // 1. Let policy be request's referrer policy. + const policy = request.referrerPolicy - get stats () { - return this[kStats] - } + // Note: policy cannot (shouldn't) be null or an empty string. + assert(policy) - async [kClose] () { - if (this[kQueue].isEmpty()) { - return Promise.all(this[kClients].map(c => c.close())) - } else { - return new Promise((resolve) => { - this[kClosedResolve] = resolve - }) - } - } + // 2. Let environment be request’s client. - async [kDestroy] (err) { - while (true) { - const item = this[kQueue].shift() - if (!item) { - break - } - item.handler.onError(err) - } + let referrerSource = null - return Promise.all(this[kClients].map(c => c.destroy(err))) - } + // 3. Switch on request’s referrer: + if (request.referrer === 'client') { + // Note: node isn't a browser and doesn't implement document/iframes, + // so we bypass this step and replace it with our own. - [kDispatch] (opts, handler) { - const dispatcher = this[kGetDispatcher]() + const globalOrigin = getGlobalOrigin() - if (!dispatcher) { - this[kNeedDrain] = true - this[kQueue].push({ opts, handler }) - this[kQueued]++ - } else if (!dispatcher.dispatch(opts, handler)) { - dispatcher[kNeedDrain] = true - this[kNeedDrain] = !this[kGetDispatcher]() + if (!globalOrigin || globalOrigin.origin === 'null') { + return 'no-referrer' } - return !this[kNeedDrain] + // note: we need to clone it as it's mutated + referrerSource = new URL(globalOrigin) + } else if (request.referrer instanceof URL) { + // Let referrerSource be request’s referrer. + referrerSource = request.referrer } - [kAddClient] (client) { - client - .on('drain', this[kOnDrain]) - .on('connect', this[kOnConnect]) - .on('disconnect', this[kOnDisconnect]) - .on('connectionError', this[kOnConnectionError]) - - this[kClients].push(client) + // 4. Let request’s referrerURL be the result of stripping referrerSource for + // use as a referrer. + let referrerURL = stripURLForReferrer(referrerSource) - if (this[kNeedDrain]) { - process.nextTick(() => { - if (this[kNeedDrain]) { - this[kOnDrain](client[kUrl], [this, client]) - } - }) - } + // 5. Let referrerOrigin be the result of stripping referrerSource for use as + // a referrer, with the origin-only flag set to true. + const referrerOrigin = stripURLForReferrer(referrerSource, true) - return this + // 6. If the result of serializing referrerURL is a string whose length is + // greater than 4096, set referrerURL to referrerOrigin. + if (referrerURL.toString().length > 4096) { + referrerURL = referrerOrigin } - [kRemoveClient] (client) { - client.close(() => { - const idx = this[kClients].indexOf(client) - if (idx !== -1) { - this[kClients].splice(idx, 1) - } - }) + const areSameOrigin = sameOrigin(request, referrerURL) + const isNonPotentiallyTrustWorthy = isURLPotentiallyTrustworthy(referrerURL) && + !isURLPotentiallyTrustworthy(request.url) - this[kNeedDrain] = this[kClients].some(dispatcher => ( - !dispatcher[kNeedDrain] && - dispatcher.closed !== true && - dispatcher.destroyed !== true - )) - } -} + // 8. Execute the switch statements corresponding to the value of policy: + switch (policy) { + case 'origin': return referrerOrigin != null ? referrerOrigin : stripURLForReferrer(referrerSource, true) + case 'unsafe-url': return referrerURL + case 'same-origin': + return areSameOrigin ? referrerOrigin : 'no-referrer' + case 'origin-when-cross-origin': + return areSameOrigin ? referrerURL : referrerOrigin + case 'strict-origin-when-cross-origin': { + const currentURL = requestCurrentURL(request) -module.exports = { - PoolBase, - kClients, - kNeedDrain, - kAddClient, - kRemoveClient, - kGetDispatcher -} - - -/***/ }), - -/***/ 9653: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -const { kFree, kConnected, kPending, kQueued, kRunning, kSize } = __nccwpck_require__(1028) -const kPool = Symbol('pool') - -class PoolStats { - constructor (pool) { - this[kPool] = pool - } - - get connected () { - return this[kPool][kConnected] - } - - get free () { - return this[kPool][kFree] - } - - get pending () { - return this[kPool][kPending] - } + // 1. If the origin of referrerURL and the origin of request’s current + // URL are the same, then return referrerURL. + if (sameOrigin(referrerURL, currentURL)) { + return referrerURL + } - get queued () { - return this[kPool][kQueued] - } + // 2. If referrerURL is a potentially trustworthy URL and request’s + // current URL is not a potentially trustworthy URL, then return no + // referrer. + if (isURLPotentiallyTrustworthy(referrerURL) && !isURLPotentiallyTrustworthy(currentURL)) { + return 'no-referrer' + } - get running () { - return this[kPool][kRunning] - } + // 3. Return referrerOrigin. + return referrerOrigin + } + case 'strict-origin': // eslint-disable-line + /** + * 1. If referrerURL is a potentially trustworthy URL and + * request’s current URL is not a potentially trustworthy URL, + * then return no referrer. + * 2. Return referrerOrigin + */ + case 'no-referrer-when-downgrade': // eslint-disable-line + /** + * 1. If referrerURL is a potentially trustworthy URL and + * request’s current URL is not a potentially trustworthy URL, + * then return no referrer. + * 2. Return referrerOrigin + */ - get size () { - return this[kPool][kSize] + default: // eslint-disable-line + return isNonPotentiallyTrustWorthy ? 'no-referrer' : referrerOrigin } } -module.exports = PoolStats +/** + * @see https://w3c.github.io/webappsec-referrer-policy/#strip-url + * @param {URL} url + * @param {boolean|undefined} originOnly + */ +function stripURLForReferrer (url, originOnly) { + // 1. Assert: url is a URL. + assert(url instanceof URL) + url = new URL(url) -/***/ }), + // 2. If url’s scheme is a local scheme, then return no referrer. + if (url.protocol === 'file:' || url.protocol === 'about:' || url.protocol === 'blank:') { + return 'no-referrer' + } -/***/ 7279: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // 3. Set url’s username to the empty string. + url.username = '' -"use strict"; + // 4. Set url’s password to the empty string. + url.password = '' + // 5. Set url’s fragment to null. + url.hash = '' -const { - PoolBase, - kClients, - kNeedDrain, - kAddClient, - kGetDispatcher -} = __nccwpck_require__(9237) -const Client = __nccwpck_require__(6466) -const { - InvalidArgumentError -} = __nccwpck_require__(6738) -const util = __nccwpck_require__(5069) -const { kUrl, kInterceptors } = __nccwpck_require__(1028) -const buildConnector = __nccwpck_require__(9323) + // 6. If the origin-only flag is true, then: + if (originOnly) { + // 1. Set url’s path to « the empty string ». + url.pathname = '' -const kOptions = Symbol('options') -const kConnections = Symbol('connections') -const kFactory = Symbol('factory') + // 2. Set url’s query to null. + url.search = '' + } -function defaultFactory (origin, opts) { - return new Client(origin, opts) + // 7. Return url. + return url } -class Pool extends PoolBase { - constructor (origin, { - connections, - factory = defaultFactory, - connect, - connectTimeout, - tls, - maxCachedSessions, - socketPath, - autoSelectFamily, - autoSelectFamilyAttemptTimeout, - allowH2, - ...options - } = {}) { - super() - - if (connections != null && (!Number.isFinite(connections) || connections < 0)) { - throw new InvalidArgumentError('invalid connections') - } +function isURLPotentiallyTrustworthy (url) { + if (!(url instanceof URL)) { + return false + } - if (typeof factory !== 'function') { - throw new InvalidArgumentError('factory must be a function.') - } + // If child of about, return true + if (url.href === 'about:blank' || url.href === 'about:srcdoc') { + return true + } - if (connect != null && typeof connect !== 'function' && typeof connect !== 'object') { - throw new InvalidArgumentError('connect must be a function or an object') - } + // If scheme is data, return true + if (url.protocol === 'data:') return true - if (typeof connect !== 'function') { - connect = buildConnector({ - ...tls, - maxCachedSessions, - allowH2, - socketPath, - timeout: connectTimeout, - ...(util.nodeHasAutoSelectFamily && autoSelectFamily ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : undefined), - ...connect - }) - } + // If file, return true + if (url.protocol === 'file:') return true - this[kInterceptors] = options.interceptors && options.interceptors.Pool && Array.isArray(options.interceptors.Pool) - ? options.interceptors.Pool - : [] - this[kConnections] = connections || null - this[kUrl] = util.parseOrigin(origin) - this[kOptions] = { ...util.deepClone(options), connect, allowH2 } - this[kOptions].interceptors = options.interceptors - ? { ...options.interceptors } - : undefined - this[kFactory] = factory + return isOriginPotentiallyTrustworthy(url.origin) - this.on('connectionError', (origin, targets, error) => { - // If a connection error occurs, we remove the client from the pool, - // and emit a connectionError event. They will not be re-used. - // Fixes https://github.com/nodejs/undici/issues/3895 - for (const target of targets) { - // Do not use kRemoveClient here, as it will close the client, - // but the client cannot be closed in this state. - const idx = this[kClients].indexOf(target) - if (idx !== -1) { - this[kClients].splice(idx, 1) - } - } - }) - } + function isOriginPotentiallyTrustworthy (origin) { + // If origin is explicitly null, return false + if (origin == null || origin === 'null') return false - [kGetDispatcher] () { - let dispatcher = this[kClients].find(dispatcher => !dispatcher[kNeedDrain]) + const originAsURL = new URL(origin) - if (dispatcher) { - return dispatcher + // If secure, return true + if (originAsURL.protocol === 'https:' || originAsURL.protocol === 'wss:') { + return true } - if (!this[kConnections] || this[kClients].length < this[kConnections]) { - dispatcher = this[kFactory](this[kUrl], this[kOptions]) - this[kAddClient](dispatcher) + // If localhost or variants, return true + if (/^127(?:\.[0-9]+){0,2}\.[0-9]+$|^\[(?:0*:)*?:?0*1\]$/.test(originAsURL.hostname) || + (originAsURL.hostname === 'localhost' || originAsURL.hostname.includes('localhost.')) || + (originAsURL.hostname.endsWith('.localhost'))) { + return true } - return dispatcher + // If any other, return false + return false } } -module.exports = Pool +/** + * @see https://w3c.github.io/webappsec-subresource-integrity/#does-response-match-metadatalist + * @param {Uint8Array} bytes + * @param {string} metadataList + */ +function bytesMatch (bytes, metadataList) { + // If node is not built with OpenSSL support, we cannot check + // a request's integrity, so allow it by default (the spec will + // allow requests if an invalid hash is given, as precedence). + /* istanbul ignore if: only if node is built with --without-ssl */ + if (crypto === undefined) { + return true + } + // 1. Let parsedMetadata be the result of parsing metadataList. + const parsedMetadata = parseMetadata(metadataList) -/***/ }), + // 2. If parsedMetadata is no metadata, return true. + if (parsedMetadata === 'no metadata') { + return true + } -/***/ 4469: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // 3. If response is not eligible for integrity validation, return false. + // TODO -"use strict"; + // 4. If parsedMetadata is the empty set, return true. + if (parsedMetadata.length === 0) { + return true + } + // 5. Let metadata be the result of getting the strongest + // metadata from parsedMetadata. + const strongest = getStrongestMetadata(parsedMetadata) + const metadata = filterMetadataListByAlgorithm(parsedMetadata, strongest) -const { kProxy, kClose, kDestroy, kInterceptors } = __nccwpck_require__(1028) -const { URL } = __nccwpck_require__(7016) -const Agent = __nccwpck_require__(2308) -const Pool = __nccwpck_require__(7279) -const DispatcherBase = __nccwpck_require__(7172) -const { InvalidArgumentError, RequestAbortedError } = __nccwpck_require__(6738) -const buildConnector = __nccwpck_require__(9323) + // 6. For each item in metadata: + for (const item of metadata) { + // 1. Let algorithm be the alg component of item. + const algorithm = item.algo -const kAgent = Symbol('proxy agent') -const kClient = Symbol('proxy client') -const kProxyHeaders = Symbol('proxy headers') -const kRequestTls = Symbol('request tls settings') -const kProxyTls = Symbol('proxy tls settings') -const kConnectEndpoint = Symbol('connect endpoint function') + // 2. Let expectedValue be the val component of item. + const expectedValue = item.hash -function defaultProtocolPort (protocol) { - return protocol === 'https:' ? 443 : 80 -} + // See https://github.com/web-platform-tests/wpt/commit/e4c5cc7a5e48093220528dfdd1c4012dc3837a0e + // "be liberal with padding". This is annoying, and it's not even in the spec. -function buildProxyOptions (opts) { - if (typeof opts === 'string') { - opts = { uri: opts } - } + // 3. Let actualValue be the result of applying algorithm to bytes. + let actualValue = crypto.createHash(algorithm).update(bytes).digest('base64') - if (!opts || !opts.uri) { - throw new InvalidArgumentError('Proxy opts.uri is mandatory') - } + if (actualValue[actualValue.length - 1] === '=') { + if (actualValue[actualValue.length - 2] === '=') { + actualValue = actualValue.slice(0, -2) + } else { + actualValue = actualValue.slice(0, -1) + } + } - return { - uri: opts.uri, - protocol: opts.protocol || 'https' + // 4. If actualValue is a case-sensitive match for expectedValue, + // return true. + if (compareBase64Mixed(actualValue, expectedValue)) { + return true + } } -} -function defaultFactory (origin, opts) { - return new Pool(origin, opts) + // 7. Return false. + return false } -class ProxyAgent extends DispatcherBase { - constructor (opts) { - super(opts) - this[kProxy] = buildProxyOptions(opts) - this[kAgent] = new Agent(opts) - this[kInterceptors] = opts.interceptors && opts.interceptors.ProxyAgent && Array.isArray(opts.interceptors.ProxyAgent) - ? opts.interceptors.ProxyAgent - : [] - - if (typeof opts === 'string') { - opts = { uri: opts } - } - - if (!opts || !opts.uri) { - throw new InvalidArgumentError('Proxy opts.uri is mandatory') - } +// https://w3c.github.io/webappsec-subresource-integrity/#grammardef-hash-with-options +// https://www.w3.org/TR/CSP2/#source-list-syntax +// https://www.rfc-editor.org/rfc/rfc5234#appendix-B.1 +const parseHashWithOptions = /(?sha256|sha384|sha512)-((?[A-Za-z0-9+/]+|[A-Za-z0-9_-]+)={0,2}(?:\s|$)( +[!-~]*)?)?/i - const { clientFactory = defaultFactory } = opts +/** + * @see https://w3c.github.io/webappsec-subresource-integrity/#parse-metadata + * @param {string} metadata + */ +function parseMetadata (metadata) { + // 1. Let result be the empty set. + /** @type {{ algo: string, hash: string }[]} */ + const result = [] - if (typeof clientFactory !== 'function') { - throw new InvalidArgumentError('Proxy opts.clientFactory must be a function.') - } + // 2. Let empty be equal to true. + let empty = true - this[kRequestTls] = opts.requestTls - this[kProxyTls] = opts.proxyTls - this[kProxyHeaders] = opts.headers || {} + // 3. For each token returned by splitting metadata on spaces: + for (const token of metadata.split(' ')) { + // 1. Set empty to false. + empty = false - const resolvedUrl = new URL(opts.uri) - const { origin, port, host, username, password } = resolvedUrl + // 2. Parse token as a hash-with-options. + const parsedToken = parseHashWithOptions.exec(token) - if (opts.auth && opts.token) { - throw new InvalidArgumentError('opts.auth cannot be used in combination with opts.token') - } else if (opts.auth) { - /* @deprecated in favour of opts.token */ - this[kProxyHeaders]['proxy-authorization'] = `Basic ${opts.auth}` - } else if (opts.token) { - this[kProxyHeaders]['proxy-authorization'] = opts.token - } else if (username && password) { - this[kProxyHeaders]['proxy-authorization'] = `Basic ${Buffer.from(`${decodeURIComponent(username)}:${decodeURIComponent(password)}`).toString('base64')}` + // 3. If token does not parse, continue to the next token. + if ( + parsedToken === null || + parsedToken.groups === undefined || + parsedToken.groups.algo === undefined + ) { + // Note: Chromium blocks the request at this point, but Firefox + // gives a warning that an invalid integrity was given. The + // correct behavior is to ignore these, and subsequently not + // check the integrity of the resource. + continue } - const connect = buildConnector({ ...opts.proxyTls }) - this[kConnectEndpoint] = buildConnector({ ...opts.requestTls }) - this[kClient] = clientFactory(resolvedUrl, { connect }) - this[kAgent] = new Agent({ - ...opts, - connect: async (opts, callback) => { - let requestedHost = opts.host - if (!opts.port) { - requestedHost += `:${defaultProtocolPort(opts.protocol)}` - } - try { - const { socket, statusCode } = await this[kClient].connect({ - origin, - port, - path: requestedHost, - signal: opts.signal, - headers: { - ...this[kProxyHeaders], - host - } - }) - if (statusCode !== 200) { - socket.on('error', () => {}).destroy() - callback(new RequestAbortedError(`Proxy response (${statusCode}) !== 200 when HTTP Tunneling`)) - } - if (opts.protocol !== 'https:') { - callback(null, socket) - return - } - let servername - if (this[kRequestTls]) { - servername = this[kRequestTls].servername - } else { - servername = opts.servername - } - this[kConnectEndpoint]({ ...opts, servername, httpSocket: socket }, callback) - } catch (err) { - callback(err) - } - } - }) - } + // 4. Let algorithm be the hash-algo component of token. + const algorithm = parsedToken.groups.algo.toLowerCase() - dispatch (opts, handler) { - const { host } = new URL(opts.origin) - const headers = buildHeaders(opts.headers) - throwIfProxyAuthIsSent(headers) - return this[kAgent].dispatch( - { - ...opts, - headers: { - ...headers, - host - } - }, - handler - ) + // 5. If algorithm is a hash function recognized by the user + // agent, add the parsed token to result. + if (supportedHashes.includes(algorithm)) { + result.push(parsedToken.groups) + } } - async [kClose] () { - await this[kAgent].close() - await this[kClient].close() + // 4. Return no metadata if empty is true, otherwise return result. + if (empty === true) { + return 'no metadata' } - async [kDestroy] () { - await this[kAgent].destroy() - await this[kClient].destroy() - } + return result } /** - * @param {string[] | Record} headers - * @returns {Record} + * @param {{ algo: 'sha256' | 'sha384' | 'sha512' }[]} metadataList */ -function buildHeaders (headers) { - // When using undici.fetch, the headers list is stored - // as an array. - if (Array.isArray(headers)) { - /** @type {Record} */ - const headersPair = {} +function getStrongestMetadata (metadataList) { + // Let algorithm be the algo component of the first item in metadataList. + // Can be sha256 + let algorithm = metadataList[0].algo + // If the algorithm is sha512, then it is the strongest + // and we can return immediately + if (algorithm[3] === '5') { + return algorithm + } - for (let i = 0; i < headers.length; i += 2) { - headersPair[headers[i]] = headers[i + 1] + for (let i = 1; i < metadataList.length; ++i) { + const metadata = metadataList[i] + // If the algorithm is sha512, then it is the strongest + // and we can break the loop immediately + if (metadata.algo[3] === '5') { + algorithm = 'sha512' + break + // If the algorithm is sha384, then a potential sha256 or sha384 is ignored + } else if (algorithm[3] === '3') { + continue + // algorithm is sha256, check if algorithm is sha384 and if so, set it as + // the strongest + } else if (metadata.algo[3] === '3') { + algorithm = 'sha384' } + } + return algorithm +} - return headersPair +function filterMetadataListByAlgorithm (metadataList, algorithm) { + if (metadataList.length === 1) { + return metadataList } - return headers + let pos = 0 + for (let i = 0; i < metadataList.length; ++i) { + if (metadataList[i].algo === algorithm) { + metadataList[pos++] = metadataList[i] + } + } + + metadataList.length = pos + + return metadataList } /** - * @param {Record} headers + * Compares two base64 strings, allowing for base64url + * in the second string. * - * Previous versions of ProxyAgent suggests the Proxy-Authorization in request headers - * Nevertheless, it was changed and to avoid a security vulnerability by end users - * this check was created. - * It should be removed in the next major version for performance reasons +* @param {string} actualValue always base64 + * @param {string} expectedValue base64 or base64url + * @returns {boolean} */ -function throwIfProxyAuthIsSent (headers) { - const existProxyAuth = headers && Object.keys(headers) - .find((key) => key.toLowerCase() === 'proxy-authorization') - if (existProxyAuth) { - throw new InvalidArgumentError('Proxy-Authorization should be sent in ProxyAgent constructor') +function compareBase64Mixed (actualValue, expectedValue) { + if (actualValue.length !== expectedValue.length) { + return false + } + for (let i = 0; i < actualValue.length; ++i) { + if (actualValue[i] !== expectedValue[i]) { + if ( + (actualValue[i] === '+' && expectedValue[i] === '-') || + (actualValue[i] === '/' && expectedValue[i] === '_') + ) { + continue + } + return false + } } + + return true } -module.exports = ProxyAgent +// https://w3c.github.io/webappsec-upgrade-insecure-requests/#upgrade-request +function tryUpgradeRequestToAPotentiallyTrustworthyURL (request) { + // TODO +} +/** + * @link {https://html.spec.whatwg.org/multipage/origin.html#same-origin} + * @param {URL} A + * @param {URL} B + */ +function sameOrigin (A, B) { + // 1. If A and B are the same opaque origin, then return true. + if (A.origin === B.origin && A.origin === 'null') { + return true + } -/***/ }), + // 2. If A and B are both tuple origins and their schemes, + // hosts, and port are identical, then return true. + if (A.protocol === B.protocol && A.hostname === B.hostname && A.port === B.port) { + return true + } -/***/ 1775: -/***/ ((module) => { + // 3. Return false. + return false +} -"use strict"; +function createDeferredPromise () { + let res + let rej + const promise = new Promise((resolve, reject) => { + res = resolve + rej = reject + }) + return { promise, resolve: res, reject: rej } +} -let fastNow = Date.now() -let fastNowTimeout +function isAborted (fetchParams) { + return fetchParams.controller.state === 'aborted' +} -const fastTimers = [] - -function onTimeout () { - fastNow = Date.now() +function isCancelled (fetchParams) { + return fetchParams.controller.state === 'aborted' || + fetchParams.controller.state === 'terminated' +} - let len = fastTimers.length - let idx = 0 - while (idx < len) { - const timer = fastTimers[idx] +/** + * @see https://fetch.spec.whatwg.org/#concept-method-normalize + * @param {string} method + */ +function normalizeMethod (method) { + return normalizedMethodRecordsBase[method.toLowerCase()] ?? method +} - if (timer.state === 0) { - timer.state = fastNow + timer.delay - } else if (timer.state > 0 && fastNow >= timer.state) { - timer.state = -1 - timer.callback(timer.opaque) - } +// https://infra.spec.whatwg.org/#serialize-a-javascript-value-to-a-json-string +function serializeJavascriptValueToJSONString (value) { + // 1. Let result be ? Call(%JSON.stringify%, undefined, « value »). + const result = JSON.stringify(value) - if (timer.state === -1) { - timer.state = -2 - if (idx !== len - 1) { - fastTimers[idx] = fastTimers.pop() - } else { - fastTimers.pop() - } - len -= 1 - } else { - idx += 1 - } + // 2. If result is undefined, then throw a TypeError. + if (result === undefined) { + throw new TypeError('Value is not JSON serializable') } - if (fastTimers.length > 0) { - refreshTimeout() - } -} + // 3. Assert: result is a string. + assert(typeof result === 'string') -function refreshTimeout () { - if (fastNowTimeout && fastNowTimeout.refresh) { - fastNowTimeout.refresh() - } else { - clearTimeout(fastNowTimeout) - fastNowTimeout = setTimeout(onTimeout, 1e3) - if (fastNowTimeout.unref) { - fastNowTimeout.unref() - } - } + // 4. Return result. + return result } -class Timeout { - constructor (callback, delay, opaque) { - this.callback = callback - this.delay = delay - this.opaque = opaque +// https://tc39.es/ecma262/#sec-%25iteratorprototype%25-object +const esIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]())) - // -2 not in timer list - // -1 in timer list but inactive - // 0 in timer list waiting for time - // > 0 in timer list waiting for time to expire - this.state = -2 +/** + * @see https://webidl.spec.whatwg.org/#dfn-iterator-prototype-object + * @param {string} name name of the instance + * @param {symbol} kInternalIterator + * @param {string | number} [keyIndex] + * @param {string | number} [valueIndex] + */ +function createIterator (name, kInternalIterator, keyIndex = 0, valueIndex = 1) { + class FastIterableIterator { + /** @type {any} */ + #target + /** @type {'key' | 'value' | 'key+value'} */ + #kind + /** @type {number} */ + #index - this.refresh() - } + /** + * @see https://webidl.spec.whatwg.org/#dfn-default-iterator-object + * @param {unknown} target + * @param {'key' | 'value' | 'key+value'} kind + */ + constructor (target, kind) { + this.#target = target + this.#kind = kind + this.#index = 0 + } - refresh () { - if (this.state === -2) { - fastTimers.push(this) - if (!fastNowTimeout || fastTimers.length === 1) { - refreshTimeout() + next () { + // 1. Let interface be the interface for which the iterator prototype object exists. + // 2. Let thisValue be the this value. + // 3. Let object be ? ToObject(thisValue). + // 4. If object is a platform object, then perform a security + // check, passing: + // 5. If object is not a default iterator object for interface, + // then throw a TypeError. + if (typeof this !== 'object' || this === null || !(#target in this)) { + throw new TypeError( + `'next' called on an object that does not implement interface ${name} Iterator.` + ) } - } - this.state = 0 - } + // 6. Let index be object’s index. + // 7. Let kind be object’s kind. + // 8. Let values be object’s target's value pairs to iterate over. + const index = this.#index + const values = this.#target[kInternalIterator] - clear () { - this.state = -1 - } -} + // 9. Let len be the length of values. + const len = values.length -module.exports = { - setTimeout (callback, delay, opaque) { - return delay < 1e3 - ? setTimeout(callback, delay, opaque) - : new Timeout(callback, delay, opaque) - }, - clearTimeout (timeout) { - if (timeout instanceof Timeout) { - timeout.clear() - } else { - clearTimeout(timeout) - } - } -} + // 10. If index is greater than or equal to len, then return + // CreateIterResultObject(undefined, true). + if (index >= len) { + return { + value: undefined, + done: true + } + } + // 11. Let pair be the entry in values at index index. + const { [keyIndex]: key, [valueIndex]: value } = values[index] -/***/ }), + // 12. Set object’s index to index + 1. + this.#index = index + 1 -/***/ 3549: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // 13. Return the iterator result for pair and kind. + + // https://webidl.spec.whatwg.org/#iterator-result + + // 1. Let result be a value determined by the value of kind: + let result + switch (this.#kind) { + case 'key': + // 1. Let idlKey be pair’s key. + // 2. Let key be the result of converting idlKey to an + // ECMAScript value. + // 3. result is key. + result = key + break + case 'value': + // 1. Let idlValue be pair’s value. + // 2. Let value be the result of converting idlValue to + // an ECMAScript value. + // 3. result is value. + result = value + break + case 'key+value': + // 1. Let idlKey be pair’s key. + // 2. Let idlValue be pair’s value. + // 3. Let key be the result of converting idlKey to an + // ECMAScript value. + // 4. Let value be the result of converting idlValue to + // an ECMAScript value. + // 5. Let array be ! ArrayCreate(2). + // 6. Call ! CreateDataProperty(array, "0", key). + // 7. Call ! CreateDataProperty(array, "1", value). + // 8. result is array. + result = [key, value] + break + } -"use strict"; + // 2. Return CreateIterResultObject(result, false). + return { + value: result, + done: false + } + } + } + // https://webidl.spec.whatwg.org/#dfn-iterator-prototype-object + // @ts-ignore + delete FastIterableIterator.prototype.constructor -const diagnosticsChannel = __nccwpck_require__(1637) -const { uid, states } = __nccwpck_require__(3300) -const { - kReadyState, - kSentClose, - kByteParser, - kReceivedClose -} = __nccwpck_require__(7652) -const { fireEvent, failWebsocketConnection } = __nccwpck_require__(5117) -const { CloseEvent } = __nccwpck_require__(896) -const { makeRequest } = __nccwpck_require__(4555) -const { fetching } = __nccwpck_require__(8130) -const { Headers } = __nccwpck_require__(3640) -const { getGlobalDispatcher } = __nccwpck_require__(5334) -const { kHeadersList } = __nccwpck_require__(1028) - -const channels = {} -channels.open = diagnosticsChannel.channel('undici:websocket:open') -channels.close = diagnosticsChannel.channel('undici:websocket:close') -channels.socketError = diagnosticsChannel.channel('undici:websocket:socket_error') + Object.setPrototypeOf(FastIterableIterator.prototype, esIteratorPrototype) -/** @type {import('crypto')} */ -let crypto -try { - crypto = __nccwpck_require__(6982) -} catch { + Object.defineProperties(FastIterableIterator.prototype, { + [Symbol.toStringTag]: { + writable: false, + enumerable: false, + configurable: true, + value: `${name} Iterator` + }, + next: { writable: true, enumerable: true, configurable: true } + }) + /** + * @param {unknown} target + * @param {'key' | 'value' | 'key+value'} kind + * @returns {IterableIterator} + */ + return function (target, kind) { + return new FastIterableIterator(target, kind) + } } /** - * @see https://websockets.spec.whatwg.org/#concept-websocket-establish - * @param {URL} url - * @param {string|string[]} protocols - * @param {import('./websocket').WebSocket} ws - * @param {(response: any) => void} onEstablish - * @param {Partial} options + * @see https://webidl.spec.whatwg.org/#dfn-iterator-prototype-object + * @param {string} name name of the instance + * @param {any} object class + * @param {symbol} kInternalIterator + * @param {string | number} [keyIndex] + * @param {string | number} [valueIndex] */ -function establishWebSocketConnection (url, protocols, ws, onEstablish, options) { - // 1. Let requestURL be a copy of url, with its scheme set to "http", if url’s - // scheme is "ws", and to "https" otherwise. - const requestURL = url +function iteratorMixin (name, object, kInternalIterator, keyIndex = 0, valueIndex = 1) { + const makeIterator = createIterator(name, kInternalIterator, keyIndex, valueIndex) - requestURL.protocol = url.protocol === 'ws:' ? 'http:' : 'https:' + const properties = { + keys: { + writable: true, + enumerable: true, + configurable: true, + value: function keys () { + webidl.brandCheck(this, object) + return makeIterator(this, 'key') + } + }, + values: { + writable: true, + enumerable: true, + configurable: true, + value: function values () { + webidl.brandCheck(this, object) + return makeIterator(this, 'value') + } + }, + entries: { + writable: true, + enumerable: true, + configurable: true, + value: function entries () { + webidl.brandCheck(this, object) + return makeIterator(this, 'key+value') + } + }, + forEach: { + writable: true, + enumerable: true, + configurable: true, + value: function forEach (callbackfn, thisArg = globalThis) { + webidl.brandCheck(this, object) + webidl.argumentLengthCheck(arguments, 1, `${name}.forEach`) + if (typeof callbackfn !== 'function') { + throw new TypeError( + `Failed to execute 'forEach' on '${name}': parameter 1 is not of type 'Function'.` + ) + } + for (const { 0: key, 1: value } of makeIterator(this, 'key+value')) { + callbackfn.call(thisArg, value, key, this) + } + } + } + } - // 2. Let request be a new request, whose URL is requestURL, client is client, - // service-workers mode is "none", referrer is "no-referrer", mode is - // "websocket", credentials mode is "include", cache mode is "no-store" , - // and redirect mode is "error". - const request = makeRequest({ - urlList: [requestURL], - serviceWorkers: 'none', - referrer: 'no-referrer', - mode: 'websocket', - credentials: 'include', - cache: 'no-store', - redirect: 'error' + return Object.defineProperties(object.prototype, { + ...properties, + [Symbol.iterator]: { + writable: true, + enumerable: false, + configurable: true, + value: properties.entries.value + } }) +} - // Note: undici extension, allow setting custom headers. - if (options.headers) { - const headersList = new Headers(options.headers)[kHeadersList] - - request.headersList = headersList - } - - // 3. Append (`Upgrade`, `websocket`) to request’s header list. - // 4. Append (`Connection`, `Upgrade`) to request’s header list. - // Note: both of these are handled by undici currently. - // https://github.com/nodejs/undici/blob/68c269c4144c446f3f1220951338daef4a6b5ec4/lib/client.js#L1397 +/** + * @see https://fetch.spec.whatwg.org/#body-fully-read + */ +async function fullyReadBody (body, processBody, processBodyError) { + // 1. If taskDestination is null, then set taskDestination to + // the result of starting a new parallel queue. - // 5. Let keyValue be a nonce consisting of a randomly selected - // 16-byte value that has been forgiving-base64-encoded and - // isomorphic encoded. - const keyValue = crypto.randomBytes(16).toString('base64') + // 2. Let successSteps given a byte sequence bytes be to queue a + // fetch task to run processBody given bytes, with taskDestination. + const successSteps = processBody - // 6. Append (`Sec-WebSocket-Key`, keyValue) to request’s - // header list. - request.headersList.append('sec-websocket-key', keyValue) + // 3. Let errorSteps be to queue a fetch task to run processBodyError, + // with taskDestination. + const errorSteps = processBodyError - // 7. Append (`Sec-WebSocket-Version`, `13`) to request’s - // header list. - request.headersList.append('sec-websocket-version', '13') + // 4. Let reader be the result of getting a reader for body’s stream. + // If that threw an exception, then run errorSteps with that + // exception and return. + let reader - // 8. For each protocol in protocols, combine - // (`Sec-WebSocket-Protocol`, protocol) in request’s header - // list. - for (const protocol of protocols) { - request.headersList.append('sec-websocket-protocol', protocol) + try { + reader = body.stream.getReader() + } catch (e) { + errorSteps(e) + return } - // 9. Let permessageDeflate be a user-agent defined - // "permessage-deflate" extension header value. - // https://github.com/mozilla/gecko-dev/blob/ce78234f5e653a5d3916813ff990f053510227bc/netwerk/protocol/websocket/WebSocketChannel.cpp#L2673 - // TODO: enable once permessage-deflate is supported - const permessageDeflate = '' // 'permessage-deflate; 15' - - // 10. Append (`Sec-WebSocket-Extensions`, permessageDeflate) to - // request’s header list. - // request.headersList.append('sec-websocket-extensions', permessageDeflate) + // 5. Read all bytes from reader, given successSteps and errorSteps. + try { + successSteps(await readAllBytes(reader)) + } catch (e) { + errorSteps(e) + } +} - // 11. Fetch request with useParallelQueue set to true, and - // processResponse given response being these steps: - const controller = fetching({ - request, - useParallelQueue: true, - dispatcher: options.dispatcher ?? getGlobalDispatcher(), - processResponse (response) { - // 1. If response is a network error or its status is not 101, - // fail the WebSocket connection. - if (response.type === 'error' || response.status !== 101) { - failWebsocketConnection(ws, 'Received network error or non-101 status code.') - return - } +function isReadableStreamLike (stream) { + return stream instanceof ReadableStream || ( + stream[Symbol.toStringTag] === 'ReadableStream' && + typeof stream.tee === 'function' + ) +} - // 2. If protocols is not the empty list and extracting header - // list values given `Sec-WebSocket-Protocol` and response’s - // header list results in null, failure, or the empty byte - // sequence, then fail the WebSocket connection. - if (protocols.length !== 0 && !response.headersList.get('Sec-WebSocket-Protocol')) { - failWebsocketConnection(ws, 'Server did not respond with sent protocols.') - return - } +/** + * @param {ReadableStreamController} controller + */ +function readableStreamClose (controller) { + try { + controller.close() + controller.byobRequest?.respond(0) + } catch (err) { + // TODO: add comment explaining why this error occurs. + if (!err.message.includes('Controller is already closed') && !err.message.includes('ReadableStream is already closed')) { + throw err + } + } +} - // 3. Follow the requirements stated step 2 to step 6, inclusive, - // of the last set of steps in section 4.1 of The WebSocket - // Protocol to validate response. This either results in fail - // the WebSocket connection or the WebSocket connection is - // established. +const invalidIsomorphicEncodeValueRegex = /[^\x00-\xFF]/ // eslint-disable-line - // 2. If the response lacks an |Upgrade| header field or the |Upgrade| - // header field contains a value that is not an ASCII case- - // insensitive match for the value "websocket", the client MUST - // _Fail the WebSocket Connection_. - if (response.headersList.get('Upgrade')?.toLowerCase() !== 'websocket') { - failWebsocketConnection(ws, 'Server did not set Upgrade header to "websocket".') - return - } +/** + * @see https://infra.spec.whatwg.org/#isomorphic-encode + * @param {string} input + */ +function isomorphicEncode (input) { + // 1. Assert: input contains no code points greater than U+00FF. + assert(!invalidIsomorphicEncodeValueRegex.test(input)) - // 3. If the response lacks a |Connection| header field or the - // |Connection| header field doesn't contain a token that is an - // ASCII case-insensitive match for the value "Upgrade", the client - // MUST _Fail the WebSocket Connection_. - if (response.headersList.get('Connection')?.toLowerCase() !== 'upgrade') { - failWebsocketConnection(ws, 'Server did not set Connection header to "upgrade".') - return - } + // 2. Return a byte sequence whose length is equal to input’s code + // point length and whose bytes have the same values as the + // values of input’s code points, in the same order + return input +} - // 4. If the response lacks a |Sec-WebSocket-Accept| header field or - // the |Sec-WebSocket-Accept| contains a value other than the - // base64-encoded SHA-1 of the concatenation of the |Sec-WebSocket- - // Key| (as a string, not base64-decoded) with the string "258EAFA5- - // E914-47DA-95CA-C5AB0DC85B11" but ignoring any leading and - // trailing whitespace, the client MUST _Fail the WebSocket - // Connection_. - const secWSAccept = response.headersList.get('Sec-WebSocket-Accept') - const digest = crypto.createHash('sha1').update(keyValue + uid).digest('base64') - if (secWSAccept !== digest) { - failWebsocketConnection(ws, 'Incorrect hash received in Sec-WebSocket-Accept header.') - return - } +/** + * @see https://streams.spec.whatwg.org/#readablestreamdefaultreader-read-all-bytes + * @see https://streams.spec.whatwg.org/#read-loop + * @param {ReadableStreamDefaultReader} reader + */ +async function readAllBytes (reader) { + const bytes = [] + let byteLength = 0 - // 5. If the response includes a |Sec-WebSocket-Extensions| header - // field and this header field indicates the use of an extension - // that was not present in the client's handshake (the server has - // indicated an extension not requested by the client), the client - // MUST _Fail the WebSocket Connection_. (The parsing of this - // header field to determine which extensions are requested is - // discussed in Section 9.1.) - const secExtension = response.headersList.get('Sec-WebSocket-Extensions') + while (true) { + const { done, value: chunk } = await reader.read() - if (secExtension !== null && secExtension !== permessageDeflate) { - failWebsocketConnection(ws, 'Received different permessage-deflate than the one set.') - return - } + if (done) { + // 1. Call successSteps with bytes. + return Buffer.concat(bytes, byteLength) + } - // 6. If the response includes a |Sec-WebSocket-Protocol| header field - // and this header field indicates the use of a subprotocol that was - // not present in the client's handshake (the server has indicated a - // subprotocol not requested by the client), the client MUST _Fail - // the WebSocket Connection_. - const secProtocol = response.headersList.get('Sec-WebSocket-Protocol') + // 1. If chunk is not a Uint8Array object, call failureSteps + // with a TypeError and abort these steps. + if (!isUint8Array(chunk)) { + throw new TypeError('Received non-Uint8Array chunk') + } - if (secProtocol !== null && secProtocol !== request.headersList.get('Sec-WebSocket-Protocol')) { - failWebsocketConnection(ws, 'Protocol was not set in the opening handshake.') - return - } + // 2. Append the bytes represented by chunk to bytes. + bytes.push(chunk) + byteLength += chunk.length - response.socket.on('data', onSocketData) - response.socket.on('close', onSocketClose) - response.socket.on('error', onSocketError) + // 3. Read-loop given reader, bytes, successSteps, and failureSteps. + } +} - if (channels.open.hasSubscribers) { - channels.open.publish({ - address: response.socket.address(), - protocol: secProtocol, - extensions: secExtension - }) - } +/** + * @see https://fetch.spec.whatwg.org/#is-local + * @param {URL} url + */ +function urlIsLocal (url) { + assert('protocol' in url) // ensure it's a url object - onEstablish(response) - } - }) + const protocol = url.protocol - return controller + return protocol === 'about:' || protocol === 'blob:' || protocol === 'data:' } /** - * @param {Buffer} chunk + * @param {string|URL} url + * @returns {boolean} */ -function onSocketData (chunk) { - if (!this.ws[kByteParser].write(chunk)) { - this.pause() - } +function urlHasHttpsScheme (url) { + return ( + ( + typeof url === 'string' && + url[5] === ':' && + url[0] === 'h' && + url[1] === 't' && + url[2] === 't' && + url[3] === 'p' && + url[4] === 's' + ) || + url.protocol === 'https:' + ) } /** - * @see https://websockets.spec.whatwg.org/#feedback-from-the-protocol - * @see https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.4 + * @see https://fetch.spec.whatwg.org/#http-scheme + * @param {URL} url */ -function onSocketClose () { - const { ws } = this +function urlIsHttpHttpsScheme (url) { + assert('protocol' in url) // ensure it's a url object - // If the TCP connection was closed after the - // WebSocket closing handshake was completed, the WebSocket connection - // is said to have been closed _cleanly_. - const wasClean = ws[kSentClose] && ws[kReceivedClose] + const protocol = url.protocol - let code = 1005 - let reason = '' + return protocol === 'http:' || protocol === 'https:' +} - const result = ws[kByteParser].closingInfo +/** + * @see https://fetch.spec.whatwg.org/#simple-range-header-value + * @param {string} value + * @param {boolean} allowWhitespace + */ +function simpleRangeHeaderValue (value, allowWhitespace) { + // 1. Let data be the isomorphic decoding of value. + // Note: isomorphic decoding takes a sequence of bytes (ie. a Uint8Array) and turns it into a string, + // nothing more. We obviously don't need to do that if value is a string already. + const data = value - if (result) { - code = result.code ?? 1005 - reason = result.reason - } else if (!ws[kSentClose]) { - // If _The WebSocket - // Connection is Closed_ and no Close control frame was received by the - // endpoint (such as could occur if the underlying transport connection - // is lost), _The WebSocket Connection Close Code_ is considered to be - // 1006. - code = 1006 + // 2. If data does not start with "bytes", then return failure. + if (!data.startsWith('bytes')) { + return 'failure' } - // 1. Change the ready state to CLOSED (3). - ws[kReadyState] = states.CLOSED - - // 2. If the user agent was required to fail the WebSocket - // connection, or if the WebSocket connection was closed - // after being flagged as full, fire an event named error - // at the WebSocket object. - // TODO - - // 3. Fire an event named close at the WebSocket object, - // using CloseEvent, with the wasClean attribute - // initialized to true if the connection closed cleanly - // and false otherwise, the code attribute initialized to - // the WebSocket connection close code, and the reason - // attribute initialized to the result of applying UTF-8 - // decode without BOM to the WebSocket connection close - // reason. - fireEvent('close', ws, CloseEvent, { - wasClean, code, reason - }) + // 3. Let position be a position variable for data, initially pointing at the 5th code point of data. + const position = { position: 5 } - if (channels.close.hasSubscribers) { - channels.close.publish({ - websocket: ws, - code, - reason - }) + // 4. If allowWhitespace is true, collect a sequence of code points that are HTTP tab or space, + // from data given position. + if (allowWhitespace) { + collectASequenceOfCodePoints( + (char) => char === '\t' || char === ' ', + data, + position + ) } -} -function onSocketError (error) { - const { ws } = this + // 5. If the code point at position within data is not U+003D (=), then return failure. + if (data.charCodeAt(position.position) !== 0x3D) { + return 'failure' + } - ws[kReadyState] = states.CLOSING + // 6. Advance position by 1. + position.position++ - if (channels.socketError.hasSubscribers) { - channels.socketError.publish(error) + // 7. If allowWhitespace is true, collect a sequence of code points that are HTTP tab or space, from + // data given position. + if (allowWhitespace) { + collectASequenceOfCodePoints( + (char) => char === '\t' || char === ' ', + data, + position + ) } - this.destroy() -} - -module.exports = { - establishWebSocketConnection -} + // 8. Let rangeStart be the result of collecting a sequence of code points that are ASCII digits, + // from data given position. + const rangeStart = collectASequenceOfCodePoints( + (char) => { + const code = char.charCodeAt(0) + return code >= 0x30 && code <= 0x39 + }, + data, + position + ) -/***/ }), + // 9. Let rangeStartValue be rangeStart, interpreted as decimal number, if rangeStart is not the + // empty string; otherwise null. + const rangeStartValue = rangeStart.length ? Number(rangeStart) : null -/***/ 3300: -/***/ ((module) => { + // 10. If allowWhitespace is true, collect a sequence of code points that are HTTP tab or space, + // from data given position. + if (allowWhitespace) { + collectASequenceOfCodePoints( + (char) => char === '\t' || char === ' ', + data, + position + ) + } -"use strict"; + // 11. If the code point at position within data is not U+002D (-), then return failure. + if (data.charCodeAt(position.position) !== 0x2D) { + return 'failure' + } + // 12. Advance position by 1. + position.position++ -// This is a Globally Unique Identifier unique used -// to validate that the endpoint accepts websocket -// connections. -// See https://www.rfc-editor.org/rfc/rfc6455.html#section-1.3 -const uid = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11' + // 13. If allowWhitespace is true, collect a sequence of code points that are HTTP tab + // or space, from data given position. + // Note from Khafra: its the same step as in #8 again lol + if (allowWhitespace) { + collectASequenceOfCodePoints( + (char) => char === '\t' || char === ' ', + data, + position + ) + } -/** @type {PropertyDescriptor} */ -const staticPropertyDescriptors = { - enumerable: true, - writable: false, - configurable: false -} + // 14. Let rangeEnd be the result of collecting a sequence of code points that are + // ASCII digits, from data given position. + // Note from Khafra: you wouldn't guess it, but this is also the same step as #8 + const rangeEnd = collectASequenceOfCodePoints( + (char) => { + const code = char.charCodeAt(0) -const states = { - CONNECTING: 0, - OPEN: 1, - CLOSING: 2, - CLOSED: 3 -} + return code >= 0x30 && code <= 0x39 + }, + data, + position + ) -const opcodes = { - CONTINUATION: 0x0, - TEXT: 0x1, - BINARY: 0x2, - CLOSE: 0x8, - PING: 0x9, - PONG: 0xA -} + // 15. Let rangeEndValue be rangeEnd, interpreted as decimal number, if rangeEnd + // is not the empty string; otherwise null. + // Note from Khafra: THE SAME STEP, AGAIN!!! + // Note: why interpret as a decimal if we only collect ascii digits? + const rangeEndValue = rangeEnd.length ? Number(rangeEnd) : null -const maxUnsigned16Bit = 2 ** 16 - 1 // 65535 + // 16. If position is not past the end of data, then return failure. + if (position.position < data.length) { + return 'failure' + } -const parserStates = { - INFO: 0, - PAYLOADLENGTH_16: 2, - PAYLOADLENGTH_64: 3, - READ_DATA: 4 -} + // 17. If rangeEndValue and rangeStartValue are null, then return failure. + if (rangeEndValue === null && rangeStartValue === null) { + return 'failure' + } -const emptyBuffer = Buffer.allocUnsafe(0) + // 18. If rangeStartValue and rangeEndValue are numbers, and rangeStartValue is + // greater than rangeEndValue, then return failure. + // Note: ... when can they not be numbers? + if (rangeStartValue > rangeEndValue) { + return 'failure' + } -module.exports = { - uid, - staticPropertyDescriptors, - states, - opcodes, - maxUnsigned16Bit, - parserStates, - emptyBuffer + // 19. Return (rangeStartValue, rangeEndValue). + return { rangeStartValue, rangeEndValue } } +/** + * @see https://fetch.spec.whatwg.org/#build-a-content-range + * @param {number} rangeStart + * @param {number} rangeEnd + * @param {number} fullLength + */ +function buildContentRange (rangeStart, rangeEnd, fullLength) { + // 1. Let contentRange be `bytes `. + let contentRange = 'bytes ' -/***/ }), + // 2. Append rangeStart, serialized and isomorphic encoded, to contentRange. + contentRange += isomorphicEncode(`${rangeStart}`) -/***/ 896: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // 3. Append 0x2D (-) to contentRange. + contentRange += '-' -"use strict"; + // 4. Append rangeEnd, serialized and isomorphic encoded to contentRange. + contentRange += isomorphicEncode(`${rangeEnd}`) + // 5. Append 0x2F (/) to contentRange. + contentRange += '/' -const { webidl } = __nccwpck_require__(8201) -const { kEnumerableProperty } = __nccwpck_require__(5069) -const { MessagePort } = __nccwpck_require__(8167) + // 6. Append fullLength, serialized and isomorphic encoded to contentRange. + contentRange += isomorphicEncode(`${fullLength}`) -/** - * @see https://html.spec.whatwg.org/multipage/comms.html#messageevent - */ -class MessageEvent extends Event { - #eventInit + // 7. Return contentRange. + return contentRange +} - constructor (type, eventInitDict = {}) { - webidl.argumentLengthCheck(arguments, 1, { header: 'MessageEvent constructor' }) +// A Stream, which pipes the response to zlib.createInflate() or +// zlib.createInflateRaw() depending on the first byte of the Buffer. +// If the lower byte of the first byte is 0x08, then the stream is +// interpreted as a zlib stream, otherwise it's interpreted as a +// raw deflate stream. +class InflateStream extends Transform { + #zlibOptions - type = webidl.converters.DOMString(type) - eventInitDict = webidl.converters.MessageEventInit(eventInitDict) + /** @param {zlib.ZlibOptions} [zlibOptions] */ + constructor (zlibOptions) { + super() + this.#zlibOptions = zlibOptions + } - super(type, eventInitDict) + _transform (chunk, encoding, callback) { + if (!this._inflateStream) { + if (chunk.length === 0) { + callback() + return + } + this._inflateStream = (chunk[0] & 0x0F) === 0x08 + ? zlib.createInflate(this.#zlibOptions) + : zlib.createInflateRaw(this.#zlibOptions) - this.#eventInit = eventInitDict - } + this._inflateStream.on('data', this.push.bind(this)) + this._inflateStream.on('end', () => this.push(null)) + this._inflateStream.on('error', (err) => this.destroy(err)) + } - get data () { - webidl.brandCheck(this, MessageEvent) + this._inflateStream.write(chunk, encoding, callback) + } - return this.#eventInit.data + _final (callback) { + if (this._inflateStream) { + this._inflateStream.end() + this._inflateStream = null + } + callback() } +} - get origin () { - webidl.brandCheck(this, MessageEvent) +/** + * @param {zlib.ZlibOptions} [zlibOptions] + * @returns {InflateStream} + */ +function createInflate (zlibOptions) { + return new InflateStream(zlibOptions) +} - return this.#eventInit.origin - } +/** + * @see https://fetch.spec.whatwg.org/#concept-header-extract-mime-type + * @param {import('./headers').HeadersList} headers + */ +function extractMimeType (headers) { + // 1. Let charset be null. + let charset = null - get lastEventId () { - webidl.brandCheck(this, MessageEvent) + // 2. Let essence be null. + let essence = null - return this.#eventInit.lastEventId - } + // 3. Let mimeType be null. + let mimeType = null - get source () { - webidl.brandCheck(this, MessageEvent) + // 4. Let values be the result of getting, decoding, and splitting `Content-Type` from headers. + const values = getDecodeSplit('content-type', headers) - return this.#eventInit.source + // 5. If values is null, then return failure. + if (values === null) { + return 'failure' } - get ports () { - webidl.brandCheck(this, MessageEvent) + // 6. For each value of values: + for (const value of values) { + // 6.1. Let temporaryMimeType be the result of parsing value. + const temporaryMimeType = parseMIMEType(value) - if (!Object.isFrozen(this.#eventInit.ports)) { - Object.freeze(this.#eventInit.ports) + // 6.2. If temporaryMimeType is failure or its essence is "*/*", then continue. + if (temporaryMimeType === 'failure' || temporaryMimeType.essence === '*/*') { + continue } - return this.#eventInit.ports - } + // 6.3. Set mimeType to temporaryMimeType. + mimeType = temporaryMimeType - initMessageEvent ( - type, - bubbles = false, - cancelable = false, - data = null, - origin = '', - lastEventId = '', - source = null, - ports = [] - ) { - webidl.brandCheck(this, MessageEvent) + // 6.4. If mimeType’s essence is not essence, then: + if (mimeType.essence !== essence) { + // 6.4.1. Set charset to null. + charset = null + + // 6.4.2. If mimeType’s parameters["charset"] exists, then set charset to + // mimeType’s parameters["charset"]. + if (mimeType.parameters.has('charset')) { + charset = mimeType.parameters.get('charset') + } - webidl.argumentLengthCheck(arguments, 1, { header: 'MessageEvent.initMessageEvent' }) + // 6.4.3. Set essence to mimeType’s essence. + essence = mimeType.essence + } else if (!mimeType.parameters.has('charset') && charset !== null) { + // 6.5. Otherwise, if mimeType’s parameters["charset"] does not exist, and + // charset is non-null, set mimeType’s parameters["charset"] to charset. + mimeType.parameters.set('charset', charset) + } + } - return new MessageEvent(type, { - bubbles, cancelable, data, origin, lastEventId, source, ports - }) + // 7. If mimeType is null, then return failure. + if (mimeType == null) { + return 'failure' } + + // 8. Return mimeType. + return mimeType } /** - * @see https://websockets.spec.whatwg.org/#the-closeevent-interface + * @see https://fetch.spec.whatwg.org/#header-value-get-decode-and-split + * @param {string|null} value */ -class CloseEvent extends Event { - #eventInit +function gettingDecodingSplitting (value) { + // 1. Let input be the result of isomorphic decoding value. + const input = value - constructor (type, eventInitDict = {}) { - webidl.argumentLengthCheck(arguments, 1, { header: 'CloseEvent constructor' }) + // 2. Let position be a position variable for input, initially pointing at the start of input. + const position = { position: 0 } - type = webidl.converters.DOMString(type) - eventInitDict = webidl.converters.CloseEventInit(eventInitDict) + // 3. Let values be a list of strings, initially empty. + const values = [] - super(type, eventInitDict) + // 4. Let temporaryValue be the empty string. + let temporaryValue = '' - this.#eventInit = eventInitDict - } + // 5. While position is not past the end of input: + while (position.position < input.length) { + // 5.1. Append the result of collecting a sequence of code points that are not U+0022 (") + // or U+002C (,) from input, given position, to temporaryValue. + temporaryValue += collectASequenceOfCodePoints( + (char) => char !== '"' && char !== ',', + input, + position + ) - get wasClean () { - webidl.brandCheck(this, CloseEvent) + // 5.2. If position is not past the end of input, then: + if (position.position < input.length) { + // 5.2.1. If the code point at position within input is U+0022 ("), then: + if (input.charCodeAt(position.position) === 0x22) { + // 5.2.1.1. Append the result of collecting an HTTP quoted string from input, given position, to temporaryValue. + temporaryValue += collectAnHTTPQuotedString( + input, + position + ) - return this.#eventInit.wasClean - } + // 5.2.1.2. If position is not past the end of input, then continue. + if (position.position < input.length) { + continue + } + } else { + // 5.2.2. Otherwise: - get code () { - webidl.brandCheck(this, CloseEvent) + // 5.2.2.1. Assert: the code point at position within input is U+002C (,). + assert(input.charCodeAt(position.position) === 0x2C) - return this.#eventInit.code - } + // 5.2.2.2. Advance position by 1. + position.position++ + } + } - get reason () { - webidl.brandCheck(this, CloseEvent) + // 5.3. Remove all HTTP tab or space from the start and end of temporaryValue. + temporaryValue = removeChars(temporaryValue, true, true, (char) => char === 0x9 || char === 0x20) - return this.#eventInit.reason + // 5.4. Append temporaryValue to values. + values.push(temporaryValue) + + // 5.6. Set temporaryValue to the empty string. + temporaryValue = '' } + + // 6. Return values. + return values } -// https://html.spec.whatwg.org/multipage/webappapis.html#the-errorevent-interface -class ErrorEvent extends Event { - #eventInit +/** + * @see https://fetch.spec.whatwg.org/#concept-header-list-get-decode-split + * @param {string} name lowercase header name + * @param {import('./headers').HeadersList} list + */ +function getDecodeSplit (name, list) { + // 1. Let value be the result of getting name from list. + const value = list.get(name, true) - constructor (type, eventInitDict) { - webidl.argumentLengthCheck(arguments, 1, { header: 'ErrorEvent constructor' }) + // 2. If value is null, then return null. + if (value === null) { + return null + } - super(type, eventInitDict) + // 3. Return the result of getting, decoding, and splitting value. + return gettingDecodingSplitting(value) +} - type = webidl.converters.DOMString(type) - eventInitDict = webidl.converters.ErrorEventInit(eventInitDict ?? {}) +const textDecoder = new TextDecoder() - this.#eventInit = eventInitDict +/** + * @see https://encoding.spec.whatwg.org/#utf-8-decode + * @param {Buffer} buffer + */ +function utf8DecodeBytes (buffer) { + if (buffer.length === 0) { + return '' } - get message () { - webidl.brandCheck(this, ErrorEvent) + // 1. Let buffer be the result of peeking three bytes from + // ioQueue, converted to a byte sequence. - return this.#eventInit.message + // 2. If buffer is 0xEF 0xBB 0xBF, then read three + // bytes from ioQueue. (Do nothing with those bytes.) + if (buffer[0] === 0xEF && buffer[1] === 0xBB && buffer[2] === 0xBF) { + buffer = buffer.subarray(3) } - get filename () { - webidl.brandCheck(this, ErrorEvent) - - return this.#eventInit.filename - } + // 3. Process a queue with an instance of UTF-8’s + // decoder, ioQueue, output, and "replacement". + const output = textDecoder.decode(buffer) - get lineno () { - webidl.brandCheck(this, ErrorEvent) + // 4. Return output. + return output +} - return this.#eventInit.lineno +class EnvironmentSettingsObjectBase { + get baseUrl () { + return getGlobalOrigin() } - get colno () { - webidl.brandCheck(this, ErrorEvent) - - return this.#eventInit.colno + get origin () { + return this.baseUrl?.origin } - get error () { - webidl.brandCheck(this, ErrorEvent) + policyContainer = makePolicyContainer() +} - return this.#eventInit.error - } +class EnvironmentSettingsObject { + settingsObject = new EnvironmentSettingsObjectBase() } -Object.defineProperties(MessageEvent.prototype, { - [Symbol.toStringTag]: { - value: 'MessageEvent', - configurable: true - }, - data: kEnumerableProperty, - origin: kEnumerableProperty, - lastEventId: kEnumerableProperty, - source: kEnumerableProperty, - ports: kEnumerableProperty, - initMessageEvent: kEnumerableProperty -}) - -Object.defineProperties(CloseEvent.prototype, { - [Symbol.toStringTag]: { - value: 'CloseEvent', - configurable: true - }, - reason: kEnumerableProperty, - code: kEnumerableProperty, - wasClean: kEnumerableProperty -}) - -Object.defineProperties(ErrorEvent.prototype, { - [Symbol.toStringTag]: { - value: 'ErrorEvent', - configurable: true - }, - message: kEnumerableProperty, - filename: kEnumerableProperty, - lineno: kEnumerableProperty, - colno: kEnumerableProperty, - error: kEnumerableProperty -}) - -webidl.converters.MessagePort = webidl.interfaceConverter(MessagePort) - -webidl.converters['sequence'] = webidl.sequenceConverter( - webidl.converters.MessagePort -) - -const eventInit = [ - { - key: 'bubbles', - converter: webidl.converters.boolean, - defaultValue: false - }, - { - key: 'cancelable', - converter: webidl.converters.boolean, - defaultValue: false - }, - { - key: 'composed', - converter: webidl.converters.boolean, - defaultValue: false - } -] - -webidl.converters.MessageEventInit = webidl.dictionaryConverter([ - ...eventInit, - { - key: 'data', - converter: webidl.converters.any, - defaultValue: null - }, - { - key: 'origin', - converter: webidl.converters.USVString, - defaultValue: '' - }, - { - key: 'lastEventId', - converter: webidl.converters.DOMString, - defaultValue: '' - }, - { - key: 'source', - // Node doesn't implement WindowProxy or ServiceWorker, so the only - // valid value for source is a MessagePort. - converter: webidl.nullableConverter(webidl.converters.MessagePort), - defaultValue: null - }, - { - key: 'ports', - converter: webidl.converters['sequence'], - get defaultValue () { - return [] - } - } -]) - -webidl.converters.CloseEventInit = webidl.dictionaryConverter([ - ...eventInit, - { - key: 'wasClean', - converter: webidl.converters.boolean, - defaultValue: false - }, - { - key: 'code', - converter: webidl.converters['unsigned short'], - defaultValue: 0 - }, - { - key: 'reason', - converter: webidl.converters.USVString, - defaultValue: '' - } -]) - -webidl.converters.ErrorEventInit = webidl.dictionaryConverter([ - ...eventInit, - { - key: 'message', - converter: webidl.converters.DOMString, - defaultValue: '' - }, - { - key: 'filename', - converter: webidl.converters.USVString, - defaultValue: '' - }, - { - key: 'lineno', - converter: webidl.converters['unsigned long'], - defaultValue: 0 - }, - { - key: 'colno', - converter: webidl.converters['unsigned long'], - defaultValue: 0 - }, - { - key: 'error', - converter: webidl.converters.any - } -]) +const environmentSettingsObject = new EnvironmentSettingsObject() module.exports = { - MessageEvent, - CloseEvent, - ErrorEvent + isAborted, + isCancelled, + isValidEncodedURL, + createDeferredPromise, + ReadableStreamFrom, + tryUpgradeRequestToAPotentiallyTrustworthyURL, + clampAndCoarsenConnectionTimingInfo, + coarsenedSharedCurrentTime, + determineRequestsReferrer, + makePolicyContainer, + clonePolicyContainer, + appendFetchMetadata, + appendRequestOriginHeader, + TAOCheck, + corsCheck, + crossOriginResourcePolicyCheck, + createOpaqueTimingInfo, + setRequestReferrerPolicyOnRedirect, + isValidHTTPToken, + requestBadPort, + requestCurrentURL, + responseURL, + responseLocationURL, + isBlobLike, + isURLPotentiallyTrustworthy, + isValidReasonPhrase, + sameOrigin, + normalizeMethod, + serializeJavascriptValueToJSONString, + iteratorMixin, + createIterator, + isValidHeaderName, + isValidHeaderValue, + isErrorLike, + fullyReadBody, + bytesMatch, + isReadableStreamLike, + readableStreamClose, + isomorphicEncode, + urlIsLocal, + urlHasHttpsScheme, + urlIsHttpHttpsScheme, + readAllBytes, + simpleRangeHeaderValue, + buildContentRange, + parseMetadata, + createInflate, + extractMimeType, + getDecodeSplit, + utf8DecodeBytes, + environmentSettingsObject } /***/ }), -/***/ 1268: +/***/ 4859: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -const { maxUnsigned16Bit } = __nccwpck_require__(3300) +const { types, inspect } = __nccwpck_require__(7975) +const { markAsUncloneable } = __nccwpck_require__(5919) +const { toUSVString } = __nccwpck_require__(7234) -/** @type {import('crypto')} */ -let crypto -try { - crypto = __nccwpck_require__(6982) -} catch { +/** @type {import('../../../types/webidl').Webidl} */ +const webidl = {} +webidl.converters = {} +webidl.util = {} +webidl.errors = {} +webidl.errors.exception = function (message) { + return new TypeError(`${message.header}: ${message.message}`) } -class WebsocketFrameSend { - /** - * @param {Buffer|undefined} data - */ - constructor (data) { - this.frameData = data - this.maskKey = crypto.randomBytes(4) - } - - createFrame (opcode) { - const bodyLength = this.frameData?.byteLength ?? 0 - - /** @type {number} */ - let payloadLength = bodyLength // 0-125 - let offset = 6 - - if (bodyLength > maxUnsigned16Bit) { - offset += 8 // payload length is next 8 bytes - payloadLength = 127 - } else if (bodyLength > 125) { - offset += 2 // payload length is next 2 bytes - payloadLength = 126 - } - - const buffer = Buffer.allocUnsafe(bodyLength + offset) - - // Clear first 2 bytes, everything else is overwritten - buffer[0] = buffer[1] = 0 - buffer[0] |= 0x80 // FIN - buffer[0] = (buffer[0] & 0xF0) + opcode // opcode +webidl.errors.conversionFailed = function (context) { + const plural = context.types.length === 1 ? '' : ' one of' + const message = + `${context.argument} could not be converted to` + + `${plural}: ${context.types.join(', ')}.` - /*! ws. MIT License. Einar Otto Stangvik */ - buffer[offset - 4] = this.maskKey[0] - buffer[offset - 3] = this.maskKey[1] - buffer[offset - 2] = this.maskKey[2] - buffer[offset - 1] = this.maskKey[3] + return webidl.errors.exception({ + header: context.prefix, + message + }) +} - buffer[1] = payloadLength +webidl.errors.invalidArgument = function (context) { + return webidl.errors.exception({ + header: context.prefix, + message: `"${context.value}" is an invalid ${context.type}.` + }) +} - if (payloadLength === 126) { - buffer.writeUInt16BE(bodyLength, 2) - } else if (payloadLength === 127) { - // Clear extended payload length - buffer[2] = buffer[3] = 0 - buffer.writeUIntBE(bodyLength, 4, 6) +// https://webidl.spec.whatwg.org/#implements +webidl.brandCheck = function (V, I, opts) { + if (opts?.strict !== false) { + if (!(V instanceof I)) { + const err = new TypeError('Illegal invocation') + err.code = 'ERR_INVALID_THIS' // node compat. + throw err } - - buffer[1] |= 0x80 // MASK - - // mask body - for (let i = 0; i < bodyLength; i++) { - buffer[offset + i] = this.frameData[i] ^ this.maskKey[i % 4] + } else { + if (V?.[Symbol.toStringTag] !== I.prototype[Symbol.toStringTag]) { + const err = new TypeError('Illegal invocation') + err.code = 'ERR_INVALID_THIS' // node compat. + throw err } + } +} - return buffer +webidl.argumentLengthCheck = function ({ length }, min, ctx) { + if (length < min) { + throw webidl.errors.exception({ + message: `${min} argument${min !== 1 ? 's' : ''} required, ` + + `but${length ? ' only' : ''} ${length} found.`, + header: ctx + }) } } -module.exports = { - WebsocketFrameSend +webidl.illegalConstructor = function () { + throw webidl.errors.exception({ + header: 'TypeError', + message: 'Illegal constructor' + }) } +// https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values +webidl.util.Type = function (V) { + switch (typeof V) { + case 'undefined': return 'Undefined' + case 'boolean': return 'Boolean' + case 'string': return 'String' + case 'symbol': return 'Symbol' + case 'number': return 'Number' + case 'bigint': return 'BigInt' + case 'function': + case 'object': { + if (V === null) { + return 'Null' + } -/***/ }), + return 'Object' + } + } +} -/***/ 4680: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +webidl.util.markAsUncloneable = markAsUncloneable || (() => {}) +// https://webidl.spec.whatwg.org/#abstract-opdef-converttoint +webidl.util.ConvertToInt = function (V, bitLength, signedness, opts) { + let upperBound + let lowerBound -"use strict"; + // 1. If bitLength is 64, then: + if (bitLength === 64) { + // 1. Let upperBound be 2^53 − 1. + upperBound = Math.pow(2, 53) - 1 + // 2. If signedness is "unsigned", then let lowerBound be 0. + if (signedness === 'unsigned') { + lowerBound = 0 + } else { + // 3. Otherwise let lowerBound be −2^53 + 1. + lowerBound = Math.pow(-2, 53) + 1 + } + } else if (signedness === 'unsigned') { + // 2. Otherwise, if signedness is "unsigned", then: -const { Writable } = __nccwpck_require__(2203) -const diagnosticsChannel = __nccwpck_require__(1637) -const { parserStates, opcodes, states, emptyBuffer } = __nccwpck_require__(3300) -const { kReadyState, kSentClose, kResponse, kReceivedClose } = __nccwpck_require__(7652) -const { isValidStatusCode, failWebsocketConnection, websocketMessageReceived } = __nccwpck_require__(5117) -const { WebsocketFrameSend } = __nccwpck_require__(1268) + // 1. Let lowerBound be 0. + lowerBound = 0 -// This code was influenced by ws released under the MIT license. -// Copyright (c) 2011 Einar Otto Stangvik -// Copyright (c) 2013 Arnout Kazemier and contributors -// Copyright (c) 2016 Luigi Pinca and contributors + // 2. Let upperBound be 2^bitLength − 1. + upperBound = Math.pow(2, bitLength) - 1 + } else { + // 3. Otherwise: -const channels = {} -channels.ping = diagnosticsChannel.channel('undici:websocket:ping') -channels.pong = diagnosticsChannel.channel('undici:websocket:pong') + // 1. Let lowerBound be -2^bitLength − 1. + lowerBound = Math.pow(-2, bitLength) - 1 -class ByteParser extends Writable { - #buffers = [] - #byteOffset = 0 + // 2. Let upperBound be 2^bitLength − 1 − 1. + upperBound = Math.pow(2, bitLength - 1) - 1 + } - #state = parserStates.INFO + // 4. Let x be ? ToNumber(V). + let x = Number(V) - #info = {} - #fragments = [] + // 5. If x is −0, then set x to +0. + if (x === 0) { + x = 0 + } - constructor (ws) { - super() + // 6. If the conversion is to an IDL type associated + // with the [EnforceRange] extended attribute, then: + if (opts?.enforceRange === true) { + // 1. If x is NaN, +∞, or −∞, then throw a TypeError. + if ( + Number.isNaN(x) || + x === Number.POSITIVE_INFINITY || + x === Number.NEGATIVE_INFINITY + ) { + throw webidl.errors.exception({ + header: 'Integer conversion', + message: `Could not convert ${webidl.util.Stringify(V)} to an integer.` + }) + } - this.ws = ws - } + // 2. Set x to IntegerPart(x). + x = webidl.util.IntegerPart(x) - /** - * @param {Buffer} chunk - * @param {() => void} callback - */ - _write (chunk, _, callback) { - this.#buffers.push(chunk) - this.#byteOffset += chunk.length + // 3. If x < lowerBound or x > upperBound, then + // throw a TypeError. + if (x < lowerBound || x > upperBound) { + throw webidl.errors.exception({ + header: 'Integer conversion', + message: `Value must be between ${lowerBound}-${upperBound}, got ${x}.` + }) + } - this.run(callback) + // 4. Return x. + return x } - /** - * Runs whenever a new chunk is received. - * Callback is called whenever there are no more chunks buffering, - * or not enough bytes are buffered to parse. - */ - run (callback) { - while (true) { - if (this.#state === parserStates.INFO) { - // If there aren't enough bytes to parse the payload length, etc. - if (this.#byteOffset < 2) { - return callback() - } + // 7. If x is not NaN and the conversion is to an IDL + // type associated with the [Clamp] extended + // attribute, then: + if (!Number.isNaN(x) && opts?.clamp === true) { + // 1. Set x to min(max(x, lowerBound), upperBound). + x = Math.min(Math.max(x, lowerBound), upperBound) - const buffer = this.consume(2) + // 2. Round x to the nearest integer, choosing the + // even integer if it lies halfway between two, + // and choosing +0 rather than −0. + if (Math.floor(x) % 2 === 0) { + x = Math.floor(x) + } else { + x = Math.ceil(x) + } - this.#info.fin = (buffer[0] & 0x80) !== 0 - this.#info.opcode = buffer[0] & 0x0F + // 3. Return x. + return x + } - // If we receive a fragmented message, we use the type of the first - // frame to parse the full message as binary/text, when it's terminated - this.#info.originalOpcode ??= this.#info.opcode + // 8. If x is NaN, +0, +∞, or −∞, then return +0. + if ( + Number.isNaN(x) || + (x === 0 && Object.is(0, x)) || + x === Number.POSITIVE_INFINITY || + x === Number.NEGATIVE_INFINITY + ) { + return 0 + } - this.#info.fragmented = !this.#info.fin && this.#info.opcode !== opcodes.CONTINUATION + // 9. Set x to IntegerPart(x). + x = webidl.util.IntegerPart(x) - if (this.#info.fragmented && this.#info.opcode !== opcodes.BINARY && this.#info.opcode !== opcodes.TEXT) { - // Only text and binary frames can be fragmented - failWebsocketConnection(this.ws, 'Invalid frame type was fragmented.') - return - } + // 10. Set x to x modulo 2^bitLength. + x = x % Math.pow(2, bitLength) - const payloadLength = buffer[1] & 0x7F + // 11. If signedness is "signed" and x ≥ 2^bitLength − 1, + // then return x − 2^bitLength. + if (signedness === 'signed' && x >= Math.pow(2, bitLength) - 1) { + return x - Math.pow(2, bitLength) + } - if (payloadLength <= 125) { - this.#info.payloadLength = payloadLength - this.#state = parserStates.READ_DATA - } else if (payloadLength === 126) { - this.#state = parserStates.PAYLOADLENGTH_16 - } else if (payloadLength === 127) { - this.#state = parserStates.PAYLOADLENGTH_64 - } + // 12. Otherwise, return x. + return x +} - if (this.#info.fragmented && payloadLength > 125) { - // A fragmented frame can't be fragmented itself - failWebsocketConnection(this.ws, 'Fragmented frame exceeded 125 bytes.') - return - } else if ( - (this.#info.opcode === opcodes.PING || - this.#info.opcode === opcodes.PONG || - this.#info.opcode === opcodes.CLOSE) && - payloadLength > 125 - ) { - // Control frames can have a payload length of 125 bytes MAX - failWebsocketConnection(this.ws, 'Payload length for control frame exceeded 125 bytes.') - return - } else if (this.#info.opcode === opcodes.CLOSE) { - if (payloadLength === 1) { - failWebsocketConnection(this.ws, 'Received close frame with a 1-byte body.') - return - } +// https://webidl.spec.whatwg.org/#abstract-opdef-integerpart +webidl.util.IntegerPart = function (n) { + // 1. Let r be floor(abs(n)). + const r = Math.floor(Math.abs(n)) - const body = this.consume(payloadLength) + // 2. If n < 0, then return -1 × r. + if (n < 0) { + return -1 * r + } - this.#info.closeInfo = this.parseCloseBody(false, body) + // 3. Otherwise, return r. + return r +} - if (!this.ws[kSentClose]) { - // If an endpoint receives a Close frame and did not previously send a - // Close frame, the endpoint MUST send a Close frame in response. (When - // sending a Close frame in response, the endpoint typically echos the - // status code it received.) - const body = Buffer.allocUnsafe(2) - body.writeUInt16BE(this.#info.closeInfo.code, 0) - const closeFrame = new WebsocketFrameSend(body) +webidl.util.Stringify = function (V) { + const type = webidl.util.Type(V) - this.ws[kResponse].socket.write( - closeFrame.createFrame(opcodes.CLOSE), - (err) => { - if (!err) { - this.ws[kSentClose] = true - } - } - ) - } + switch (type) { + case 'Symbol': + return `Symbol(${V.description})` + case 'Object': + return inspect(V) + case 'String': + return `"${V}"` + default: + return `${V}` + } +} - // Upon either sending or receiving a Close control frame, it is said - // that _The WebSocket Closing Handshake is Started_ and that the - // WebSocket connection is in the CLOSING state. - this.ws[kReadyState] = states.CLOSING - this.ws[kReceivedClose] = true +// https://webidl.spec.whatwg.org/#es-sequence +webidl.sequenceConverter = function (converter) { + return (V, prefix, argument, Iterable) => { + // 1. If Type(V) is not Object, throw a TypeError. + if (webidl.util.Type(V) !== 'Object') { + throw webidl.errors.exception({ + header: prefix, + message: `${argument} (${webidl.util.Stringify(V)}) is not iterable.` + }) + } - this.end() + // 2. Let method be ? GetMethod(V, @@iterator). + /** @type {Generator} */ + const method = typeof Iterable === 'function' ? Iterable() : V?.[Symbol.iterator]?.() + const seq = [] + let index = 0 - return - } else if (this.#info.opcode === opcodes.PING) { - // Upon receipt of a Ping frame, an endpoint MUST send a Pong frame in - // response, unless it already received a Close frame. - // A Pong frame sent in response to a Ping frame must have identical - // "Application data" + // 3. If method is undefined, throw a TypeError. + if ( + method === undefined || + typeof method.next !== 'function' + ) { + throw webidl.errors.exception({ + header: prefix, + message: `${argument} is not iterable.` + }) + } - const body = this.consume(payloadLength) + // https://webidl.spec.whatwg.org/#create-sequence-from-iterable + while (true) { + const { done, value } = method.next() - if (!this.ws[kReceivedClose]) { - const frame = new WebsocketFrameSend(body) + if (done) { + break + } - this.ws[kResponse].socket.write(frame.createFrame(opcodes.PONG)) + seq.push(converter(value, prefix, `${argument}[${index++}]`)) + } - if (channels.ping.hasSubscribers) { - channels.ping.publish({ - payload: body - }) - } - } + return seq + } +} - this.#state = parserStates.INFO +// https://webidl.spec.whatwg.org/#es-to-record +webidl.recordConverter = function (keyConverter, valueConverter) { + return (O, prefix, argument) => { + // 1. If Type(O) is not Object, throw a TypeError. + if (webidl.util.Type(O) !== 'Object') { + throw webidl.errors.exception({ + header: prefix, + message: `${argument} ("${webidl.util.Type(O)}") is not an Object.` + }) + } - if (this.#byteOffset > 0) { - continue - } else { - callback() - return - } - } else if (this.#info.opcode === opcodes.PONG) { - // A Pong frame MAY be sent unsolicited. This serves as a - // unidirectional heartbeat. A response to an unsolicited Pong frame is - // not expected. + // 2. Let result be a new empty instance of record. + const result = {} - const body = this.consume(payloadLength) + if (!types.isProxy(O)) { + // 1. Let desc be ? O.[[GetOwnProperty]](key). + const keys = [...Object.getOwnPropertyNames(O), ...Object.getOwnPropertySymbols(O)] - if (channels.pong.hasSubscribers) { - channels.pong.publish({ - payload: body - }) - } + for (const key of keys) { + // 1. Let typedKey be key converted to an IDL value of type K. + const typedKey = keyConverter(key, prefix, argument) - if (this.#byteOffset > 0) { - continue - } else { - callback() - return - } - } - } else if (this.#state === parserStates.PAYLOADLENGTH_16) { - if (this.#byteOffset < 2) { - return callback() - } - - const buffer = this.consume(2) - - this.#info.payloadLength = buffer.readUInt16BE(0) - this.#state = parserStates.READ_DATA - } else if (this.#state === parserStates.PAYLOADLENGTH_64) { - if (this.#byteOffset < 8) { - return callback() - } - - const buffer = this.consume(8) - const upper = buffer.readUInt32BE(0) - - // 2^31 is the maxinimum bytes an arraybuffer can contain - // on 32-bit systems. Although, on 64-bit systems, this is - // 2^53-1 bytes. - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Invalid_array_length - // https://source.chromium.org/chromium/chromium/src/+/main:v8/src/common/globals.h;drc=1946212ac0100668f14eb9e2843bdd846e510a1e;bpv=1;bpt=1;l=1275 - // https://source.chromium.org/chromium/chromium/src/+/main:v8/src/objects/js-array-buffer.h;l=34;drc=1946212ac0100668f14eb9e2843bdd846e510a1e - if (upper > 2 ** 31 - 1) { - failWebsocketConnection(this.ws, 'Received payload length > 2^31 bytes.') - return - } - - const lower = buffer.readUInt32BE(4) - - this.#info.payloadLength = (upper << 8) + lower - this.#state = parserStates.READ_DATA - } else if (this.#state === parserStates.READ_DATA) { - if (this.#byteOffset < this.#info.payloadLength) { - // If there is still more data in this chunk that needs to be read - return callback() - } else if (this.#byteOffset >= this.#info.payloadLength) { - // If the server sent multiple frames in a single chunk + // 2. Let value be ? Get(O, key). + // 3. Let typedValue be value converted to an IDL value of type V. + const typedValue = valueConverter(O[key], prefix, argument) - const body = this.consume(this.#info.payloadLength) + // 4. Set result[typedKey] to typedValue. + result[typedKey] = typedValue + } - this.#fragments.push(body) + // 5. Return result. + return result + } - // If the frame is unfragmented, or a fragmented frame was terminated, - // a message was received - if (!this.#info.fragmented || (this.#info.fin && this.#info.opcode === opcodes.CONTINUATION)) { - const fullMessage = Buffer.concat(this.#fragments) + // 3. Let keys be ? O.[[OwnPropertyKeys]](). + const keys = Reflect.ownKeys(O) - websocketMessageReceived(this.ws, this.#info.originalOpcode, fullMessage) + // 4. For each key of keys. + for (const key of keys) { + // 1. Let desc be ? O.[[GetOwnProperty]](key). + const desc = Reflect.getOwnPropertyDescriptor(O, key) - this.#info = {} - this.#fragments.length = 0 - } + // 2. If desc is not undefined and desc.[[Enumerable]] is true: + if (desc?.enumerable) { + // 1. Let typedKey be key converted to an IDL value of type K. + const typedKey = keyConverter(key, prefix, argument) - this.#state = parserStates.INFO - } - } + // 2. Let value be ? Get(O, key). + // 3. Let typedValue be value converted to an IDL value of type V. + const typedValue = valueConverter(O[key], prefix, argument) - if (this.#byteOffset > 0) { - continue - } else { - callback() - break + // 4. Set result[typedKey] to typedValue. + result[typedKey] = typedValue } } - } - /** - * Take n bytes from the buffered Buffers - * @param {number} n - * @returns {Buffer|null} - */ - consume (n) { - if (n > this.#byteOffset) { - return null - } else if (n === 0) { - return emptyBuffer - } + // 5. Return result. + return result + } +} - if (this.#buffers[0].length === n) { - this.#byteOffset -= this.#buffers[0].length - return this.#buffers.shift() +webidl.interfaceConverter = function (i) { + return (V, prefix, argument, opts) => { + if (opts?.strict !== false && !(V instanceof i)) { + throw webidl.errors.exception({ + header: prefix, + message: `Expected ${argument} ("${webidl.util.Stringify(V)}") to be an instance of ${i.name}.` + }) } - const buffer = Buffer.allocUnsafe(n) - let offset = 0 + return V + } +} - while (offset !== n) { - const next = this.#buffers[0] - const { length } = next +webidl.dictionaryConverter = function (converters) { + return (dictionary, prefix, argument) => { + const type = webidl.util.Type(dictionary) + const dict = {} - if (length + offset === n) { - buffer.set(this.#buffers.shift(), offset) - break - } else if (length + offset > n) { - buffer.set(next.subarray(0, n - offset), offset) - this.#buffers[0] = next.subarray(n - offset) - break - } else { - buffer.set(this.#buffers.shift(), offset) - offset += next.length - } + if (type === 'Null' || type === 'Undefined') { + return dict + } else if (type !== 'Object') { + throw webidl.errors.exception({ + header: prefix, + message: `Expected ${dictionary} to be one of: Null, Undefined, Object.` + }) } - this.#byteOffset -= n - - return buffer - } + for (const options of converters) { + const { key, defaultValue, required, converter } = options - parseCloseBody (onlyCode, data) { - // https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.5 - /** @type {number|undefined} */ - let code + if (required === true) { + if (!Object.hasOwn(dictionary, key)) { + throw webidl.errors.exception({ + header: prefix, + message: `Missing required key "${key}".` + }) + } + } - if (data.length >= 2) { - // _The WebSocket Connection Close Code_ is - // defined as the status code (Section 7.4) contained in the first Close - // control frame received by the application - code = data.readUInt16BE(0) - } + let value = dictionary[key] + const hasDefault = Object.hasOwn(options, 'defaultValue') - if (onlyCode) { - if (!isValidStatusCode(code)) { - return null + // Only use defaultValue if value is undefined and + // a defaultValue options was provided. + if (hasDefault && value !== null) { + value ??= defaultValue() } - return { code } - } + // A key can be optional and have no default value. + // When this happens, do not perform a conversion, + // and do not assign the key a value. + if (required || hasDefault || value !== undefined) { + value = converter(value, prefix, `${argument}.${key}`) - // https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.6 - /** @type {Buffer} */ - let reason = data.subarray(2) + if ( + options.allowedValues && + !options.allowedValues.includes(value) + ) { + throw webidl.errors.exception({ + header: prefix, + message: `${value} is not an accepted type. Expected one of ${options.allowedValues.join(', ')}.` + }) + } - // Remove BOM - if (reason[0] === 0xEF && reason[1] === 0xBB && reason[2] === 0xBF) { - reason = reason.subarray(3) + dict[key] = value + } } - if (code !== undefined && !isValidStatusCode(code)) { - return null - } + return dict + } +} - try { - // TODO: optimize this - reason = new TextDecoder('utf-8', { fatal: true }).decode(reason) - } catch { - return null +webidl.nullableConverter = function (converter) { + return (V, prefix, argument) => { + if (V === null) { + return V } - return { code, reason } - } - - get closingInfo () { - return this.#info.closeInfo + return converter(V, prefix, argument) } } -module.exports = { - ByteParser -} - +// https://webidl.spec.whatwg.org/#es-DOMString +webidl.converters.DOMString = function (V, prefix, argument, opts) { + // 1. If V is null and the conversion is to an IDL type + // associated with the [LegacyNullToEmptyString] + // extended attribute, then return the DOMString value + // that represents the empty string. + if (V === null && opts?.legacyNullToEmptyString) { + return '' + } -/***/ }), + // 2. Let x be ? ToString(V). + if (typeof V === 'symbol') { + throw webidl.errors.exception({ + header: prefix, + message: `${argument} is a symbol, which cannot be converted to a DOMString.` + }) + } -/***/ 7652: -/***/ ((module) => { + // 3. Return the IDL DOMString value that represents the + // same sequence of code units as the one the + // ECMAScript String value x represents. + return String(V) +} -"use strict"; +// https://webidl.spec.whatwg.org/#es-ByteString +webidl.converters.ByteString = function (V, prefix, argument) { + // 1. Let x be ? ToString(V). + // Note: DOMString converter perform ? ToString(V) + const x = webidl.converters.DOMString(V, prefix, argument) + // 2. If the value of any element of x is greater than + // 255, then throw a TypeError. + for (let index = 0; index < x.length; index++) { + if (x.charCodeAt(index) > 255) { + throw new TypeError( + 'Cannot convert argument to a ByteString because the character at ' + + `index ${index} has a value of ${x.charCodeAt(index)} which is greater than 255.` + ) + } + } -module.exports = { - kWebSocketURL: Symbol('url'), - kReadyState: Symbol('ready state'), - kController: Symbol('controller'), - kResponse: Symbol('response'), - kBinaryType: Symbol('binary type'), - kSentClose: Symbol('sent close'), - kReceivedClose: Symbol('received close'), - kByteParser: Symbol('byte parser') + // 3. Return an IDL ByteString value whose length is the + // length of x, and where the value of each element is + // the value of the corresponding element of x. + return x } +// https://webidl.spec.whatwg.org/#es-USVString +// TODO: rewrite this so we can control the errors thrown +webidl.converters.USVString = toUSVString -/***/ }), - -/***/ 5117: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -"use strict"; +// https://webidl.spec.whatwg.org/#es-boolean +webidl.converters.boolean = function (V) { + // 1. Let x be the result of computing ToBoolean(V). + const x = Boolean(V) + // 2. Return the IDL boolean value that is the one that represents + // the same truth value as the ECMAScript Boolean value x. + return x +} -const { kReadyState, kController, kResponse, kBinaryType, kWebSocketURL } = __nccwpck_require__(7652) -const { states, opcodes } = __nccwpck_require__(3300) -const { MessageEvent, ErrorEvent } = __nccwpck_require__(896) +// https://webidl.spec.whatwg.org/#es-any +webidl.converters.any = function (V) { + return V +} -/* globals Blob */ +// https://webidl.spec.whatwg.org/#es-long-long +webidl.converters['long long'] = function (V, prefix, argument) { + // 1. Let x be ? ConvertToInt(V, 64, "signed"). + const x = webidl.util.ConvertToInt(V, 64, 'signed', undefined, prefix, argument) -/** - * @param {import('./websocket').WebSocket} ws - */ -function isEstablished (ws) { - // If the server's response is validated as provided for above, it is - // said that _The WebSocket Connection is Established_ and that the - // WebSocket Connection is in the OPEN state. - return ws[kReadyState] === states.OPEN + // 2. Return the IDL long long value that represents + // the same numeric value as x. + return x } -/** - * @param {import('./websocket').WebSocket} ws - */ -function isClosing (ws) { - // Upon either sending or receiving a Close control frame, it is said - // that _The WebSocket Closing Handshake is Started_ and that the - // WebSocket connection is in the CLOSING state. - return ws[kReadyState] === states.CLOSING -} +// https://webidl.spec.whatwg.org/#es-unsigned-long-long +webidl.converters['unsigned long long'] = function (V, prefix, argument) { + // 1. Let x be ? ConvertToInt(V, 64, "unsigned"). + const x = webidl.util.ConvertToInt(V, 64, 'unsigned', undefined, prefix, argument) -/** - * @param {import('./websocket').WebSocket} ws - */ -function isClosed (ws) { - return ws[kReadyState] === states.CLOSED + // 2. Return the IDL unsigned long long value that + // represents the same numeric value as x. + return x } -/** - * @see https://dom.spec.whatwg.org/#concept-event-fire - * @param {string} e - * @param {EventTarget} target - * @param {EventInit | undefined} eventInitDict - */ -function fireEvent (e, target, eventConstructor = Event, eventInitDict) { - // 1. If eventConstructor is not given, then let eventConstructor be Event. +// https://webidl.spec.whatwg.org/#es-unsigned-long +webidl.converters['unsigned long'] = function (V, prefix, argument) { + // 1. Let x be ? ConvertToInt(V, 32, "unsigned"). + const x = webidl.util.ConvertToInt(V, 32, 'unsigned', undefined, prefix, argument) - // 2. Let event be the result of creating an event given eventConstructor, - // in the relevant realm of target. - // 3. Initialize event’s type attribute to e. - const event = new eventConstructor(e, eventInitDict) // eslint-disable-line new-cap + // 2. Return the IDL unsigned long value that + // represents the same numeric value as x. + return x +} - // 4. Initialize any other IDL attributes of event as described in the - // invocation of this algorithm. +// https://webidl.spec.whatwg.org/#es-unsigned-short +webidl.converters['unsigned short'] = function (V, prefix, argument, opts) { + // 1. Let x be ? ConvertToInt(V, 16, "unsigned"). + const x = webidl.util.ConvertToInt(V, 16, 'unsigned', opts, prefix, argument) - // 5. Return the result of dispatching event at target, with legacy target - // override flag set if set. - target.dispatchEvent(event) + // 2. Return the IDL unsigned short value that represents + // the same numeric value as x. + return x } -/** - * @see https://websockets.spec.whatwg.org/#feedback-from-the-protocol - * @param {import('./websocket').WebSocket} ws - * @param {number} type Opcode - * @param {Buffer} data application data - */ -function websocketMessageReceived (ws, type, data) { - // 1. If ready state is not OPEN (1), then return. - if (ws[kReadyState] !== states.OPEN) { - return +// https://webidl.spec.whatwg.org/#idl-ArrayBuffer +webidl.converters.ArrayBuffer = function (V, prefix, argument, opts) { + // 1. If Type(V) is not Object, or V does not have an + // [[ArrayBufferData]] internal slot, then throw a + // TypeError. + // see: https://tc39.es/ecma262/#sec-properties-of-the-arraybuffer-instances + // see: https://tc39.es/ecma262/#sec-properties-of-the-sharedarraybuffer-instances + if ( + webidl.util.Type(V) !== 'Object' || + !types.isAnyArrayBuffer(V) + ) { + throw webidl.errors.conversionFailed({ + prefix, + argument: `${argument} ("${webidl.util.Stringify(V)}")`, + types: ['ArrayBuffer'] + }) } - // 2. Let dataForEvent be determined by switching on type and binary type: - let dataForEvent + // 2. If the conversion is not to an IDL type associated + // with the [AllowShared] extended attribute, and + // IsSharedArrayBuffer(V) is true, then throw a + // TypeError. + if (opts?.allowShared === false && types.isSharedArrayBuffer(V)) { + throw webidl.errors.exception({ + header: 'ArrayBuffer', + message: 'SharedArrayBuffer is not allowed.' + }) + } - if (type === opcodes.TEXT) { - // -> type indicates that the data is Text - // a new DOMString containing data - try { - dataForEvent = new TextDecoder('utf-8', { fatal: true }).decode(data) - } catch { - failWebsocketConnection(ws, 'Received invalid UTF-8 in text frame.') - return - } - } else if (type === opcodes.BINARY) { - if (ws[kBinaryType] === 'blob') { - // -> type indicates that the data is Binary and binary type is "blob" - // a new Blob object, created in the relevant Realm of the WebSocket - // object, that represents data as its raw data - dataForEvent = new Blob([data]) - } else { - // -> type indicates that the data is Binary and binary type is "arraybuffer" - // a new ArrayBuffer object, created in the relevant Realm of the - // WebSocket object, whose contents are data - dataForEvent = new Uint8Array(data).buffer - } + // 3. If the conversion is not to an IDL type associated + // with the [AllowResizable] extended attribute, and + // IsResizableArrayBuffer(V) is true, then throw a + // TypeError. + if (V.resizable || V.growable) { + throw webidl.errors.exception({ + header: 'ArrayBuffer', + message: 'Received a resizable ArrayBuffer.' + }) } - // 3. Fire an event named message at the WebSocket object, using MessageEvent, - // with the origin attribute initialized to the serialization of the WebSocket - // object’s url's origin, and the data attribute initialized to dataForEvent. - fireEvent('message', ws, MessageEvent, { - origin: ws[kWebSocketURL].origin, - data: dataForEvent - }) + // 4. Return the IDL ArrayBuffer value that is a + // reference to the same object as V. + return V } -/** - * @see https://datatracker.ietf.org/doc/html/rfc6455 - * @see https://datatracker.ietf.org/doc/html/rfc2616 - * @see https://bugs.chromium.org/p/chromium/issues/detail?id=398407 - * @param {string} protocol - */ -function isValidSubprotocol (protocol) { - // If present, this value indicates one - // or more comma-separated subprotocol the client wishes to speak, - // ordered by preference. The elements that comprise this value - // MUST be non-empty strings with characters in the range U+0021 to - // U+007E not including separator characters as defined in - // [RFC2616] and MUST all be unique strings. - if (protocol.length === 0) { - return false - } - - for (const char of protocol) { - const code = char.charCodeAt(0) +webidl.converters.TypedArray = function (V, T, prefix, name, opts) { + // 1. Let T be the IDL type V is being converted to. - if ( - code < 0x21 || - code > 0x7E || - char === '(' || - char === ')' || - char === '<' || - char === '>' || - char === '@' || - char === ',' || - char === ';' || - char === ':' || - char === '\\' || - char === '"' || - char === '/' || - char === '[' || - char === ']' || - char === '?' || - char === '=' || - char === '{' || - char === '}' || - code === 32 || // SP - code === 9 // HT - ) { - return false - } + // 2. If Type(V) is not Object, or V does not have a + // [[TypedArrayName]] internal slot with a value + // equal to T’s name, then throw a TypeError. + if ( + webidl.util.Type(V) !== 'Object' || + !types.isTypedArray(V) || + V.constructor.name !== T.name + ) { + throw webidl.errors.conversionFailed({ + prefix, + argument: `${name} ("${webidl.util.Stringify(V)}")`, + types: [T.name] + }) } - return true -} + // 3. If the conversion is not to an IDL type associated + // with the [AllowShared] extended attribute, and + // IsSharedArrayBuffer(V.[[ViewedArrayBuffer]]) is + // true, then throw a TypeError. + if (opts?.allowShared === false && types.isSharedArrayBuffer(V.buffer)) { + throw webidl.errors.exception({ + header: 'ArrayBuffer', + message: 'SharedArrayBuffer is not allowed.' + }) + } -/** - * @see https://datatracker.ietf.org/doc/html/rfc6455#section-7-4 - * @param {number} code - */ -function isValidStatusCode (code) { - if (code >= 1000 && code < 1015) { - return ( - code !== 1004 && // reserved - code !== 1005 && // "MUST NOT be set as a status code" - code !== 1006 // "MUST NOT be set as a status code" - ) + // 4. If the conversion is not to an IDL type associated + // with the [AllowResizable] extended attribute, and + // IsResizableArrayBuffer(V.[[ViewedArrayBuffer]]) is + // true, then throw a TypeError. + if (V.buffer.resizable || V.buffer.growable) { + throw webidl.errors.exception({ + header: 'ArrayBuffer', + message: 'Received a resizable ArrayBuffer.' + }) } - return code >= 3000 && code <= 4999 + // 5. Return the IDL value of type T that is a reference + // to the same object as V. + return V } -/** - * @param {import('./websocket').WebSocket} ws - * @param {string|undefined} reason - */ -function failWebsocketConnection (ws, reason) { - const { [kController]: controller, [kResponse]: response } = ws - - controller.abort() +webidl.converters.DataView = function (V, prefix, name, opts) { + // 1. If Type(V) is not Object, or V does not have a + // [[DataView]] internal slot, then throw a TypeError. + if (webidl.util.Type(V) !== 'Object' || !types.isDataView(V)) { + throw webidl.errors.exception({ + header: prefix, + message: `${name} is not a DataView.` + }) + } - if (response?.socket && !response.socket.destroyed) { - response.socket.destroy() + // 2. If the conversion is not to an IDL type associated + // with the [AllowShared] extended attribute, and + // IsSharedArrayBuffer(V.[[ViewedArrayBuffer]]) is true, + // then throw a TypeError. + if (opts?.allowShared === false && types.isSharedArrayBuffer(V.buffer)) { + throw webidl.errors.exception({ + header: 'ArrayBuffer', + message: 'SharedArrayBuffer is not allowed.' + }) } - if (reason) { - fireEvent('error', ws, ErrorEvent, { - error: new Error(reason) + // 3. If the conversion is not to an IDL type associated + // with the [AllowResizable] extended attribute, and + // IsResizableArrayBuffer(V.[[ViewedArrayBuffer]]) is + // true, then throw a TypeError. + if (V.buffer.resizable || V.buffer.growable) { + throw webidl.errors.exception({ + header: 'ArrayBuffer', + message: 'Received a resizable ArrayBuffer.' }) } -} -module.exports = { - isEstablished, - isClosing, - isClosed, - fireEvent, - isValidSubprotocol, - isValidStatusCode, - failWebsocketConnection, - websocketMessageReceived + // 4. Return the IDL DataView value that is a reference + // to the same object as V. + return V } +// https://webidl.spec.whatwg.org/#BufferSource +webidl.converters.BufferSource = function (V, prefix, name, opts) { + if (types.isAnyArrayBuffer(V)) { + return webidl.converters.ArrayBuffer(V, prefix, name, { ...opts, allowShared: false }) + } -/***/ }), + if (types.isTypedArray(V)) { + return webidl.converters.TypedArray(V, V.constructor, prefix, name, { ...opts, allowShared: false }) + } -/***/ 5778: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + if (types.isDataView(V)) { + return webidl.converters.DataView(V, prefix, name, { ...opts, allowShared: false }) + } -"use strict"; + throw webidl.errors.conversionFailed({ + prefix, + argument: `${name} ("${webidl.util.Stringify(V)}")`, + types: ['BufferSource'] + }) +} +webidl.converters['sequence'] = webidl.sequenceConverter( + webidl.converters.ByteString +) -const { webidl } = __nccwpck_require__(8201) -const { DOMException } = __nccwpck_require__(3283) -const { URLSerializer } = __nccwpck_require__(4955) -const { getGlobalOrigin } = __nccwpck_require__(4407) -const { staticPropertyDescriptors, states, opcodes, emptyBuffer } = __nccwpck_require__(3300) -const { - kWebSocketURL, - kReadyState, - kController, - kBinaryType, - kResponse, - kSentClose, - kByteParser -} = __nccwpck_require__(7652) -const { isEstablished, isClosing, isValidSubprotocol, failWebsocketConnection, fireEvent } = __nccwpck_require__(5117) -const { establishWebSocketConnection } = __nccwpck_require__(3549) -const { WebsocketFrameSend } = __nccwpck_require__(1268) -const { ByteParser } = __nccwpck_require__(4680) -const { kEnumerableProperty, isBlobLike } = __nccwpck_require__(5069) -const { getGlobalDispatcher } = __nccwpck_require__(5334) -const { types } = __nccwpck_require__(9023) +webidl.converters['sequence>'] = webidl.sequenceConverter( + webidl.converters['sequence'] +) -let experimentalWarned = false +webidl.converters['record'] = webidl.recordConverter( + webidl.converters.ByteString, + webidl.converters.ByteString +) -// https://websockets.spec.whatwg.org/#interface-definition -class WebSocket extends EventTarget { - #events = { - open: null, - error: null, - close: null, - message: null - } +module.exports = { + webidl +} - #bufferedAmount = 0 - #protocol = '' - #extensions = '' - /** - * @param {string} url - * @param {string|string[]} protocols - */ - constructor (url, protocols = []) { - super() +/***/ }), - webidl.argumentLengthCheck(arguments, 1, { header: 'WebSocket constructor' }) +/***/ 2725: +/***/ ((module) => { - if (!experimentalWarned) { - experimentalWarned = true - process.emitWarning('WebSockets are experimental, expect them to change at any time.', { - code: 'UNDICI-WS' - }) - } - const options = webidl.converters['DOMString or sequence or WebSocketInit'](protocols) - url = webidl.converters.USVString(url) - protocols = options.protocols +/** + * @see https://encoding.spec.whatwg.org/#concept-encoding-get + * @param {string|undefined} label + */ +function getEncoding (label) { + if (!label) { + return 'failure' + } - // 1. Let baseURL be this's relevant settings object's API base URL. - const baseURL = getGlobalOrigin() + // 1. Remove any leading and trailing ASCII whitespace from label. + // 2. If label is an ASCII case-insensitive match for any of the + // labels listed in the table below, then return the + // corresponding encoding; otherwise return failure. + switch (label.trim().toLowerCase()) { + case 'unicode-1-1-utf-8': + case 'unicode11utf8': + case 'unicode20utf8': + case 'utf-8': + case 'utf8': + case 'x-unicode20utf8': + return 'UTF-8' + case '866': + case 'cp866': + case 'csibm866': + case 'ibm866': + return 'IBM866' + case 'csisolatin2': + case 'iso-8859-2': + case 'iso-ir-101': + case 'iso8859-2': + case 'iso88592': + case 'iso_8859-2': + case 'iso_8859-2:1987': + case 'l2': + case 'latin2': + return 'ISO-8859-2' + case 'csisolatin3': + case 'iso-8859-3': + case 'iso-ir-109': + case 'iso8859-3': + case 'iso88593': + case 'iso_8859-3': + case 'iso_8859-3:1988': + case 'l3': + case 'latin3': + return 'ISO-8859-3' + case 'csisolatin4': + case 'iso-8859-4': + case 'iso-ir-110': + case 'iso8859-4': + case 'iso88594': + case 'iso_8859-4': + case 'iso_8859-4:1988': + case 'l4': + case 'latin4': + return 'ISO-8859-4' + case 'csisolatincyrillic': + case 'cyrillic': + case 'iso-8859-5': + case 'iso-ir-144': + case 'iso8859-5': + case 'iso88595': + case 'iso_8859-5': + case 'iso_8859-5:1988': + return 'ISO-8859-5' + case 'arabic': + case 'asmo-708': + case 'csiso88596e': + case 'csiso88596i': + case 'csisolatinarabic': + case 'ecma-114': + case 'iso-8859-6': + case 'iso-8859-6-e': + case 'iso-8859-6-i': + case 'iso-ir-127': + case 'iso8859-6': + case 'iso88596': + case 'iso_8859-6': + case 'iso_8859-6:1987': + return 'ISO-8859-6' + case 'csisolatingreek': + case 'ecma-118': + case 'elot_928': + case 'greek': + case 'greek8': + case 'iso-8859-7': + case 'iso-ir-126': + case 'iso8859-7': + case 'iso88597': + case 'iso_8859-7': + case 'iso_8859-7:1987': + case 'sun_eu_greek': + return 'ISO-8859-7' + case 'csiso88598e': + case 'csisolatinhebrew': + case 'hebrew': + case 'iso-8859-8': + case 'iso-8859-8-e': + case 'iso-ir-138': + case 'iso8859-8': + case 'iso88598': + case 'iso_8859-8': + case 'iso_8859-8:1988': + case 'visual': + return 'ISO-8859-8' + case 'csiso88598i': + case 'iso-8859-8-i': + case 'logical': + return 'ISO-8859-8-I' + case 'csisolatin6': + case 'iso-8859-10': + case 'iso-ir-157': + case 'iso8859-10': + case 'iso885910': + case 'l6': + case 'latin6': + return 'ISO-8859-10' + case 'iso-8859-13': + case 'iso8859-13': + case 'iso885913': + return 'ISO-8859-13' + case 'iso-8859-14': + case 'iso8859-14': + case 'iso885914': + return 'ISO-8859-14' + case 'csisolatin9': + case 'iso-8859-15': + case 'iso8859-15': + case 'iso885915': + case 'iso_8859-15': + case 'l9': + return 'ISO-8859-15' + case 'iso-8859-16': + return 'ISO-8859-16' + case 'cskoi8r': + case 'koi': + case 'koi8': + case 'koi8-r': + case 'koi8_r': + return 'KOI8-R' + case 'koi8-ru': + case 'koi8-u': + return 'KOI8-U' + case 'csmacintosh': + case 'mac': + case 'macintosh': + case 'x-mac-roman': + return 'macintosh' + case 'iso-8859-11': + case 'iso8859-11': + case 'iso885911': + case 'tis-620': + case 'windows-874': + return 'windows-874' + case 'cp1250': + case 'windows-1250': + case 'x-cp1250': + return 'windows-1250' + case 'cp1251': + case 'windows-1251': + case 'x-cp1251': + return 'windows-1251' + case 'ansi_x3.4-1968': + case 'ascii': + case 'cp1252': + case 'cp819': + case 'csisolatin1': + case 'ibm819': + case 'iso-8859-1': + case 'iso-ir-100': + case 'iso8859-1': + case 'iso88591': + case 'iso_8859-1': + case 'iso_8859-1:1987': + case 'l1': + case 'latin1': + case 'us-ascii': + case 'windows-1252': + case 'x-cp1252': + return 'windows-1252' + case 'cp1253': + case 'windows-1253': + case 'x-cp1253': + return 'windows-1253' + case 'cp1254': + case 'csisolatin5': + case 'iso-8859-9': + case 'iso-ir-148': + case 'iso8859-9': + case 'iso88599': + case 'iso_8859-9': + case 'iso_8859-9:1989': + case 'l5': + case 'latin5': + case 'windows-1254': + case 'x-cp1254': + return 'windows-1254' + case 'cp1255': + case 'windows-1255': + case 'x-cp1255': + return 'windows-1255' + case 'cp1256': + case 'windows-1256': + case 'x-cp1256': + return 'windows-1256' + case 'cp1257': + case 'windows-1257': + case 'x-cp1257': + return 'windows-1257' + case 'cp1258': + case 'windows-1258': + case 'x-cp1258': + return 'windows-1258' + case 'x-mac-cyrillic': + case 'x-mac-ukrainian': + return 'x-mac-cyrillic' + case 'chinese': + case 'csgb2312': + case 'csiso58gb231280': + case 'gb2312': + case 'gb_2312': + case 'gb_2312-80': + case 'gbk': + case 'iso-ir-58': + case 'x-gbk': + return 'GBK' + case 'gb18030': + return 'gb18030' + case 'big5': + case 'big5-hkscs': + case 'cn-big5': + case 'csbig5': + case 'x-x-big5': + return 'Big5' + case 'cseucpkdfmtjapanese': + case 'euc-jp': + case 'x-euc-jp': + return 'EUC-JP' + case 'csiso2022jp': + case 'iso-2022-jp': + return 'ISO-2022-JP' + case 'csshiftjis': + case 'ms932': + case 'ms_kanji': + case 'shift-jis': + case 'shift_jis': + case 'sjis': + case 'windows-31j': + case 'x-sjis': + return 'Shift_JIS' + case 'cseuckr': + case 'csksc56011987': + case 'euc-kr': + case 'iso-ir-149': + case 'korean': + case 'ks_c_5601-1987': + case 'ks_c_5601-1989': + case 'ksc5601': + case 'ksc_5601': + case 'windows-949': + return 'EUC-KR' + case 'csiso2022kr': + case 'hz-gb-2312': + case 'iso-2022-cn': + case 'iso-2022-cn-ext': + case 'iso-2022-kr': + case 'replacement': + return 'replacement' + case 'unicodefffe': + case 'utf-16be': + return 'UTF-16BE' + case 'csunicode': + case 'iso-10646-ucs-2': + case 'ucs-2': + case 'unicode': + case 'unicodefeff': + case 'utf-16': + case 'utf-16le': + return 'UTF-16LE' + case 'x-user-defined': + return 'x-user-defined' + default: return 'failure' + } +} - // 1. Let urlRecord be the result of applying the URL parser to url with baseURL. - let urlRecord +module.exports = { + getEncoding +} - try { - urlRecord = new URL(url, baseURL) - } catch (e) { - // 3. If urlRecord is failure, then throw a "SyntaxError" DOMException. - throw new DOMException(e, 'SyntaxError') - } - // 4. If urlRecord’s scheme is "http", then set urlRecord’s scheme to "ws". - if (urlRecord.protocol === 'http:') { - urlRecord.protocol = 'ws:' - } else if (urlRecord.protocol === 'https:') { - // 5. Otherwise, if urlRecord’s scheme is "https", set urlRecord’s scheme to "wss". - urlRecord.protocol = 'wss:' - } +/***/ }), - // 6. If urlRecord’s scheme is not "ws" or "wss", then throw a "SyntaxError" DOMException. - if (urlRecord.protocol !== 'ws:' && urlRecord.protocol !== 'wss:') { - throw new DOMException( - `Expected a ws: or wss: protocol, got ${urlRecord.protocol}`, - 'SyntaxError' - ) - } +/***/ 1705: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - // 7. If urlRecord’s fragment is non-null, then throw a "SyntaxError" - // DOMException. - if (urlRecord.hash || urlRecord.href.endsWith('#')) { - throw new DOMException('Got fragment', 'SyntaxError') - } - // 8. If protocols is a string, set protocols to a sequence consisting - // of just that string. - if (typeof protocols === 'string') { - protocols = [protocols] - } - // 9. If any of the values in protocols occur more than once or otherwise - // fail to match the requirements for elements that comprise the value - // of `Sec-WebSocket-Protocol` fields as defined by The WebSocket - // protocol, then throw a "SyntaxError" DOMException. - if (protocols.length !== new Set(protocols.map(p => p.toLowerCase())).size) { - throw new DOMException('Invalid Sec-WebSocket-Protocol value', 'SyntaxError') - } +const { + staticPropertyDescriptors, + readOperation, + fireAProgressEvent +} = __nccwpck_require__(2444) +const { + kState, + kError, + kResult, + kEvents, + kAborted +} = __nccwpck_require__(2879) +const { webidl } = __nccwpck_require__(4859) +const { kEnumerableProperty } = __nccwpck_require__(7234) - if (protocols.length > 0 && !protocols.every(p => isValidSubprotocol(p))) { - throw new DOMException('Invalid Sec-WebSocket-Protocol value', 'SyntaxError') +class FileReader extends EventTarget { + constructor () { + super() + + this[kState] = 'empty' + this[kResult] = null + this[kError] = null + this[kEvents] = { + loadend: null, + error: null, + abort: null, + load: null, + progress: null, + loadstart: null } + } - // 10. Set this's url to urlRecord. - this[kWebSocketURL] = new URL(urlRecord.href) + /** + * @see https://w3c.github.io/FileAPI/#dfn-readAsArrayBuffer + * @param {import('buffer').Blob} blob + */ + readAsArrayBuffer (blob) { + webidl.brandCheck(this, FileReader) - // 11. Let client be this's relevant settings object. + webidl.argumentLengthCheck(arguments, 1, 'FileReader.readAsArrayBuffer') - // 12. Run this step in parallel: + blob = webidl.converters.Blob(blob, { strict: false }) - // 1. Establish a WebSocket connection given urlRecord, protocols, - // and client. - this[kController] = establishWebSocketConnection( - urlRecord, - protocols, - this, - (response) => this.#onConnectionEstablished(response), - options - ) + // The readAsArrayBuffer(blob) method, when invoked, + // must initiate a read operation for blob with ArrayBuffer. + readOperation(this, blob, 'ArrayBuffer') + } - // Each WebSocket object has an associated ready state, which is a - // number representing the state of the connection. Initially it must - // be CONNECTING (0). - this[kReadyState] = WebSocket.CONNECTING + /** + * @see https://w3c.github.io/FileAPI/#readAsBinaryString + * @param {import('buffer').Blob} blob + */ + readAsBinaryString (blob) { + webidl.brandCheck(this, FileReader) - // The extensions attribute must initially return the empty string. + webidl.argumentLengthCheck(arguments, 1, 'FileReader.readAsBinaryString') - // The protocol attribute must initially return the empty string. + blob = webidl.converters.Blob(blob, { strict: false }) - // Each WebSocket object has an associated binary type, which is a - // BinaryType. Initially it must be "blob". - this[kBinaryType] = 'blob' + // The readAsBinaryString(blob) method, when invoked, + // must initiate a read operation for blob with BinaryString. + readOperation(this, blob, 'BinaryString') } /** - * @see https://websockets.spec.whatwg.org/#dom-websocket-close - * @param {number|undefined} code - * @param {string|undefined} reason + * @see https://w3c.github.io/FileAPI/#readAsDataText + * @param {import('buffer').Blob} blob + * @param {string?} encoding */ - close (code = undefined, reason = undefined) { - webidl.brandCheck(this, WebSocket) + readAsText (blob, encoding = undefined) { + webidl.brandCheck(this, FileReader) - if (code !== undefined) { - code = webidl.converters['unsigned short'](code, { clamp: true }) - } + webidl.argumentLengthCheck(arguments, 1, 'FileReader.readAsText') - if (reason !== undefined) { - reason = webidl.converters.USVString(reason) - } + blob = webidl.converters.Blob(blob, { strict: false }) - // 1. If code is present, but is neither an integer equal to 1000 nor an - // integer in the range 3000 to 4999, inclusive, throw an - // "InvalidAccessError" DOMException. - if (code !== undefined) { - if (code !== 1000 && (code < 3000 || code > 4999)) { - throw new DOMException('invalid code', 'InvalidAccessError') - } + if (encoding !== undefined) { + encoding = webidl.converters.DOMString(encoding, 'FileReader.readAsText', 'encoding') } - let reasonByteLength = 0 - - // 2. If reason is present, then run these substeps: - if (reason !== undefined) { - // 1. Let reasonBytes be the result of encoding reason. - // 2. If reasonBytes is longer than 123 bytes, then throw a - // "SyntaxError" DOMException. - reasonByteLength = Buffer.byteLength(reason) + // The readAsText(blob, encoding) method, when invoked, + // must initiate a read operation for blob with Text and encoding. + readOperation(this, blob, 'Text', encoding) + } - if (reasonByteLength > 123) { - throw new DOMException( - `Reason must be less than 123 bytes; received ${reasonByteLength}`, - 'SyntaxError' - ) - } - } + /** + * @see https://w3c.github.io/FileAPI/#dfn-readAsDataURL + * @param {import('buffer').Blob} blob + */ + readAsDataURL (blob) { + webidl.brandCheck(this, FileReader) - // 3. Run the first matching steps from the following list: - if (this[kReadyState] === WebSocket.CLOSING || this[kReadyState] === WebSocket.CLOSED) { - // If this's ready state is CLOSING (2) or CLOSED (3) - // Do nothing. - } else if (!isEstablished(this)) { - // If the WebSocket connection is not yet established - // Fail the WebSocket connection and set this's ready state - // to CLOSING (2). - failWebsocketConnection(this, 'Connection was closed before it was established.') - this[kReadyState] = WebSocket.CLOSING - } else if (!isClosing(this)) { - // If the WebSocket closing handshake has not yet been started - // Start the WebSocket closing handshake and set this's ready - // state to CLOSING (2). - // - If neither code nor reason is present, the WebSocket Close - // message must not have a body. - // - If code is present, then the status code to use in the - // WebSocket Close message must be the integer given by code. - // - If reason is also present, then reasonBytes must be - // provided in the Close message after the status code. - - const frame = new WebsocketFrameSend() - - // If neither code nor reason is present, the WebSocket Close - // message must not have a body. - - // If code is present, then the status code to use in the - // WebSocket Close message must be the integer given by code. - if (code !== undefined && reason === undefined) { - frame.frameData = Buffer.allocUnsafe(2) - frame.frameData.writeUInt16BE(code, 0) - } else if (code !== undefined && reason !== undefined) { - // If reason is also present, then reasonBytes must be - // provided in the Close message after the status code. - frame.frameData = Buffer.allocUnsafe(2 + reasonByteLength) - frame.frameData.writeUInt16BE(code, 0) - // the body MAY contain UTF-8-encoded data with value /reason/ - frame.frameData.write(reason, 2, 'utf-8') - } else { - frame.frameData = emptyBuffer - } + webidl.argumentLengthCheck(arguments, 1, 'FileReader.readAsDataURL') - /** @type {import('stream').Duplex} */ - const socket = this[kResponse].socket + blob = webidl.converters.Blob(blob, { strict: false }) - socket.write(frame.createFrame(opcodes.CLOSE), (err) => { - if (!err) { - this[kSentClose] = true - } - }) - - // Upon either sending or receiving a Close control frame, it is said - // that _The WebSocket Closing Handshake is Started_ and that the - // WebSocket connection is in the CLOSING state. - this[kReadyState] = states.CLOSING - } else { - // Otherwise - // Set this's ready state to CLOSING (2). - this[kReadyState] = WebSocket.CLOSING - } - } + // The readAsDataURL(blob) method, when invoked, must + // initiate a read operation for blob with DataURL. + readOperation(this, blob, 'DataURL') + } /** - * @see https://websockets.spec.whatwg.org/#dom-websocket-send - * @param {NodeJS.TypedArray|ArrayBuffer|Blob|string} data + * @see https://w3c.github.io/FileAPI/#dfn-abort */ - send (data) { - webidl.brandCheck(this, WebSocket) - - webidl.argumentLengthCheck(arguments, 1, { header: 'WebSocket.send' }) - - data = webidl.converters.WebSocketSendData(data) - - // 1. If this's ready state is CONNECTING, then throw an - // "InvalidStateError" DOMException. - if (this[kReadyState] === WebSocket.CONNECTING) { - throw new DOMException('Sent before connected.', 'InvalidStateError') - } - - // 2. Run the appropriate set of steps from the following list: - // https://datatracker.ietf.org/doc/html/rfc6455#section-6.1 - // https://datatracker.ietf.org/doc/html/rfc6455#section-5.2 - - if (!isEstablished(this) || isClosing(this)) { + abort () { + // 1. If this's state is "empty" or if this's state is + // "done" set this's result to null and terminate + // this algorithm. + if (this[kState] === 'empty' || this[kState] === 'done') { + this[kResult] = null return } - /** @type {import('stream').Duplex} */ - const socket = this[kResponse].socket - - // If data is a string - if (typeof data === 'string') { - // If the WebSocket connection is established and the WebSocket - // closing handshake has not yet started, then the user agent - // must send a WebSocket Message comprised of the data argument - // using a text frame opcode; if the data cannot be sent, e.g. - // because it would need to be buffered but the buffer is full, - // the user agent must flag the WebSocket as full and then close - // the WebSocket connection. Any invocation of this method with a - // string argument that does not throw an exception must increase - // the bufferedAmount attribute by the number of bytes needed to - // express the argument as UTF-8. - - const value = Buffer.from(data) - const frame = new WebsocketFrameSend(value) - const buffer = frame.createFrame(opcodes.TEXT) - - this.#bufferedAmount += value.byteLength - socket.write(buffer, () => { - this.#bufferedAmount -= value.byteLength - }) - } else if (types.isArrayBuffer(data)) { - // If the WebSocket connection is established, and the WebSocket - // closing handshake has not yet started, then the user agent must - // send a WebSocket Message comprised of data using a binary frame - // opcode; if the data cannot be sent, e.g. because it would need - // to be buffered but the buffer is full, the user agent must flag - // the WebSocket as full and then close the WebSocket connection. - // The data to be sent is the data stored in the buffer described - // by the ArrayBuffer object. Any invocation of this method with an - // ArrayBuffer argument that does not throw an exception must - // increase the bufferedAmount attribute by the length of the - // ArrayBuffer in bytes. - - const value = Buffer.from(data) - const frame = new WebsocketFrameSend(value) - const buffer = frame.createFrame(opcodes.BINARY) - - this.#bufferedAmount += value.byteLength - socket.write(buffer, () => { - this.#bufferedAmount -= value.byteLength - }) - } else if (ArrayBuffer.isView(data)) { - // If the WebSocket connection is established, and the WebSocket - // closing handshake has not yet started, then the user agent must - // send a WebSocket Message comprised of data using a binary frame - // opcode; if the data cannot be sent, e.g. because it would need to - // be buffered but the buffer is full, the user agent must flag the - // WebSocket as full and then close the WebSocket connection. The - // data to be sent is the data stored in the section of the buffer - // described by the ArrayBuffer object that data references. Any - // invocation of this method with this kind of argument that does - // not throw an exception must increase the bufferedAmount attribute - // by the length of data’s buffer in bytes. - - const ab = Buffer.from(data, data.byteOffset, data.byteLength) - - const frame = new WebsocketFrameSend(ab) - const buffer = frame.createFrame(opcodes.BINARY) + // 2. If this's state is "loading" set this's state to + // "done" and set this's result to null. + if (this[kState] === 'loading') { + this[kState] = 'done' + this[kResult] = null + } - this.#bufferedAmount += ab.byteLength - socket.write(buffer, () => { - this.#bufferedAmount -= ab.byteLength - }) - } else if (isBlobLike(data)) { - // If the WebSocket connection is established, and the WebSocket - // closing handshake has not yet started, then the user agent must - // send a WebSocket Message comprised of data using a binary frame - // opcode; if the data cannot be sent, e.g. because it would need to - // be buffered but the buffer is full, the user agent must flag the - // WebSocket as full and then close the WebSocket connection. The data - // to be sent is the raw data represented by the Blob object. Any - // invocation of this method with a Blob argument that does not throw - // an exception must increase the bufferedAmount attribute by the size - // of the Blob object’s raw data, in bytes. + // 3. If there are any tasks from this on the file reading + // task source in an affiliated task queue, then remove + // those tasks from that task queue. + this[kAborted] = true - const frame = new WebsocketFrameSend() + // 4. Terminate the algorithm for the read method being processed. + // TODO - data.arrayBuffer().then((ab) => { - const value = Buffer.from(ab) - frame.frameData = value - const buffer = frame.createFrame(opcodes.BINARY) + // 5. Fire a progress event called abort at this. + fireAProgressEvent('abort', this) - this.#bufferedAmount += value.byteLength - socket.write(buffer, () => { - this.#bufferedAmount -= value.byteLength - }) - }) + // 6. If this's state is not "loading", fire a progress + // event called loadend at this. + if (this[kState] !== 'loading') { + fireAProgressEvent('loadend', this) } } + /** + * @see https://w3c.github.io/FileAPI/#dom-filereader-readystate + */ get readyState () { - webidl.brandCheck(this, WebSocket) - - // The readyState getter steps are to return this's ready state. - return this[kReadyState] - } - - get bufferedAmount () { - webidl.brandCheck(this, WebSocket) - - return this.#bufferedAmount - } - - get url () { - webidl.brandCheck(this, WebSocket) + webidl.brandCheck(this, FileReader) - // The url getter steps are to return this's url, serialized. - return URLSerializer(this[kWebSocketURL]) + switch (this[kState]) { + case 'empty': return this.EMPTY + case 'loading': return this.LOADING + case 'done': return this.DONE + } } - get extensions () { - webidl.brandCheck(this, WebSocket) + /** + * @see https://w3c.github.io/FileAPI/#dom-filereader-result + */ + get result () { + webidl.brandCheck(this, FileReader) - return this.#extensions + // The result attribute’s getter, when invoked, must return + // this's result. + return this[kResult] } - get protocol () { - webidl.brandCheck(this, WebSocket) + /** + * @see https://w3c.github.io/FileAPI/#dom-filereader-error + */ + get error () { + webidl.brandCheck(this, FileReader) - return this.#protocol + // The error attribute’s getter, when invoked, must return + // this's error. + return this[kError] } - get onopen () { - webidl.brandCheck(this, WebSocket) + get onloadend () { + webidl.brandCheck(this, FileReader) - return this.#events.open + return this[kEvents].loadend } - set onopen (fn) { - webidl.brandCheck(this, WebSocket) + set onloadend (fn) { + webidl.brandCheck(this, FileReader) - if (this.#events.open) { - this.removeEventListener('open', this.#events.open) + if (this[kEvents].loadend) { + this.removeEventListener('loadend', this[kEvents].loadend) } if (typeof fn === 'function') { - this.#events.open = fn - this.addEventListener('open', fn) + this[kEvents].loadend = fn + this.addEventListener('loadend', fn) } else { - this.#events.open = null + this[kEvents].loadend = null } } get onerror () { - webidl.brandCheck(this, WebSocket) + webidl.brandCheck(this, FileReader) - return this.#events.error + return this[kEvents].error } set onerror (fn) { - webidl.brandCheck(this, WebSocket) + webidl.brandCheck(this, FileReader) - if (this.#events.error) { - this.removeEventListener('error', this.#events.error) + if (this[kEvents].error) { + this.removeEventListener('error', this[kEvents].error) } if (typeof fn === 'function') { - this.#events.error = fn + this[kEvents].error = fn this.addEventListener('error', fn) } else { - this.#events.error = null + this[kEvents].error = null } } - get onclose () { - webidl.brandCheck(this, WebSocket) + get onloadstart () { + webidl.brandCheck(this, FileReader) - return this.#events.close + return this[kEvents].loadstart } - set onclose (fn) { - webidl.brandCheck(this, WebSocket) + set onloadstart (fn) { + webidl.brandCheck(this, FileReader) - if (this.#events.close) { - this.removeEventListener('close', this.#events.close) + if (this[kEvents].loadstart) { + this.removeEventListener('loadstart', this[kEvents].loadstart) } if (typeof fn === 'function') { - this.#events.close = fn - this.addEventListener('close', fn) + this[kEvents].loadstart = fn + this.addEventListener('loadstart', fn) } else { - this.#events.close = null + this[kEvents].loadstart = null } } - get onmessage () { - webidl.brandCheck(this, WebSocket) + get onprogress () { + webidl.brandCheck(this, FileReader) - return this.#events.message + return this[kEvents].progress } - set onmessage (fn) { - webidl.brandCheck(this, WebSocket) + set onprogress (fn) { + webidl.brandCheck(this, FileReader) - if (this.#events.message) { - this.removeEventListener('message', this.#events.message) + if (this[kEvents].progress) { + this.removeEventListener('progress', this[kEvents].progress) } if (typeof fn === 'function') { - this.#events.message = fn - this.addEventListener('message', fn) + this[kEvents].progress = fn + this.addEventListener('progress', fn) } else { - this.#events.message = null + this[kEvents].progress = null } } - get binaryType () { - webidl.brandCheck(this, WebSocket) + get onload () { + webidl.brandCheck(this, FileReader) - return this[kBinaryType] + return this[kEvents].load } - set binaryType (type) { - webidl.brandCheck(this, WebSocket) + set onload (fn) { + webidl.brandCheck(this, FileReader) - if (type !== 'blob' && type !== 'arraybuffer') { - this[kBinaryType] = 'blob' + if (this[kEvents].load) { + this.removeEventListener('load', this[kEvents].load) + } + + if (typeof fn === 'function') { + this[kEvents].load = fn + this.addEventListener('load', fn) } else { - this[kBinaryType] = type + this[kEvents].load = null } } - /** - * @see https://websockets.spec.whatwg.org/#feedback-from-the-protocol - */ - #onConnectionEstablished (response) { - // processResponse is called when the "response’s header list has been received and initialized." - // once this happens, the connection is open - this[kResponse] = response - - const parser = new ByteParser(this) - parser.on('drain', function onParserDrain () { - this.ws[kResponse].socket.resume() - }) - - response.socket.ws = this - this[kByteParser] = parser + get onabort () { + webidl.brandCheck(this, FileReader) - // 1. Change the ready state to OPEN (1). - this[kReadyState] = states.OPEN + return this[kEvents].abort + } - // 2. Change the extensions attribute’s value to the extensions in use, if - // it is not the null value. - // https://datatracker.ietf.org/doc/html/rfc6455#section-9.1 - const extensions = response.headersList.get('sec-websocket-extensions') + set onabort (fn) { + webidl.brandCheck(this, FileReader) - if (extensions !== null) { - this.#extensions = extensions + if (this[kEvents].abort) { + this.removeEventListener('abort', this[kEvents].abort) } - // 3. Change the protocol attribute’s value to the subprotocol in use, if - // it is not the null value. - // https://datatracker.ietf.org/doc/html/rfc6455#section-1.9 - const protocol = response.headersList.get('sec-websocket-protocol') - - if (protocol !== null) { - this.#protocol = protocol + if (typeof fn === 'function') { + this[kEvents].abort = fn + this.addEventListener('abort', fn) + } else { + this[kEvents].abort = null } - - // 4. Fire an event named open at the WebSocket object. - fireEvent('open', this) } } -// https://websockets.spec.whatwg.org/#dom-websocket-connecting -WebSocket.CONNECTING = WebSocket.prototype.CONNECTING = states.CONNECTING -// https://websockets.spec.whatwg.org/#dom-websocket-open -WebSocket.OPEN = WebSocket.prototype.OPEN = states.OPEN -// https://websockets.spec.whatwg.org/#dom-websocket-closing -WebSocket.CLOSING = WebSocket.prototype.CLOSING = states.CLOSING -// https://websockets.spec.whatwg.org/#dom-websocket-closed -WebSocket.CLOSED = WebSocket.prototype.CLOSED = states.CLOSED +// https://w3c.github.io/FileAPI/#dom-filereader-empty +FileReader.EMPTY = FileReader.prototype.EMPTY = 0 +// https://w3c.github.io/FileAPI/#dom-filereader-loading +FileReader.LOADING = FileReader.prototype.LOADING = 1 +// https://w3c.github.io/FileAPI/#dom-filereader-done +FileReader.DONE = FileReader.prototype.DONE = 2 -Object.defineProperties(WebSocket.prototype, { - CONNECTING: staticPropertyDescriptors, - OPEN: staticPropertyDescriptors, - CLOSING: staticPropertyDescriptors, - CLOSED: staticPropertyDescriptors, - url: kEnumerableProperty, +Object.defineProperties(FileReader.prototype, { + EMPTY: staticPropertyDescriptors, + LOADING: staticPropertyDescriptors, + DONE: staticPropertyDescriptors, + readAsArrayBuffer: kEnumerableProperty, + readAsBinaryString: kEnumerableProperty, + readAsText: kEnumerableProperty, + readAsDataURL: kEnumerableProperty, + abort: kEnumerableProperty, readyState: kEnumerableProperty, - bufferedAmount: kEnumerableProperty, - onopen: kEnumerableProperty, + result: kEnumerableProperty, + error: kEnumerableProperty, + onloadstart: kEnumerableProperty, + onprogress: kEnumerableProperty, + onload: kEnumerableProperty, + onabort: kEnumerableProperty, onerror: kEnumerableProperty, - onclose: kEnumerableProperty, - close: kEnumerableProperty, - onmessage: kEnumerableProperty, - binaryType: kEnumerableProperty, - send: kEnumerableProperty, - extensions: kEnumerableProperty, - protocol: kEnumerableProperty, + onloadend: kEnumerableProperty, [Symbol.toStringTag]: { - value: 'WebSocket', + value: 'FileReader', writable: false, enumerable: false, configurable: true } }) -Object.defineProperties(WebSocket, { - CONNECTING: staticPropertyDescriptors, - OPEN: staticPropertyDescriptors, - CLOSING: staticPropertyDescriptors, - CLOSED: staticPropertyDescriptors +Object.defineProperties(FileReader, { + EMPTY: staticPropertyDescriptors, + LOADING: staticPropertyDescriptors, + DONE: staticPropertyDescriptors }) -webidl.converters['sequence'] = webidl.sequenceConverter( - webidl.converters.DOMString -) +module.exports = { + FileReader +} -webidl.converters['DOMString or sequence'] = function (V) { - if (webidl.util.Type(V) === 'Object' && Symbol.iterator in V) { - return webidl.converters['sequence'](V) + +/***/ }), + +/***/ 9347: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + + + +const { webidl } = __nccwpck_require__(4859) + +const kState = Symbol('ProgressEvent state') + +/** + * @see https://xhr.spec.whatwg.org/#progressevent + */ +class ProgressEvent extends Event { + constructor (type, eventInitDict = {}) { + type = webidl.converters.DOMString(type, 'ProgressEvent constructor', 'type') + eventInitDict = webidl.converters.ProgressEventInit(eventInitDict ?? {}) + + super(type, eventInitDict) + + this[kState] = { + lengthComputable: eventInitDict.lengthComputable, + loaded: eventInitDict.loaded, + total: eventInitDict.total + } + } + + get lengthComputable () { + webidl.brandCheck(this, ProgressEvent) + + return this[kState].lengthComputable + } + + get loaded () { + webidl.brandCheck(this, ProgressEvent) + + return this[kState].loaded } - return webidl.converters.DOMString(V) + get total () { + webidl.brandCheck(this, ProgressEvent) + + return this[kState].total + } } -// This implements the propsal made in https://github.com/whatwg/websockets/issues/42 -webidl.converters.WebSocketInit = webidl.dictionaryConverter([ +webidl.converters.ProgressEventInit = webidl.dictionaryConverter([ { - key: 'protocols', - converter: webidl.converters['DOMString or sequence'], - get defaultValue () { - return [] - } + key: 'lengthComputable', + converter: webidl.converters.boolean, + defaultValue: () => false }, { - key: 'dispatcher', - converter: (V) => V, - get defaultValue () { - return getGlobalDispatcher() - } + key: 'loaded', + converter: webidl.converters['unsigned long long'], + defaultValue: () => 0 }, { - key: 'headers', - converter: webidl.nullableConverter(webidl.converters.HeadersInit) + key: 'total', + converter: webidl.converters['unsigned long long'], + defaultValue: () => 0 + }, + { + key: 'bubbles', + converter: webidl.converters.boolean, + defaultValue: () => false + }, + { + key: 'cancelable', + converter: webidl.converters.boolean, + defaultValue: () => false + }, + { + key: 'composed', + converter: webidl.converters.boolean, + defaultValue: () => false } ]) -webidl.converters['DOMString or sequence or WebSocketInit'] = function (V) { - if (webidl.util.Type(V) === 'Object' && !(Symbol.iterator in V)) { - return webidl.converters.WebSocketInit(V) - } - - return { protocols: webidl.converters['DOMString or sequence'](V) } +module.exports = { + ProgressEvent } -webidl.converters.WebSocketSendData = function (V) { - if (webidl.util.Type(V) === 'Object') { - if (isBlobLike(V)) { - return webidl.converters.Blob(V, { strict: false }) - } - if (ArrayBuffer.isView(V) || types.isAnyArrayBuffer(V)) { - return webidl.converters.BufferSource(V) - } - } +/***/ }), + +/***/ 2879: +/***/ ((module) => { + - return webidl.converters.USVString(V) -} module.exports = { - WebSocket + kState: Symbol('FileReader state'), + kResult: Symbol('FileReader result'), + kError: Symbol('FileReader error'), + kLastProgressEventFired: Symbol('FileReader last progress event fired timestamp'), + kEvents: Symbol('FileReader events'), + kAborted: Symbol('FileReader aborted') } /***/ }), -/***/ 7767: +/***/ 2444: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; - - -const Client = __nccwpck_require__(226) -const Dispatcher = __nccwpck_require__(2096) -const Pool = __nccwpck_require__(8767) -const BalancedPool = __nccwpck_require__(7604) -const RoundRobinPool = __nccwpck_require__(3079) -const Agent = __nccwpck_require__(2004) -const ProxyAgent = __nccwpck_require__(7621) -const EnvHttpProxyAgent = __nccwpck_require__(4646) -const RetryAgent = __nccwpck_require__(139) -const H2CClient = __nccwpck_require__(8036) -const errors = __nccwpck_require__(4928) -const util = __nccwpck_require__(983) -const { InvalidArgumentError } = errors -const api = __nccwpck_require__(2812) -const buildConnector = __nccwpck_require__(978) -const MockClient = __nccwpck_require__(1024) -const { MockCallHistory, MockCallHistoryLog } = __nccwpck_require__(7686) -const MockAgent = __nccwpck_require__(3550) -const MockPool = __nccwpck_require__(733) -const SnapshotAgent = __nccwpck_require__(8784) -const mockErrors = __nccwpck_require__(9664) -const RetryHandler = __nccwpck_require__(4943) -const { getGlobalDispatcher, setGlobalDispatcher } = __nccwpck_require__(4456) -const DecoratorHandler = __nccwpck_require__(5156) -const RedirectHandler = __nccwpck_require__(415) -Object.assign(Dispatcher.prototype, api) -module.exports.Dispatcher = Dispatcher -module.exports.Client = Client -module.exports.Pool = Pool -module.exports.BalancedPool = BalancedPool -module.exports.RoundRobinPool = RoundRobinPool -module.exports.Agent = Agent -module.exports.ProxyAgent = ProxyAgent -module.exports.EnvHttpProxyAgent = EnvHttpProxyAgent -module.exports.RetryAgent = RetryAgent -module.exports.H2CClient = H2CClient -module.exports.RetryHandler = RetryHandler - -module.exports.DecoratorHandler = DecoratorHandler -module.exports.RedirectHandler = RedirectHandler -module.exports.interceptors = { - redirect: __nccwpck_require__(4455), - responseError: __nccwpck_require__(3175), - retry: __nccwpck_require__(3149), - dump: __nccwpck_require__(873), - dns: __nccwpck_require__(4020), - cache: __nccwpck_require__(5661), - decompress: __nccwpck_require__(4100), - deduplicate: __nccwpck_require__(675) -} - -module.exports.cacheStores = { - MemoryCacheStore: __nccwpck_require__(9972) -} - -const SqliteCacheStore = __nccwpck_require__(6675) -module.exports.cacheStores.SqliteCacheStore = SqliteCacheStore - -module.exports.buildConnector = buildConnector -module.exports.errors = errors -module.exports.util = { - parseHeaders: util.parseHeaders, - headerNameToString: util.headerNameToString +const { + kState, + kError, + kResult, + kAborted, + kLastProgressEventFired +} = __nccwpck_require__(2879) +const { ProgressEvent } = __nccwpck_require__(9347) +const { getEncoding } = __nccwpck_require__(2725) +const { serializeAMimeType, parseMIMEType } = __nccwpck_require__(6406) +const { types } = __nccwpck_require__(7975) +const { StringDecoder } = __nccwpck_require__(3193) +const { btoa } = __nccwpck_require__(4573) + +/** @type {PropertyDescriptor} */ +const staticPropertyDescriptors = { + enumerable: true, + writable: false, + configurable: false } -function makeDispatcher (fn) { - return (url, opts, handler) => { - if (typeof opts === 'function') { - handler = opts - opts = null - } +/** + * @see https://w3c.github.io/FileAPI/#readOperation + * @param {import('./filereader').FileReader} fr + * @param {import('buffer').Blob} blob + * @param {string} type + * @param {string?} encodingName + */ +function readOperation (fr, blob, type, encodingName) { + // 1. If fr’s state is "loading", throw an InvalidStateError + // DOMException. + if (fr[kState] === 'loading') { + throw new DOMException('Invalid state', 'InvalidStateError') + } - if (!url || (typeof url !== 'string' && typeof url !== 'object' && !(url instanceof URL))) { - throw new InvalidArgumentError('invalid url') - } + // 2. Set fr’s state to "loading". + fr[kState] = 'loading' - if (opts != null && typeof opts !== 'object') { - throw new InvalidArgumentError('invalid opts') - } + // 3. Set fr’s result to null. + fr[kResult] = null - if (opts && opts.path != null) { - if (typeof opts.path !== 'string') { - throw new InvalidArgumentError('invalid opts.path') - } + // 4. Set fr’s error to null. + fr[kError] = null - let path = opts.path - if (!opts.path.startsWith('/')) { - path = `/${path}` - } - - url = new URL(util.parseOrigin(url).origin + path) - } else { - if (!opts) { - opts = typeof url === 'object' ? url : {} - } - - url = util.parseURL(url) - } - - const { agent, dispatcher = getGlobalDispatcher() } = opts - - if (agent) { - throw new InvalidArgumentError('unsupported opts.agent. Did you mean opts.client?') - } - - return fn.call(dispatcher, { - ...opts, - origin: url.origin, - path: url.search ? `${url.pathname}${url.search}` : url.pathname, - method: opts.method || (opts.body ? 'PUT' : 'GET') - }, handler) - } -} - -module.exports.setGlobalDispatcher = setGlobalDispatcher -module.exports.getGlobalDispatcher = getGlobalDispatcher - -const fetchImpl = (__nccwpck_require__(6377).fetch) + // 5. Let stream be the result of calling get stream on blob. + /** @type {import('stream/web').ReadableStream} */ + const stream = blob.stream() -module.exports.fetch = function fetch (init, options = undefined) { - return fetchImpl(init, options).catch(err => { - if (err && typeof err === 'object') { - Error.captureStackTrace(err) - } - throw err - }) -} -module.exports.Headers = __nccwpck_require__(8447).Headers -module.exports.Response = __nccwpck_require__(9294).Response -module.exports.Request = __nccwpck_require__(8140).Request -module.exports.FormData = __nccwpck_require__(51).FormData + // 6. Let reader be the result of getting a reader from stream. + const reader = stream.getReader() -const { setGlobalOrigin, getGlobalOrigin } = __nccwpck_require__(3862) + // 7. Let bytes be an empty byte sequence. + /** @type {Uint8Array[]} */ + const bytes = [] -module.exports.setGlobalOrigin = setGlobalOrigin -module.exports.getGlobalOrigin = getGlobalOrigin + // 8. Let chunkPromise be the result of reading a chunk from + // stream with reader. + let chunkPromise = reader.read() -const { CacheStorage } = __nccwpck_require__(7456) -const { kConstruct } = __nccwpck_require__(9562) + // 9. Let isFirstChunk be true. + let isFirstChunk = true -module.exports.caches = new CacheStorage(kConstruct) + // 10. In parallel, while true: + // Note: "In parallel" just means non-blocking + // Note 2: readOperation itself cannot be async as double + // reading the body would then reject the promise, instead + // of throwing an error. + ;(async () => { + while (!fr[kAborted]) { + // 1. Wait for chunkPromise to be fulfilled or rejected. + try { + const { done, value } = await chunkPromise -const { deleteCookie, getCookies, getSetCookies, setCookie, parseCookie } = __nccwpck_require__(2178) + // 2. If chunkPromise is fulfilled, and isFirstChunk is + // true, queue a task to fire a progress event called + // loadstart at fr. + if (isFirstChunk && !fr[kAborted]) { + queueMicrotask(() => { + fireAProgressEvent('loadstart', fr) + }) + } -module.exports.deleteCookie = deleteCookie -module.exports.getCookies = getCookies -module.exports.getSetCookies = getSetCookies -module.exports.setCookie = setCookie -module.exports.parseCookie = parseCookie + // 3. Set isFirstChunk to false. + isFirstChunk = false -const { parseMIMEType, serializeAMimeType } = __nccwpck_require__(9425) + // 4. If chunkPromise is fulfilled with an object whose + // done property is false and whose value property is + // a Uint8Array object, run these steps: + if (!done && types.isUint8Array(value)) { + // 1. Let bs be the byte sequence represented by the + // Uint8Array object. -module.exports.parseMIMEType = parseMIMEType -module.exports.serializeAMimeType = serializeAMimeType + // 2. Append bs to bytes. + bytes.push(value) -const { CloseEvent, ErrorEvent, MessageEvent } = __nccwpck_require__(649) -const { WebSocket, ping } = __nccwpck_require__(9197) -module.exports.WebSocket = WebSocket -module.exports.CloseEvent = CloseEvent -module.exports.ErrorEvent = ErrorEvent -module.exports.MessageEvent = MessageEvent -module.exports.ping = ping + // 3. If roughly 50ms have passed since these steps + // were last invoked, queue a task to fire a + // progress event called progress at fr. + if ( + ( + fr[kLastProgressEventFired] === undefined || + Date.now() - fr[kLastProgressEventFired] >= 50 + ) && + !fr[kAborted] + ) { + fr[kLastProgressEventFired] = Date.now() + queueMicrotask(() => { + fireAProgressEvent('progress', fr) + }) + } -module.exports.WebSocketStream = __nccwpck_require__(3056).WebSocketStream -module.exports.WebSocketError = __nccwpck_require__(9536).WebSocketError + // 4. Set chunkPromise to the result of reading a + // chunk from stream with reader. + chunkPromise = reader.read() + } else if (done) { + // 5. Otherwise, if chunkPromise is fulfilled with an + // object whose done property is true, queue a task + // to run the following steps and abort this algorithm: + queueMicrotask(() => { + // 1. Set fr’s state to "done". + fr[kState] = 'done' -module.exports.request = makeDispatcher(api.request) -module.exports.stream = makeDispatcher(api.stream) -module.exports.pipeline = makeDispatcher(api.pipeline) -module.exports.connect = makeDispatcher(api.connect) -module.exports.upgrade = makeDispatcher(api.upgrade) + // 2. Let result be the result of package data given + // bytes, type, blob’s type, and encodingName. + try { + const result = packageData(bytes, type, blob.type, encodingName) -module.exports.MockClient = MockClient -module.exports.MockCallHistory = MockCallHistory -module.exports.MockCallHistoryLog = MockCallHistoryLog -module.exports.MockPool = MockPool -module.exports.MockAgent = MockAgent -module.exports.SnapshotAgent = SnapshotAgent -module.exports.mockErrors = mockErrors + // 4. Else: -const { EventSource } = __nccwpck_require__(8845) + if (fr[kAborted]) { + return + } -module.exports.EventSource = EventSource + // 1. Set fr’s result to result. + fr[kResult] = result -function install () { - globalThis.fetch = module.exports.fetch - globalThis.Headers = module.exports.Headers - globalThis.Response = module.exports.Response - globalThis.Request = module.exports.Request - globalThis.FormData = module.exports.FormData - globalThis.WebSocket = module.exports.WebSocket - globalThis.CloseEvent = module.exports.CloseEvent - globalThis.ErrorEvent = module.exports.ErrorEvent - globalThis.MessageEvent = module.exports.MessageEvent - globalThis.EventSource = module.exports.EventSource -} + // 2. Fire a progress event called load at the fr. + fireAProgressEvent('load', fr) + } catch (error) { + // 3. If package data threw an exception error: -module.exports.install = install + // 1. Set fr’s error to error. + fr[kError] = error + // 2. Fire a progress event called error at fr. + fireAProgressEvent('error', fr) + } -/***/ }), + // 5. If fr’s state is not "loading", fire a progress + // event called loadend at the fr. + if (fr[kState] !== 'loading') { + fireAProgressEvent('loadend', fr) + } + }) -/***/ 6851: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + break + } + } catch (error) { + if (fr[kAborted]) { + return + } -"use strict"; + // 6. Otherwise, if chunkPromise is rejected with an + // error error, queue a task to run the following + // steps and abort this algorithm: + queueMicrotask(() => { + // 1. Set fr’s state to "done". + fr[kState] = 'done' + // 2. Set fr’s error to error. + fr[kError] = error -const { addAbortListener } = __nccwpck_require__(983) -const { RequestAbortedError } = __nccwpck_require__(4928) + // 3. Fire a progress event called error at fr. + fireAProgressEvent('error', fr) -const kListener = Symbol('kListener') -const kSignal = Symbol('kSignal') + // 4. If fr’s state is not "loading", fire a progress + // event called loadend at fr. + if (fr[kState] !== 'loading') { + fireAProgressEvent('loadend', fr) + } + }) -function abort (self) { - if (self.abort) { - self.abort(self[kSignal]?.reason) - } else { - self.reason = self[kSignal]?.reason ?? new RequestAbortedError() - } - removeSignal(self) + break + } + } + })() } -function addSignal (self, signal) { - self.reason = null +/** + * @see https://w3c.github.io/FileAPI/#fire-a-progress-event + * @see https://dom.spec.whatwg.org/#concept-event-fire + * @param {string} e The name of the event + * @param {import('./filereader').FileReader} reader + */ +function fireAProgressEvent (e, reader) { + // The progress event e does not bubble. e.bubbles must be false + // The progress event e is NOT cancelable. e.cancelable must be false + const event = new ProgressEvent(e, { + bubbles: false, + cancelable: false + }) - self[kSignal] = null - self[kListener] = null + reader.dispatchEvent(event) +} - if (!signal) { - return - } +/** + * @see https://w3c.github.io/FileAPI/#blob-package-data + * @param {Uint8Array[]} bytes + * @param {string} type + * @param {string?} mimeType + * @param {string?} encodingName + */ +function packageData (bytes, type, mimeType, encodingName) { + // 1. A Blob has an associated package data algorithm, given + // bytes, a type, a optional mimeType, and a optional + // encodingName, which switches on type and runs the + // associated steps: - if (signal.aborted) { - abort(self) - return - } + switch (type) { + case 'DataURL': { + // 1. Return bytes as a DataURL [RFC2397] subject to + // the considerations below: + // * Use mimeType as part of the Data URL if it is + // available in keeping with the Data URL + // specification [RFC2397]. + // * If mimeType is not available return a Data URL + // without a media-type. [RFC2397]. - self[kSignal] = signal - self[kListener] = () => { - abort(self) - } + // https://datatracker.ietf.org/doc/html/rfc2397#section-3 + // dataurl := "data:" [ mediatype ] [ ";base64" ] "," data + // mediatype := [ type "/" subtype ] *( ";" parameter ) + // data := *urlchar + // parameter := attribute "=" value + let dataURL = 'data:' - addAbortListener(self[kSignal], self[kListener]) -} + const parsed = parseMIMEType(mimeType || 'application/octet-stream') -function removeSignal (self) { - if (!self[kSignal]) { - return - } + if (parsed !== 'failure') { + dataURL += serializeAMimeType(parsed) + } - if ('removeEventListener' in self[kSignal]) { - self[kSignal].removeEventListener('abort', self[kListener]) - } else { - self[kSignal].removeListener('abort', self[kListener]) - } + dataURL += ';base64,' - self[kSignal] = null - self[kListener] = null -} + const decoder = new StringDecoder('latin1') -module.exports = { - addSignal, - removeSignal -} + for (const chunk of bytes) { + dataURL += btoa(decoder.write(chunk)) + } + dataURL += btoa(decoder.end()) -/***/ }), + return dataURL + } + case 'Text': { + // 1. Let encoding be failure + let encoding = 'failure' -/***/ 4031: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // 2. If the encodingName is present, set encoding to the + // result of getting an encoding from encodingName. + if (encodingName) { + encoding = getEncoding(encodingName) + } -"use strict"; + // 3. If encoding is failure, and mimeType is present: + if (encoding === 'failure' && mimeType) { + // 1. Let type be the result of parse a MIME type + // given mimeType. + const type = parseMIMEType(mimeType) + // 2. If type is not failure, set encoding to the result + // of getting an encoding from type’s parameters["charset"]. + if (type !== 'failure') { + encoding = getEncoding(type.parameters.get('charset')) + } + } -const assert = __nccwpck_require__(4589) -const { AsyncResource } = __nccwpck_require__(6698) -const { InvalidArgumentError, SocketError } = __nccwpck_require__(4928) -const util = __nccwpck_require__(983) -const { addSignal, removeSignal } = __nccwpck_require__(6851) + // 4. If encoding is failure, then set encoding to UTF-8. + if (encoding === 'failure') { + encoding = 'UTF-8' + } -class ConnectHandler extends AsyncResource { - constructor (opts, callback) { - if (!opts || typeof opts !== 'object') { - throw new InvalidArgumentError('invalid opts') + // 5. Decode bytes using fallback encoding encoding, and + // return the result. + return decode(bytes, encoding) } + case 'ArrayBuffer': { + // Return a new ArrayBuffer whose contents are bytes. + const sequence = combineByteSequences(bytes) - if (typeof callback !== 'function') { - throw new InvalidArgumentError('invalid callback') + return sequence.buffer } + case 'BinaryString': { + // Return bytes as a binary string, in which every byte + // is represented by a code unit of equal value [0..255]. + let binaryString = '' - const { signal, opaque, responseHeaders } = opts - - if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { - throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') - } + const decoder = new StringDecoder('latin1') - super('UNDICI_CONNECT') + for (const chunk of bytes) { + binaryString += decoder.write(chunk) + } - this.opaque = opaque || null - this.responseHeaders = responseHeaders || null - this.callback = callback - this.abort = null + binaryString += decoder.end() - addSignal(this, signal) + return binaryString + } } +} - onConnect (abort, context) { - if (this.reason) { - abort(this.reason) - return - } +/** + * @see https://encoding.spec.whatwg.org/#decode + * @param {Uint8Array[]} ioQueue + * @param {string} encoding + */ +function decode (ioQueue, encoding) { + const bytes = combineByteSequences(ioQueue) - assert(this.callback) + // 1. Let BOMEncoding be the result of BOM sniffing ioQueue. + const BOMEncoding = BOMSniffing(bytes) - this.abort = abort - this.context = context - } + let slice = 0 - onHeaders () { - throw new SocketError('bad connect', null) + // 2. If BOMEncoding is non-null: + if (BOMEncoding !== null) { + // 1. Set encoding to BOMEncoding. + encoding = BOMEncoding + + // 2. Read three bytes from ioQueue, if BOMEncoding is + // UTF-8; otherwise read two bytes. + // (Do nothing with those bytes.) + slice = BOMEncoding === 'UTF-8' ? 3 : 2 } - onUpgrade (statusCode, rawHeaders, socket) { - const { callback, opaque, context } = this + // 3. Process a queue with an instance of encoding’s + // decoder, ioQueue, output, and "replacement". - removeSignal(this) + // 4. Return output. - this.callback = null + const sliced = bytes.slice(slice) + return new TextDecoder(encoding).decode(sliced) +} - let headers = rawHeaders - // Indicates is an HTTP2Session - if (headers != null) { - headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) - } +/** + * @see https://encoding.spec.whatwg.org/#bom-sniff + * @param {Uint8Array} ioQueue + */ +function BOMSniffing (ioQueue) { + // 1. Let BOM be the result of peeking 3 bytes from ioQueue, + // converted to a byte sequence. + const [a, b, c] = ioQueue - this.runInAsyncScope(callback, null, null, { - statusCode, - headers, - socket, - opaque, - context - }) + // 2. For each of the rows in the table below, starting with + // the first one and going down, if BOM starts with the + // bytes given in the first column, then return the + // encoding given in the cell in the second column of that + // row. Otherwise, return null. + if (a === 0xEF && b === 0xBB && c === 0xBF) { + return 'UTF-8' + } else if (a === 0xFE && b === 0xFF) { + return 'UTF-16BE' + } else if (a === 0xFF && b === 0xFE) { + return 'UTF-16LE' } - onError (err) { - const { callback, opaque } = this - - removeSignal(this) - - if (callback) { - this.callback = null - queueMicrotask(() => { - this.runInAsyncScope(callback, null, err, { opaque }) - }) - } - } + return null } -function connect (opts, callback) { - if (callback === undefined) { - return new Promise((resolve, reject) => { - connect.call(this, opts, (err, data) => { - return err ? reject(err) : resolve(data) - }) - }) - } +/** + * @param {Uint8Array[]} sequences + */ +function combineByteSequences (sequences) { + const size = sequences.reduce((a, b) => { + return a + b.byteLength + }, 0) - try { - const connectHandler = new ConnectHandler(opts, callback) - const connectOptions = { ...opts, method: 'CONNECT' } + let offset = 0 - this.dispatch(connectOptions, connectHandler) - } catch (err) { - if (typeof callback !== 'function') { - throw err - } - const opaque = opts?.opaque - queueMicrotask(() => callback(err, { opaque })) - } + return sequences.reduce((a, b) => { + a.set(b, offset) + offset += b.byteLength + return a + }, new Uint8Array(size)) } -module.exports = connect +module.exports = { + staticPropertyDescriptors, + readOperation, + fireAProgressEvent +} /***/ }), -/***/ 9715: +/***/ 9107: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; +const { uid, states, sentCloseFrameState, emptyBuffer, opcodes } = __nccwpck_require__(8850) const { - Readable, - Duplex, - PassThrough -} = __nccwpck_require__(7075) -const assert = __nccwpck_require__(4589) -const { AsyncResource } = __nccwpck_require__(6698) -const { - InvalidArgumentError, - InvalidReturnValueError, - RequestAbortedError -} = __nccwpck_require__(4928) -const util = __nccwpck_require__(983) -const { addSignal, removeSignal } = __nccwpck_require__(6851) - -function noop () {} + kReadyState, + kSentClose, + kByteParser, + kReceivedClose, + kResponse +} = __nccwpck_require__(6178) +const { fireEvent, failWebsocketConnection, isClosing, isClosed, isEstablished, parseExtensions } = __nccwpck_require__(5695) +const { channels } = __nccwpck_require__(7820) +const { CloseEvent } = __nccwpck_require__(8086) +const { makeRequest } = __nccwpck_require__(5417) +const { fetching } = __nccwpck_require__(5780) +const { Headers, getHeadersList } = __nccwpck_require__(217) +const { getDecodeSplit } = __nccwpck_require__(1046) +const { WebsocketFrameSend } = __nccwpck_require__(8298) -const kResume = Symbol('resume') +/** @type {import('crypto')} */ +let crypto +try { + crypto = __nccwpck_require__(7598) +/* c8 ignore next 3 */ +} catch { -class PipelineRequest extends Readable { - constructor () { - super({ autoDestroy: true }) +} - this[kResume] = null - } +/** + * @see https://websockets.spec.whatwg.org/#concept-websocket-establish + * @param {URL} url + * @param {string|string[]} protocols + * @param {import('./websocket').WebSocket} ws + * @param {(response: any, extensions: string[] | undefined) => void} onEstablish + * @param {Partial} options + */ +function establishWebSocketConnection (url, protocols, client, ws, onEstablish, options) { + // 1. Let requestURL be a copy of url, with its scheme set to "http", if url’s + // scheme is "ws", and to "https" otherwise. + const requestURL = url - _read () { - const { [kResume]: resume } = this + requestURL.protocol = url.protocol === 'ws:' ? 'http:' : 'https:' - if (resume) { - this[kResume] = null - resume() - } - } + // 2. Let request be a new request, whose URL is requestURL, client is client, + // service-workers mode is "none", referrer is "no-referrer", mode is + // "websocket", credentials mode is "include", cache mode is "no-store" , + // and redirect mode is "error". + const request = makeRequest({ + urlList: [requestURL], + client, + serviceWorkers: 'none', + referrer: 'no-referrer', + mode: 'websocket', + credentials: 'include', + cache: 'no-store', + redirect: 'error' + }) - _destroy (err, callback) { - this._read() + // Note: undici extension, allow setting custom headers. + if (options.headers) { + const headersList = getHeadersList(new Headers(options.headers)) - callback(err) + request.headersList = headersList } -} -class PipelineResponse extends Readable { - constructor (resume) { - super({ autoDestroy: true }) - this[kResume] = resume - } + // 3. Append (`Upgrade`, `websocket`) to request’s header list. + // 4. Append (`Connection`, `Upgrade`) to request’s header list. + // Note: both of these are handled by undici currently. + // https://github.com/nodejs/undici/blob/68c269c4144c446f3f1220951338daef4a6b5ec4/lib/client.js#L1397 - _read () { - this[kResume]() - } + // 5. Let keyValue be a nonce consisting of a randomly selected + // 16-byte value that has been forgiving-base64-encoded and + // isomorphic encoded. + const keyValue = crypto.randomBytes(16).toString('base64') - _destroy (err, callback) { - if (!err && !this._readableState.endEmitted) { - err = new RequestAbortedError() - } + // 6. Append (`Sec-WebSocket-Key`, keyValue) to request’s + // header list. + request.headersList.append('sec-websocket-key', keyValue) - callback(err) + // 7. Append (`Sec-WebSocket-Version`, `13`) to request’s + // header list. + request.headersList.append('sec-websocket-version', '13') + + // 8. For each protocol in protocols, combine + // (`Sec-WebSocket-Protocol`, protocol) in request’s header + // list. + for (const protocol of protocols) { + request.headersList.append('sec-websocket-protocol', protocol) } -} -class PipelineHandler extends AsyncResource { - constructor (opts, handler) { - if (!opts || typeof opts !== 'object') { - throw new InvalidArgumentError('invalid opts') - } + // 9. Let permessageDeflate be a user-agent defined + // "permessage-deflate" extension header value. + // https://github.com/mozilla/gecko-dev/blob/ce78234f5e653a5d3916813ff990f053510227bc/netwerk/protocol/websocket/WebSocketChannel.cpp#L2673 + const permessageDeflate = 'permessage-deflate; client_max_window_bits' - if (typeof handler !== 'function') { - throw new InvalidArgumentError('invalid handler') - } + // 10. Append (`Sec-WebSocket-Extensions`, permessageDeflate) to + // request’s header list. + request.headersList.append('sec-websocket-extensions', permessageDeflate) - const { signal, method, opaque, onInfo, responseHeaders } = opts + // 11. Fetch request with useParallelQueue set to true, and + // processResponse given response being these steps: + const controller = fetching({ + request, + useParallelQueue: true, + dispatcher: options.dispatcher, + processResponse (response) { + // 1. If response is a network error or its status is not 101, + // fail the WebSocket connection. + if (response.type === 'error' || response.status !== 101) { + failWebsocketConnection(ws, 'Received network error or non-101 status code.') + return + } - if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { - throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') - } + // 2. If protocols is not the empty list and extracting header + // list values given `Sec-WebSocket-Protocol` and response’s + // header list results in null, failure, or the empty byte + // sequence, then fail the WebSocket connection. + if (protocols.length !== 0 && !response.headersList.get('Sec-WebSocket-Protocol')) { + failWebsocketConnection(ws, 'Server did not respond with sent protocols.') + return + } - if (method === 'CONNECT') { - throw new InvalidArgumentError('invalid method') - } + // 3. Follow the requirements stated step 2 to step 6, inclusive, + // of the last set of steps in section 4.1 of The WebSocket + // Protocol to validate response. This either results in fail + // the WebSocket connection or the WebSocket connection is + // established. - if (onInfo && typeof onInfo !== 'function') { - throw new InvalidArgumentError('invalid onInfo callback') - } + // 2. If the response lacks an |Upgrade| header field or the |Upgrade| + // header field contains a value that is not an ASCII case- + // insensitive match for the value "websocket", the client MUST + // _Fail the WebSocket Connection_. + if (response.headersList.get('Upgrade')?.toLowerCase() !== 'websocket') { + failWebsocketConnection(ws, 'Server did not set Upgrade header to "websocket".') + return + } - super('UNDICI_PIPELINE') + // 3. If the response lacks a |Connection| header field or the + // |Connection| header field doesn't contain a token that is an + // ASCII case-insensitive match for the value "Upgrade", the client + // MUST _Fail the WebSocket Connection_. + if (response.headersList.get('Connection')?.toLowerCase() !== 'upgrade') { + failWebsocketConnection(ws, 'Server did not set Connection header to "upgrade".') + return + } - this.opaque = opaque || null - this.responseHeaders = responseHeaders || null - this.handler = handler - this.abort = null - this.context = null - this.onInfo = onInfo || null + // 4. If the response lacks a |Sec-WebSocket-Accept| header field or + // the |Sec-WebSocket-Accept| contains a value other than the + // base64-encoded SHA-1 of the concatenation of the |Sec-WebSocket- + // Key| (as a string, not base64-decoded) with the string "258EAFA5- + // E914-47DA-95CA-C5AB0DC85B11" but ignoring any leading and + // trailing whitespace, the client MUST _Fail the WebSocket + // Connection_. + const secWSAccept = response.headersList.get('Sec-WebSocket-Accept') + const digest = crypto.createHash('sha1').update(keyValue + uid).digest('base64') + if (secWSAccept !== digest) { + failWebsocketConnection(ws, 'Incorrect hash received in Sec-WebSocket-Accept header.') + return + } - this.req = new PipelineRequest().on('error', noop) + // 5. If the response includes a |Sec-WebSocket-Extensions| header + // field and this header field indicates the use of an extension + // that was not present in the client's handshake (the server has + // indicated an extension not requested by the client), the client + // MUST _Fail the WebSocket Connection_. (The parsing of this + // header field to determine which extensions are requested is + // discussed in Section 9.1.) + const secExtension = response.headersList.get('Sec-WebSocket-Extensions') + let extensions - this.ret = new Duplex({ - readableObjectMode: opts.objectMode, - autoDestroy: true, - read: () => { - const { body } = this + if (secExtension !== null) { + extensions = parseExtensions(secExtension) - if (body?.resume) { - body.resume() + if (!extensions.has('permessage-deflate')) { + failWebsocketConnection(ws, 'Sec-WebSocket-Extensions header does not match.') + return } - }, - write: (chunk, encoding, callback) => { - const { req } = this + } - if (req.push(chunk, encoding) || req._readableState.destroyed) { - callback() - } else { - req[kResume] = callback - } - }, - destroy: (err, callback) => { - const { body, req, res, ret, abort } = this + // 6. If the response includes a |Sec-WebSocket-Protocol| header field + // and this header field indicates the use of a subprotocol that was + // not present in the client's handshake (the server has indicated a + // subprotocol not requested by the client), the client MUST _Fail + // the WebSocket Connection_. + const secProtocol = response.headersList.get('Sec-WebSocket-Protocol') - if (!err && !ret._readableState.endEmitted) { - err = new RequestAbortedError() - } + if (secProtocol !== null) { + const requestProtocols = getDecodeSplit('sec-websocket-protocol', request.headersList) - if (abort && err) { - abort() + // The client can request that the server use a specific subprotocol by + // including the |Sec-WebSocket-Protocol| field in its handshake. If it + // is specified, the server needs to include the same field and one of + // the selected subprotocol values in its response for the connection to + // be established. + if (!requestProtocols.includes(secProtocol)) { + failWebsocketConnection(ws, 'Protocol was not set in the opening handshake.') + return } + } - util.destroy(body, err) - util.destroy(req, err) - util.destroy(res, err) - - removeSignal(this) + response.socket.on('data', onSocketData) + response.socket.on('close', onSocketClose) + response.socket.on('error', onSocketError) - callback(err) + if (channels.open.hasSubscribers) { + channels.open.publish({ + address: response.socket.address(), + protocol: secProtocol, + extensions: secExtension + }) } - }).on('prefinish', () => { - const { req } = this - // Node < 15 does not call _final in same tick. - req.push(null) - }) + onEstablish(response, extensions) + } + }) - this.res = null + return controller +} - addSignal(this, signal) - } +function closeWebSocketConnection (ws, code, reason, reasonByteLength) { + if (isClosing(ws) || isClosed(ws)) { + // If this's ready state is CLOSING (2) or CLOSED (3) + // Do nothing. + } else if (!isEstablished(ws)) { + // If the WebSocket connection is not yet established + // Fail the WebSocket connection and set this's ready state + // to CLOSING (2). + failWebsocketConnection(ws, 'Connection was closed before it was established.') + ws[kReadyState] = states.CLOSING + } else if (ws[kSentClose] === sentCloseFrameState.NOT_SENT) { + // If the WebSocket closing handshake has not yet been started + // Start the WebSocket closing handshake and set this's ready + // state to CLOSING (2). + // - If neither code nor reason is present, the WebSocket Close + // message must not have a body. + // - If code is present, then the status code to use in the + // WebSocket Close message must be the integer given by code. + // - If reason is also present, then reasonBytes must be + // provided in the Close message after the status code. + + ws[kSentClose] = sentCloseFrameState.PROCESSING - onConnect (abort, context) { - const { res } = this + const frame = new WebsocketFrameSend() - if (this.reason) { - abort(this.reason) - return + // If neither code nor reason is present, the WebSocket Close + // message must not have a body. + + // If code is present, then the status code to use in the + // WebSocket Close message must be the integer given by code. + if (code !== undefined && reason === undefined) { + frame.frameData = Buffer.allocUnsafe(2) + frame.frameData.writeUInt16BE(code, 0) + } else if (code !== undefined && reason !== undefined) { + // If reason is also present, then reasonBytes must be + // provided in the Close message after the status code. + frame.frameData = Buffer.allocUnsafe(2 + reasonByteLength) + frame.frameData.writeUInt16BE(code, 0) + // the body MAY contain UTF-8-encoded data with value /reason/ + frame.frameData.write(reason, 2, 'utf-8') + } else { + frame.frameData = emptyBuffer } - assert(!res, 'pipeline cannot be retried') + /** @type {import('stream').Duplex} */ + const socket = ws[kResponse].socket - this.abort = abort - this.context = context + socket.write(frame.createFrame(opcodes.CLOSE)) + + ws[kSentClose] = sentCloseFrameState.SENT + + // Upon either sending or receiving a Close control frame, it is said + // that _The WebSocket Closing Handshake is Started_ and that the + // WebSocket connection is in the CLOSING state. + ws[kReadyState] = states.CLOSING + } else { + // Otherwise + // Set this's ready state to CLOSING (2). + ws[kReadyState] = states.CLOSING } +} - onHeaders (statusCode, rawHeaders, resume) { - const { opaque, handler, context } = this +/** + * @param {Buffer} chunk + */ +function onSocketData (chunk) { + if (!this.ws[kByteParser].write(chunk)) { + this.pause() + } +} - if (statusCode < 200) { - if (this.onInfo) { - const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) - this.onInfo({ statusCode, headers }) - } - return - } +/** + * @see https://websockets.spec.whatwg.org/#feedback-from-the-protocol + * @see https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.4 + */ +function onSocketClose () { + const { ws } = this + const { [kResponse]: response } = ws - this.res = new PipelineResponse(resume) + response.socket.off('data', onSocketData) + response.socket.off('close', onSocketClose) + response.socket.off('error', onSocketError) - let body - try { - this.handler = null - const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) - body = this.runInAsyncScope(handler, null, { - statusCode, - headers, - opaque, - body: this.res, - context - }) - } catch (err) { - this.res.on('error', noop) - throw err - } + // If the TCP connection was closed after the + // WebSocket closing handshake was completed, the WebSocket connection + // is said to have been closed _cleanly_. + const wasClean = ws[kSentClose] === sentCloseFrameState.SENT && ws[kReceivedClose] - if (!body || typeof body.on !== 'function') { - throw new InvalidReturnValueError('expected Readable') - } + let code = 1005 + let reason = '' - body - .on('data', (chunk) => { - const { ret, body } = this + const result = ws[kByteParser].closingInfo - if (!ret.push(chunk) && body.pause) { - body.pause() - } - }) - .on('error', (err) => { - const { ret } = this + if (result && !result.error) { + code = result.code ?? 1005 + reason = result.reason + } else if (!ws[kReceivedClose]) { + // If _The WebSocket + // Connection is Closed_ and no Close control frame was received by the + // endpoint (such as could occur if the underlying transport connection + // is lost), _The WebSocket Connection Close Code_ is considered to be + // 1006. + code = 1006 + } - util.destroy(ret, err) - }) - .on('end', () => { - const { ret } = this + // 1. Change the ready state to CLOSED (3). + ws[kReadyState] = states.CLOSED - ret.push(null) - }) - .on('close', () => { - const { ret } = this + // 2. If the user agent was required to fail the WebSocket + // connection, or if the WebSocket connection was closed + // after being flagged as full, fire an event named error + // at the WebSocket object. + // TODO - if (!ret._readableState.ended) { - util.destroy(ret, new RequestAbortedError()) - } - }) + // 3. Fire an event named close at the WebSocket object, + // using CloseEvent, with the wasClean attribute + // initialized to true if the connection closed cleanly + // and false otherwise, the code attribute initialized to + // the WebSocket connection close code, and the reason + // attribute initialized to the result of applying UTF-8 + // decode without BOM to the WebSocket connection close + // reason. + // TODO: process.nextTick + fireEvent('close', ws, (type, init) => new CloseEvent(type, init), { + wasClean, code, reason + }) - this.body = body + if (channels.close.hasSubscribers) { + channels.close.publish({ + websocket: ws, + code, + reason + }) } +} - onData (chunk) { - const { res } = this - return res.push(chunk) - } +function onSocketError (error) { + const { ws } = this - onComplete (trailers) { - const { res } = this - res.push(null) - } + ws[kReadyState] = states.CLOSING - onError (err) { - const { ret } = this - this.handler = null - util.destroy(ret, err) + if (channels.socketError.hasSubscribers) { + channels.socketError.publish(error) } -} -function pipeline (opts, handler) { - try { - const pipelineHandler = new PipelineHandler(opts, handler) - this.dispatch({ ...opts, body: pipelineHandler.req }, pipelineHandler) - return pipelineHandler.ret - } catch (err) { - return new PassThrough().destroy(err) - } + this.destroy() } -module.exports = pipeline +module.exports = { + establishWebSocketConnection, + closeWebSocketConnection +} /***/ }), -/***/ 6388: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +/***/ 8850: +/***/ ((module) => { -"use strict"; -const assert = __nccwpck_require__(4589) -const { AsyncResource } = __nccwpck_require__(6698) -const { Readable } = __nccwpck_require__(498) -const { InvalidArgumentError, RequestAbortedError } = __nccwpck_require__(4928) -const util = __nccwpck_require__(983) +// This is a Globally Unique Identifier unique used +// to validate that the endpoint accepts websocket +// connections. +// See https://www.rfc-editor.org/rfc/rfc6455.html#section-1.3 +const uid = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11' -function noop () {} +/** @type {PropertyDescriptor} */ +const staticPropertyDescriptors = { + enumerable: true, + writable: false, + configurable: false +} -class RequestHandler extends AsyncResource { - constructor (opts, callback) { - if (!opts || typeof opts !== 'object') { - throw new InvalidArgumentError('invalid opts') - } +const states = { + CONNECTING: 0, + OPEN: 1, + CLOSING: 2, + CLOSED: 3 +} - const { signal, method, opaque, body, onInfo, responseHeaders, highWaterMark } = opts +const sentCloseFrameState = { + NOT_SENT: 0, + PROCESSING: 1, + SENT: 2 +} - try { - if (typeof callback !== 'function') { - throw new InvalidArgumentError('invalid callback') - } +const opcodes = { + CONTINUATION: 0x0, + TEXT: 0x1, + BINARY: 0x2, + CLOSE: 0x8, + PING: 0x9, + PONG: 0xA +} - if (highWaterMark && (typeof highWaterMark !== 'number' || highWaterMark < 0)) { - throw new InvalidArgumentError('invalid highWaterMark') - } +const maxUnsigned16Bit = 2 ** 16 - 1 // 65535 - if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { - throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') - } +const parserStates = { + INFO: 0, + PAYLOADLENGTH_16: 2, + PAYLOADLENGTH_64: 3, + READ_DATA: 4 +} - if (method === 'CONNECT') { - throw new InvalidArgumentError('invalid method') - } +const emptyBuffer = Buffer.allocUnsafe(0) - if (onInfo && typeof onInfo !== 'function') { - throw new InvalidArgumentError('invalid onInfo callback') - } +const sendHints = { + string: 1, + typedArray: 2, + arrayBuffer: 3, + blob: 4 +} - super('UNDICI_REQUEST') - } catch (err) { - if (util.isStream(body)) { - util.destroy(body.on('error', noop), err) - } - throw err - } +module.exports = { + uid, + sentCloseFrameState, + staticPropertyDescriptors, + states, + opcodes, + maxUnsigned16Bit, + parserStates, + emptyBuffer, + sendHints +} - this.method = method - this.responseHeaders = responseHeaders || null - this.opaque = opaque || null - this.callback = callback - this.res = null - this.abort = null - this.body = body - this.trailers = {} - this.context = null - this.onInfo = onInfo || null - this.highWaterMark = highWaterMark - this.reason = null - this.removeAbortListener = null - if (signal?.aborted) { - this.reason = signal.reason ?? new RequestAbortedError() - } else if (signal) { - this.removeAbortListener = util.addAbortListener(signal, () => { - this.reason = signal.reason ?? new RequestAbortedError() - if (this.res) { - util.destroy(this.res.on('error', noop), this.reason) - } else if (this.abort) { - this.abort(this.reason) - } - }) - } - } +/***/ }), - onConnect (abort, context) { - if (this.reason) { - abort(this.reason) - return - } +/***/ 8086: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - assert(this.callback) - this.abort = abort - this.context = context - } - onHeaders (statusCode, rawHeaders, resume, statusMessage) { - const { callback, opaque, abort, context, responseHeaders, highWaterMark } = this +const { webidl } = __nccwpck_require__(4859) +const { kEnumerableProperty } = __nccwpck_require__(7234) +const { kConstruct } = __nccwpck_require__(7417) +const { MessagePort } = __nccwpck_require__(5919) - const headers = responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) +/** + * @see https://html.spec.whatwg.org/multipage/comms.html#messageevent + */ +class MessageEvent extends Event { + #eventInit - if (statusCode < 200) { - if (this.onInfo) { - this.onInfo({ statusCode, headers }) - } + constructor (type, eventInitDict = {}) { + if (type === kConstruct) { + super(arguments[1], arguments[2]) + webidl.util.markAsUncloneable(this) return } - const parsedHeaders = responseHeaders === 'raw' ? util.parseHeaders(rawHeaders) : headers - const contentType = parsedHeaders['content-type'] - const contentLength = parsedHeaders['content-length'] - const res = new Readable({ - resume, - abort, - contentType, - contentLength: this.method !== 'HEAD' && contentLength - ? Number(contentLength) - : null, - highWaterMark - }) - - if (this.removeAbortListener) { - res.on('close', this.removeAbortListener) - this.removeAbortListener = null - } + const prefix = 'MessageEvent constructor' + webidl.argumentLengthCheck(arguments, 1, prefix) - this.callback = null - this.res = res - if (callback !== null) { - try { - this.runInAsyncScope(callback, null, null, { - statusCode, - headers, - trailers: this.trailers, - opaque, - body: res, - context - }) - } catch (err) { - // If the callback throws synchronously, we need to handle it - // Remove reference to res to allow res being garbage collected - this.res = null + type = webidl.converters.DOMString(type, prefix, 'type') + eventInitDict = webidl.converters.MessageEventInit(eventInitDict, prefix, 'eventInitDict') - // Destroy the response stream - util.destroy(res.on('error', noop), err) + super(type, eventInitDict) - // Use queueMicrotask to re-throw the error so it reaches uncaughtException - queueMicrotask(() => { - throw err - }) - } - } + this.#eventInit = eventInitDict + webidl.util.markAsUncloneable(this) } - onData (chunk) { - return this.res.push(chunk) + get data () { + webidl.brandCheck(this, MessageEvent) + + return this.#eventInit.data } - onComplete (trailers) { - util.parseHeaders(trailers, this.trailers) - this.res.push(null) + get origin () { + webidl.brandCheck(this, MessageEvent) + + return this.#eventInit.origin } - onError (err) { - const { res, callback, body, opaque } = this + get lastEventId () { + webidl.brandCheck(this, MessageEvent) - if (callback) { - // TODO: Does this need queueMicrotask? - this.callback = null - queueMicrotask(() => { - this.runInAsyncScope(callback, null, err, { opaque }) - }) - } + return this.#eventInit.lastEventId + } - if (res) { - this.res = null - // Ensure all queued handlers are invoked before destroying res. - queueMicrotask(() => { - util.destroy(res.on('error', noop), err) - }) - } + get source () { + webidl.brandCheck(this, MessageEvent) - if (body) { - this.body = null + return this.#eventInit.source + } - if (util.isStream(body)) { - body.on('error', noop) - util.destroy(body, err) - } - } + get ports () { + webidl.brandCheck(this, MessageEvent) - if (this.removeAbortListener) { - this.removeAbortListener() - this.removeAbortListener = null + if (!Object.isFrozen(this.#eventInit.ports)) { + Object.freeze(this.#eventInit.ports) } + + return this.#eventInit.ports } -} -function request (opts, callback) { - if (callback === undefined) { - return new Promise((resolve, reject) => { - request.call(this, opts, (err, data) => { - return err ? reject(err) : resolve(data) - }) + initMessageEvent ( + type, + bubbles = false, + cancelable = false, + data = null, + origin = '', + lastEventId = '', + source = null, + ports = [] + ) { + webidl.brandCheck(this, MessageEvent) + + webidl.argumentLengthCheck(arguments, 1, 'MessageEvent.initMessageEvent') + + return new MessageEvent(type, { + bubbles, cancelable, data, origin, lastEventId, source, ports }) } - try { - const handler = new RequestHandler(opts, callback) - - this.dispatch(opts, handler) - } catch (err) { - if (typeof callback !== 'function') { - throw err - } - const opaque = opts?.opaque - queueMicrotask(() => callback(err, { opaque })) + static createFastMessageEvent (type, init) { + const messageEvent = new MessageEvent(kConstruct, type, init) + messageEvent.#eventInit = init + messageEvent.#eventInit.data ??= null + messageEvent.#eventInit.origin ??= '' + messageEvent.#eventInit.lastEventId ??= '' + messageEvent.#eventInit.source ??= null + messageEvent.#eventInit.ports ??= [] + return messageEvent } } -module.exports = request -module.exports.RequestHandler = RequestHandler - - -/***/ }), +const { createFastMessageEvent } = MessageEvent +delete MessageEvent.createFastMessageEvent -/***/ 757: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +/** + * @see https://websockets.spec.whatwg.org/#the-closeevent-interface + */ +class CloseEvent extends Event { + #eventInit -"use strict"; + constructor (type, eventInitDict = {}) { + const prefix = 'CloseEvent constructor' + webidl.argumentLengthCheck(arguments, 1, prefix) + type = webidl.converters.DOMString(type, prefix, 'type') + eventInitDict = webidl.converters.CloseEventInit(eventInitDict) -const assert = __nccwpck_require__(4589) -const { finished } = __nccwpck_require__(7075) -const { AsyncResource } = __nccwpck_require__(6698) -const { InvalidArgumentError, InvalidReturnValueError } = __nccwpck_require__(4928) -const util = __nccwpck_require__(983) -const { addSignal, removeSignal } = __nccwpck_require__(6851) + super(type, eventInitDict) -function noop () {} + this.#eventInit = eventInitDict + webidl.util.markAsUncloneable(this) + } -class StreamHandler extends AsyncResource { - constructor (opts, factory, callback) { - if (!opts || typeof opts !== 'object') { - throw new InvalidArgumentError('invalid opts') - } + get wasClean () { + webidl.brandCheck(this, CloseEvent) - const { signal, method, opaque, body, onInfo, responseHeaders } = opts + return this.#eventInit.wasClean + } - try { - if (typeof callback !== 'function') { - throw new InvalidArgumentError('invalid callback') - } + get code () { + webidl.brandCheck(this, CloseEvent) - if (typeof factory !== 'function') { - throw new InvalidArgumentError('invalid factory') - } + return this.#eventInit.code + } - if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { - throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') - } + get reason () { + webidl.brandCheck(this, CloseEvent) - if (method === 'CONNECT') { - throw new InvalidArgumentError('invalid method') - } + return this.#eventInit.reason + } +} - if (onInfo && typeof onInfo !== 'function') { - throw new InvalidArgumentError('invalid onInfo callback') - } +// https://html.spec.whatwg.org/multipage/webappapis.html#the-errorevent-interface +class ErrorEvent extends Event { + #eventInit - super('UNDICI_STREAM') - } catch (err) { - if (util.isStream(body)) { - util.destroy(body.on('error', noop), err) - } - throw err - } + constructor (type, eventInitDict) { + const prefix = 'ErrorEvent constructor' + webidl.argumentLengthCheck(arguments, 1, prefix) - this.responseHeaders = responseHeaders || null - this.opaque = opaque || null - this.factory = factory - this.callback = callback - this.res = null - this.abort = null - this.context = null - this.trailers = null - this.body = body - this.onInfo = onInfo || null + super(type, eventInitDict) + webidl.util.markAsUncloneable(this) - if (util.isStream(body)) { - body.on('error', (err) => { - this.onError(err) - }) - } + type = webidl.converters.DOMString(type, prefix, 'type') + eventInitDict = webidl.converters.ErrorEventInit(eventInitDict ?? {}) - addSignal(this, signal) + this.#eventInit = eventInitDict } - onConnect (abort, context) { - if (this.reason) { - abort(this.reason) - return - } - - assert(this.callback) + get message () { + webidl.brandCheck(this, ErrorEvent) - this.abort = abort - this.context = context + return this.#eventInit.message } - onHeaders (statusCode, rawHeaders, resume, statusMessage) { - const { factory, opaque, context, responseHeaders } = this + get filename () { + webidl.brandCheck(this, ErrorEvent) - const headers = responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) + return this.#eventInit.filename + } - if (statusCode < 200) { - if (this.onInfo) { - this.onInfo({ statusCode, headers }) - } - return - } + get lineno () { + webidl.brandCheck(this, ErrorEvent) - this.factory = null + return this.#eventInit.lineno + } - if (factory === null) { - return - } + get colno () { + webidl.brandCheck(this, ErrorEvent) - const res = this.runInAsyncScope(factory, null, { - statusCode, - headers, - opaque, - context - }) + return this.#eventInit.colno + } - if ( - !res || - typeof res.write !== 'function' || - typeof res.end !== 'function' || - typeof res.on !== 'function' - ) { - throw new InvalidReturnValueError('expected Writable') - } + get error () { + webidl.brandCheck(this, ErrorEvent) - // TODO: Avoid finished. It registers an unnecessary amount of listeners. - finished(res, { readable: false }, (err) => { - const { callback, res, opaque, trailers, abort } = this + return this.#eventInit.error + } +} - this.res = null - if (err || !res?.readable) { - util.destroy(res, err) - } +Object.defineProperties(MessageEvent.prototype, { + [Symbol.toStringTag]: { + value: 'MessageEvent', + configurable: true + }, + data: kEnumerableProperty, + origin: kEnumerableProperty, + lastEventId: kEnumerableProperty, + source: kEnumerableProperty, + ports: kEnumerableProperty, + initMessageEvent: kEnumerableProperty +}) - this.callback = null - this.runInAsyncScope(callback, null, err || null, { opaque, trailers }) +Object.defineProperties(CloseEvent.prototype, { + [Symbol.toStringTag]: { + value: 'CloseEvent', + configurable: true + }, + reason: kEnumerableProperty, + code: kEnumerableProperty, + wasClean: kEnumerableProperty +}) - if (err) { - abort() - } - }) +Object.defineProperties(ErrorEvent.prototype, { + [Symbol.toStringTag]: { + value: 'ErrorEvent', + configurable: true + }, + message: kEnumerableProperty, + filename: kEnumerableProperty, + lineno: kEnumerableProperty, + colno: kEnumerableProperty, + error: kEnumerableProperty +}) - res.on('drain', resume) +webidl.converters.MessagePort = webidl.interfaceConverter(MessagePort) - this.res = res +webidl.converters['sequence'] = webidl.sequenceConverter( + webidl.converters.MessagePort +) - const needDrain = res.writableNeedDrain !== undefined - ? res.writableNeedDrain - : res._writableState?.needDrain +const eventInit = [ + { + key: 'bubbles', + converter: webidl.converters.boolean, + defaultValue: () => false + }, + { + key: 'cancelable', + converter: webidl.converters.boolean, + defaultValue: () => false + }, + { + key: 'composed', + converter: webidl.converters.boolean, + defaultValue: () => false + } +] - return needDrain !== true +webidl.converters.MessageEventInit = webidl.dictionaryConverter([ + ...eventInit, + { + key: 'data', + converter: webidl.converters.any, + defaultValue: () => null + }, + { + key: 'origin', + converter: webidl.converters.USVString, + defaultValue: () => '' + }, + { + key: 'lastEventId', + converter: webidl.converters.DOMString, + defaultValue: () => '' + }, + { + key: 'source', + // Node doesn't implement WindowProxy or ServiceWorker, so the only + // valid value for source is a MessagePort. + converter: webidl.nullableConverter(webidl.converters.MessagePort), + defaultValue: () => null + }, + { + key: 'ports', + converter: webidl.converters['sequence'], + defaultValue: () => new Array(0) } +]) - onData (chunk) { - const { res } = this +webidl.converters.CloseEventInit = webidl.dictionaryConverter([ + ...eventInit, + { + key: 'wasClean', + converter: webidl.converters.boolean, + defaultValue: () => false + }, + { + key: 'code', + converter: webidl.converters['unsigned short'], + defaultValue: () => 0 + }, + { + key: 'reason', + converter: webidl.converters.USVString, + defaultValue: () => '' + } +]) - return res ? res.write(chunk) : true +webidl.converters.ErrorEventInit = webidl.dictionaryConverter([ + ...eventInit, + { + key: 'message', + converter: webidl.converters.DOMString, + defaultValue: () => '' + }, + { + key: 'filename', + converter: webidl.converters.USVString, + defaultValue: () => '' + }, + { + key: 'lineno', + converter: webidl.converters['unsigned long'], + defaultValue: () => 0 + }, + { + key: 'colno', + converter: webidl.converters['unsigned long'], + defaultValue: () => 0 + }, + { + key: 'error', + converter: webidl.converters.any } +]) - onComplete (trailers) { - const { res } = this +module.exports = { + MessageEvent, + CloseEvent, + ErrorEvent, + createFastMessageEvent +} - removeSignal(this) - if (!res) { - return - } +/***/ }), - this.trailers = util.parseHeaders(trailers) +/***/ 8298: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - res.end() - } - onError (err) { - const { res, callback, opaque, body } = this - removeSignal(this) +const { maxUnsigned16Bit } = __nccwpck_require__(8850) - this.factory = null +const BUFFER_SIZE = 16386 - if (res) { - this.res = null - util.destroy(res, err) - } else if (callback) { - this.callback = null - queueMicrotask(() => { - this.runInAsyncScope(callback, null, err, { opaque }) - }) - } +/** @type {import('crypto')} */ +let crypto +let buffer = null +let bufIdx = BUFFER_SIZE - if (body) { - this.body = null - util.destroy(body, err) +try { + crypto = __nccwpck_require__(7598) +/* c8 ignore next 3 */ +} catch { + crypto = { + // not full compatibility, but minimum. + randomFillSync: function randomFillSync (buffer, _offset, _size) { + for (let i = 0; i < buffer.length; ++i) { + buffer[i] = Math.random() * 255 | 0 + } + return buffer } } } -function stream (opts, factory, callback) { - if (callback === undefined) { - return new Promise((resolve, reject) => { - stream.call(this, opts, factory, (err, data) => { - return err ? reject(err) : resolve(data) - }) - }) +function generateMask () { + if (bufIdx === BUFFER_SIZE) { + bufIdx = 0 + crypto.randomFillSync((buffer ??= Buffer.allocUnsafe(BUFFER_SIZE)), 0, BUFFER_SIZE) } + return [buffer[bufIdx++], buffer[bufIdx++], buffer[bufIdx++], buffer[bufIdx++]] +} - try { - const handler = new StreamHandler(opts, factory, callback) - - this.dispatch(opts, handler) - } catch (err) { - if (typeof callback !== 'function') { - throw err - } - const opaque = opts?.opaque - queueMicrotask(() => callback(err, { opaque })) +class WebsocketFrameSend { + /** + * @param {Buffer|undefined} data + */ + constructor (data) { + this.frameData = data } -} -module.exports = stream + createFrame (opcode) { + const frameData = this.frameData + const maskKey = generateMask() + const bodyLength = frameData?.byteLength ?? 0 + /** @type {number} */ + let payloadLength = bodyLength // 0-125 + let offset = 6 -/***/ }), - -/***/ 6901: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + if (bodyLength > maxUnsigned16Bit) { + offset += 8 // payload length is next 8 bytes + payloadLength = 127 + } else if (bodyLength > 125) { + offset += 2 // payload length is next 2 bytes + payloadLength = 126 + } -"use strict"; + const buffer = Buffer.allocUnsafe(bodyLength + offset) + // Clear first 2 bytes, everything else is overwritten + buffer[0] = buffer[1] = 0 + buffer[0] |= 0x80 // FIN + buffer[0] = (buffer[0] & 0xF0) + opcode // opcode -const { InvalidArgumentError, SocketError } = __nccwpck_require__(4928) -const { AsyncResource } = __nccwpck_require__(6698) -const assert = __nccwpck_require__(4589) -const util = __nccwpck_require__(983) -const { kHTTP2Stream } = __nccwpck_require__(9562) -const { addSignal, removeSignal } = __nccwpck_require__(6851) + /*! ws. MIT License. Einar Otto Stangvik */ + buffer[offset - 4] = maskKey[0] + buffer[offset - 3] = maskKey[1] + buffer[offset - 2] = maskKey[2] + buffer[offset - 1] = maskKey[3] -class UpgradeHandler extends AsyncResource { - constructor (opts, callback) { - if (!opts || typeof opts !== 'object') { - throw new InvalidArgumentError('invalid opts') - } + buffer[1] = payloadLength - if (typeof callback !== 'function') { - throw new InvalidArgumentError('invalid callback') + if (payloadLength === 126) { + buffer.writeUInt16BE(bodyLength, 2) + } else if (payloadLength === 127) { + // Clear extended payload length + buffer[2] = buffer[3] = 0 + buffer.writeUIntBE(bodyLength, 4, 6) } - const { signal, opaque, responseHeaders } = opts + buffer[1] |= 0x80 // MASK - if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { - throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') + // mask body + for (let i = 0; i < bodyLength; ++i) { + buffer[offset + i] = frameData[i] ^ maskKey[i & 3] } - super('UNDICI_UPGRADE') + return buffer + } +} - this.responseHeaders = responseHeaders || null - this.opaque = opaque || null - this.callback = callback - this.abort = null - this.context = null +module.exports = { + WebsocketFrameSend +} - addSignal(this, signal) - } - onConnect (abort, context) { - if (this.reason) { - abort(this.reason) - return - } +/***/ }), - assert(this.callback) +/***/ 1031: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - this.abort = abort - this.context = null - } - onHeaders () { - throw new SocketError('bad upgrade', null) - } - onUpgrade (statusCode, rawHeaders, socket) { - assert(socket[kHTTP2Stream] === true ? statusCode === 200 : statusCode === 101) +const { createInflateRaw, Z_DEFAULT_WINDOWBITS } = __nccwpck_require__(8522) +const { isValidClientWindowBits } = __nccwpck_require__(5695) - const { callback, opaque, context } = this +const tail = Buffer.from([0x00, 0x00, 0xff, 0xff]) +const kBuffer = Symbol('kBuffer') +const kLength = Symbol('kLength') - removeSignal(this) +class PerMessageDeflate { + /** @type {import('node:zlib').InflateRaw} */ + #inflate - this.callback = null - const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) - this.runInAsyncScope(callback, null, null, { - headers, - socket, - opaque, - context - }) + #options = {} + + constructor (extensions) { + this.#options.serverNoContextTakeover = extensions.has('server_no_context_takeover') + this.#options.serverMaxWindowBits = extensions.get('server_max_window_bits') } - onError (err) { - const { callback, opaque } = this + decompress (chunk, fin, callback) { + // An endpoint uses the following algorithm to decompress a message. + // 1. Append 4 octets of 0x00 0x00 0xff 0xff to the tail end of the + // payload of the message. + // 2. Decompress the resulting data using DEFLATE. - removeSignal(this) + if (!this.#inflate) { + let windowBits = Z_DEFAULT_WINDOWBITS - if (callback) { - this.callback = null - queueMicrotask(() => { - this.runInAsyncScope(callback, null, err, { opaque }) - }) - } - } -} + if (this.#options.serverMaxWindowBits) { // empty values default to Z_DEFAULT_WINDOWBITS + if (!isValidClientWindowBits(this.#options.serverMaxWindowBits)) { + callback(new Error('Invalid server_max_window_bits')) + return + } -function upgrade (opts, callback) { - if (callback === undefined) { - return new Promise((resolve, reject) => { - upgrade.call(this, opts, (err, data) => { - return err ? reject(err) : resolve(data) + windowBits = Number.parseInt(this.#options.serverMaxWindowBits) + } + + this.#inflate = createInflateRaw({ windowBits }) + this.#inflate[kBuffer] = [] + this.#inflate[kLength] = 0 + + this.#inflate.on('data', (data) => { + this.#inflate[kBuffer].push(data) + this.#inflate[kLength] += data.length }) - }) - } - try { - const upgradeHandler = new UpgradeHandler(opts, callback) - const upgradeOpts = { - ...opts, - method: opts.method || 'GET', - upgrade: opts.protocol || 'Websocket' + this.#inflate.on('error', (err) => { + this.#inflate = null + callback(err) + }) } - this.dispatch(upgradeOpts, upgradeHandler) - } catch (err) { - if (typeof callback !== 'function') { - throw err + this.#inflate.write(chunk) + if (fin) { + this.#inflate.write(tail) } - const opaque = opts?.opaque - queueMicrotask(() => callback(err, { opaque })) + + this.#inflate.flush(() => { + const full = Buffer.concat(this.#inflate[kBuffer], this.#inflate[kLength]) + + this.#inflate[kBuffer].length = 0 + this.#inflate[kLength] = 0 + + callback(null, full) + }) } } -module.exports = upgrade +module.exports = { PerMessageDeflate } /***/ }), -/***/ 2812: +/***/ 3274: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -module.exports.request = __nccwpck_require__(6388) -module.exports.stream = __nccwpck_require__(757) -module.exports.pipeline = __nccwpck_require__(9715) -module.exports.upgrade = __nccwpck_require__(6901) -module.exports.connect = __nccwpck_require__(4031) +const { Writable } = __nccwpck_require__(7075) +const assert = __nccwpck_require__(4589) +const { parserStates, opcodes, states, emptyBuffer, sentCloseFrameState } = __nccwpck_require__(8850) +const { kReadyState, kSentClose, kResponse, kReceivedClose } = __nccwpck_require__(6178) +const { channels } = __nccwpck_require__(7820) +const { + isValidStatusCode, + isValidOpcode, + failWebsocketConnection, + websocketMessageReceived, + utf8Decode, + isControlFrame, + isTextBinaryFrame, + isContinuationFrame +} = __nccwpck_require__(5695) +const { WebsocketFrameSend } = __nccwpck_require__(8298) +const { closeWebSocketConnection } = __nccwpck_require__(9107) +const { PerMessageDeflate } = __nccwpck_require__(1031) +// This code was influenced by ws released under the MIT license. +// Copyright (c) 2011 Einar Otto Stangvik +// Copyright (c) 2013 Arnout Kazemier and contributors +// Copyright (c) 2016 Luigi Pinca and contributors -/***/ }), +class ByteParser extends Writable { + #buffers = [] + #byteOffset = 0 + #loop = false -/***/ 498: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + #state = parserStates.INFO -"use strict"; + #info = {} + #fragments = [] + /** @type {Map} */ + #extensions -const assert = __nccwpck_require__(4589) -const { Readable } = __nccwpck_require__(7075) -const { RequestAbortedError, NotSupportedError, InvalidArgumentError, AbortError } = __nccwpck_require__(4928) -const util = __nccwpck_require__(983) -const { ReadableStreamFrom } = __nccwpck_require__(983) + constructor (ws, extensions) { + super() -const kConsume = Symbol('kConsume') -const kReading = Symbol('kReading') -const kBody = Symbol('kBody') -const kAbort = Symbol('kAbort') -const kContentType = Symbol('kContentType') -const kContentLength = Symbol('kContentLength') -const kUsed = Symbol('kUsed') -const kBytesRead = Symbol('kBytesRead') + this.ws = ws + this.#extensions = extensions == null ? new Map() : extensions -const noop = () => {} + if (this.#extensions.has('permessage-deflate')) { + this.#extensions.set('permessage-deflate', new PerMessageDeflate(extensions)) + } + } -/** - * @class - * @extends {Readable} - * @see https://fetch.spec.whatwg.org/#body - */ -class BodyReadable extends Readable { /** - * @param {object} opts - * @param {(this: Readable, size: number) => void} opts.resume - * @param {() => (void | null)} opts.abort - * @param {string} [opts.contentType = ''] - * @param {number} [opts.contentLength] - * @param {number} [opts.highWaterMark = 64 * 1024] + * @param {Buffer} chunk + * @param {() => void} callback */ - constructor ({ - resume, - abort, - contentType = '', - contentLength, - highWaterMark = 64 * 1024 // Same as nodejs fs streams. - }) { - super({ - autoDestroy: true, - read: resume, - highWaterMark - }) + _write (chunk, _, callback) { + this.#buffers.push(chunk) + this.#byteOffset += chunk.length + this.#loop = true - this._readableState.dataEmitted = false + this.run(callback) + } - this[kAbort] = abort + /** + * Runs whenever a new chunk is received. + * Callback is called whenever there are no more chunks buffering, + * or not enough bytes are buffered to parse. + */ + run (callback) { + while (this.#loop) { + if (this.#state === parserStates.INFO) { + // If there aren't enough bytes to parse the payload length, etc. + if (this.#byteOffset < 2) { + return callback() + } - /** @type {Consume | null} */ - this[kConsume] = null + const buffer = this.consume(2) + const fin = (buffer[0] & 0x80) !== 0 + const opcode = buffer[0] & 0x0F + const masked = (buffer[1] & 0x80) === 0x80 - /** @type {number} */ - this[kBytesRead] = 0 + const fragmented = !fin && opcode !== opcodes.CONTINUATION + const payloadLength = buffer[1] & 0x7F - /** @type {ReadableStream|null} */ - this[kBody] = null + const rsv1 = buffer[0] & 0x40 + const rsv2 = buffer[0] & 0x20 + const rsv3 = buffer[0] & 0x10 - /** @type {boolean} */ - this[kUsed] = false + if (!isValidOpcode(opcode)) { + failWebsocketConnection(this.ws, 'Invalid opcode received') + return callback() + } - /** @type {string} */ - this[kContentType] = contentType + if (masked) { + failWebsocketConnection(this.ws, 'Frame cannot be masked') + return callback() + } - /** @type {number|null} */ - this[kContentLength] = Number.isFinite(contentLength) ? contentLength : null + // MUST be 0 unless an extension is negotiated that defines meanings + // for non-zero values. If a nonzero value is received and none of + // the negotiated extensions defines the meaning of such a nonzero + // value, the receiving endpoint MUST _Fail the WebSocket + // Connection_. + // This document allocates the RSV1 bit of the WebSocket header for + // PMCEs and calls the bit the "Per-Message Compressed" bit. On a + // WebSocket connection where a PMCE is in use, this bit indicates + // whether a message is compressed or not. + if (rsv1 !== 0 && !this.#extensions.has('permessage-deflate')) { + failWebsocketConnection(this.ws, 'Expected RSV1 to be clear.') + return + } - /** - * Is stream being consumed through Readable API? - * This is an optimization so that we avoid checking - * for 'data' and 'readable' listeners in the hot path - * inside push(). - * - * @type {boolean} - */ - this[kReading] = false - } + if (rsv2 !== 0 || rsv3 !== 0) { + failWebsocketConnection(this.ws, 'RSV1, RSV2, RSV3 must be clear') + return + } - /** - * @param {Error|null} err - * @param {(error:(Error|null)) => void} callback - * @returns {void} - */ - _destroy (err, callback) { - if (!err && !this._readableState.endEmitted) { - err = new RequestAbortedError() - } + if (fragmented && !isTextBinaryFrame(opcode)) { + // Only text and binary frames can be fragmented + failWebsocketConnection(this.ws, 'Invalid frame type was fragmented.') + return + } - if (err) { - this[kAbort]() - } + // If we are already parsing a text/binary frame and do not receive either + // a continuation frame or close frame, fail the connection. + if (isTextBinaryFrame(opcode) && this.#fragments.length > 0) { + failWebsocketConnection(this.ws, 'Expected continuation frame') + return + } - // Workaround for Node "bug". If the stream is destroyed in same - // tick as it is created, then a user who is waiting for a - // promise (i.e micro tick) for installing an 'error' listener will - // never get a chance and will always encounter an unhandled exception. - if (!this[kUsed]) { - setImmediate(callback, err) - } else { - callback(err) - } - } + if (this.#info.fragmented && fragmented) { + // A fragmented frame can't be fragmented itself + failWebsocketConnection(this.ws, 'Fragmented frame exceeded 125 bytes.') + return + } - /** - * @param {string|symbol} event - * @param {(...args: any[]) => void} listener - * @returns {this} - */ - on (event, listener) { - if (event === 'data' || event === 'readable') { - this[kReading] = true - this[kUsed] = true - } - return super.on(event, listener) - } + // "All control frames MUST have a payload length of 125 bytes or less + // and MUST NOT be fragmented." + if ((payloadLength > 125 || fragmented) && isControlFrame(opcode)) { + failWebsocketConnection(this.ws, 'Control frame either too large or fragmented') + return + } - /** - * @param {string|symbol} event - * @param {(...args: any[]) => void} listener - * @returns {this} - */ - addListener (event, listener) { - return this.on(event, listener) - } + if (isContinuationFrame(opcode) && this.#fragments.length === 0 && !this.#info.compressed) { + failWebsocketConnection(this.ws, 'Unexpected continuation frame') + return + } - /** - * @param {string|symbol} event - * @param {(...args: any[]) => void} listener - * @returns {this} - */ - off (event, listener) { - const ret = super.off(event, listener) - if (event === 'data' || event === 'readable') { - this[kReading] = ( - this.listenerCount('data') > 0 || - this.listenerCount('readable') > 0 - ) - } - return ret - } + if (payloadLength <= 125) { + this.#info.payloadLength = payloadLength + this.#state = parserStates.READ_DATA + } else if (payloadLength === 126) { + this.#state = parserStates.PAYLOADLENGTH_16 + } else if (payloadLength === 127) { + this.#state = parserStates.PAYLOADLENGTH_64 + } - /** - * @param {string|symbol} event - * @param {(...args: any[]) => void} listener - * @returns {this} - */ - removeListener (event, listener) { - return this.off(event, listener) - } + if (isTextBinaryFrame(opcode)) { + this.#info.binaryType = opcode + this.#info.compressed = rsv1 !== 0 + } - /** - * @param {Buffer|null} chunk - * @returns {boolean} - */ - push (chunk) { - if (chunk) { - this[kBytesRead] += chunk.length - if (this[kConsume]) { - consumePush(this[kConsume], chunk) - return this[kReading] ? super.push(chunk) : true - } - } + this.#info.opcode = opcode + this.#info.masked = masked + this.#info.fin = fin + this.#info.fragmented = fragmented + } else if (this.#state === parserStates.PAYLOADLENGTH_16) { + if (this.#byteOffset < 2) { + return callback() + } - return super.push(chunk) - } + const buffer = this.consume(2) - /** - * Consumes and returns the body as a string. - * - * @see https://fetch.spec.whatwg.org/#dom-body-text - * @returns {Promise} - */ - text () { - return consume(this, 'text') - } + this.#info.payloadLength = buffer.readUInt16BE(0) + this.#state = parserStates.READ_DATA + } else if (this.#state === parserStates.PAYLOADLENGTH_64) { + if (this.#byteOffset < 8) { + return callback() + } - /** - * Consumes and returns the body as a JavaScript Object. - * - * @see https://fetch.spec.whatwg.org/#dom-body-json - * @returns {Promise} - */ - json () { - return consume(this, 'json') - } + const buffer = this.consume(8) + const upper = buffer.readUInt32BE(0) - /** - * Consumes and returns the body as a Blob - * - * @see https://fetch.spec.whatwg.org/#dom-body-blob - * @returns {Promise} - */ - blob () { - return consume(this, 'blob') - } + // 2^31 is the maximum bytes an arraybuffer can contain + // on 32-bit systems. Although, on 64-bit systems, this is + // 2^53-1 bytes. + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Invalid_array_length + // https://source.chromium.org/chromium/chromium/src/+/main:v8/src/common/globals.h;drc=1946212ac0100668f14eb9e2843bdd846e510a1e;bpv=1;bpt=1;l=1275 + // https://source.chromium.org/chromium/chromium/src/+/main:v8/src/objects/js-array-buffer.h;l=34;drc=1946212ac0100668f14eb9e2843bdd846e510a1e + if (upper > 2 ** 31 - 1) { + failWebsocketConnection(this.ws, 'Received payload length > 2^31 bytes.') + return + } - /** - * Consumes and returns the body as an Uint8Array. - * - * @see https://fetch.spec.whatwg.org/#dom-body-bytes - * @returns {Promise} - */ - bytes () { - return consume(this, 'bytes') - } + const lower = buffer.readUInt32BE(4) - /** - * Consumes and returns the body as an ArrayBuffer. - * - * @see https://fetch.spec.whatwg.org/#dom-body-arraybuffer - * @returns {Promise} - */ - arrayBuffer () { - return consume(this, 'arrayBuffer') - } + this.#info.payloadLength = (upper << 8) + lower + this.#state = parserStates.READ_DATA + } else if (this.#state === parserStates.READ_DATA) { + if (this.#byteOffset < this.#info.payloadLength) { + return callback() + } - /** - * Not implemented - * - * @see https://fetch.spec.whatwg.org/#dom-body-formdata - * @throws {NotSupportedError} - */ - async formData () { - // TODO: Implement. - throw new NotSupportedError() - } - - /** - * Returns true if the body is not null and the body has been consumed. - * Otherwise, returns false. - * - * @see https://fetch.spec.whatwg.org/#dom-body-bodyused - * @readonly - * @returns {boolean} - */ - get bodyUsed () { - return util.isDisturbed(this) - } + const body = this.consume(this.#info.payloadLength) - /** - * @see https://fetch.spec.whatwg.org/#dom-body-body - * @readonly - * @returns {ReadableStream} - */ - get body () { - if (!this[kBody]) { - this[kBody] = ReadableStreamFrom(this) - if (this[kConsume]) { - // TODO: Is this the best way to force a lock? - this[kBody].getReader() // Ensure stream is locked. - assert(this[kBody].locked) - } - } - return this[kBody] - } + if (isControlFrame(this.#info.opcode)) { + this.#loop = this.parseControlFrame(body) + this.#state = parserStates.INFO + } else { + if (!this.#info.compressed) { + this.#fragments.push(body) - /** - * Dumps the response body by reading `limit` number of bytes. - * @param {object} opts - * @param {number} [opts.limit = 131072] Number of bytes to read. - * @param {AbortSignal} [opts.signal] An AbortSignal to cancel the dump. - * @returns {Promise} - */ - dump (opts) { - const signal = opts?.signal + // If the frame is not fragmented, a message has been received. + // If the frame is fragmented, it will terminate with a fin bit set + // and an opcode of 0 (continuation), therefore we handle that when + // parsing continuation frames, not here. + if (!this.#info.fragmented && this.#info.fin) { + const fullMessage = Buffer.concat(this.#fragments) + websocketMessageReceived(this.ws, this.#info.binaryType, fullMessage) + this.#fragments.length = 0 + } - if (signal != null && (typeof signal !== 'object' || !('aborted' in signal))) { - return Promise.reject(new InvalidArgumentError('signal must be an AbortSignal')) - } + this.#state = parserStates.INFO + } else { + this.#extensions.get('permessage-deflate').decompress(body, this.#info.fin, (error, data) => { + if (error) { + closeWebSocketConnection(this.ws, 1007, error.message, error.message.length) + return + } - const limit = opts?.limit && Number.isFinite(opts.limit) - ? opts.limit - : 128 * 1024 + this.#fragments.push(data) - if (signal?.aborted) { - return Promise.reject(signal.reason ?? new AbortError()) - } + if (!this.#info.fin) { + this.#state = parserStates.INFO + this.#loop = true + this.run(callback) + return + } - if (this._readableState.closeEmitted) { - return Promise.resolve(null) - } + websocketMessageReceived(this.ws, this.#info.binaryType, Buffer.concat(this.#fragments)) - return new Promise((resolve, reject) => { - if ( - (this[kContentLength] && (this[kContentLength] > limit)) || - this[kBytesRead] > limit - ) { - this.destroy(new AbortError()) - } + this.#loop = true + this.#state = parserStates.INFO + this.#fragments.length = 0 + this.run(callback) + }) - if (signal) { - const onAbort = () => { - this.destroy(signal.reason ?? new AbortError()) + this.#loop = false + break + } } - signal.addEventListener('abort', onAbort) - this - .on('close', function () { - signal.removeEventListener('abort', onAbort) - if (signal.aborted) { - reject(signal.reason ?? new AbortError()) - } else { - resolve(null) - } - }) - } else { - this.on('close', resolve) } - - this - .on('error', noop) - .on('data', () => { - if (this[kBytesRead] > limit) { - this.destroy() - } - }) - .resume() - }) + } } /** - * @param {BufferEncoding} encoding - * @returns {this} + * Take n bytes from the buffered Buffers + * @param {number} n + * @returns {Buffer} */ - setEncoding (encoding) { - if (Buffer.isEncoding(encoding)) { - this._readableState.encoding = encoding + consume (n) { + if (n > this.#byteOffset) { + throw new Error('Called consume() before buffers satiated.') + } else if (n === 0) { + return emptyBuffer } - return this - } -} - -/** - * @see https://streams.spec.whatwg.org/#readablestream-locked - * @param {BodyReadable} bodyReadable - * @returns {boolean} - */ -function isLocked (bodyReadable) { - // Consume is an implicit lock. - return bodyReadable[kBody]?.locked === true || bodyReadable[kConsume] !== null -} - -/** - * @see https://fetch.spec.whatwg.org/#body-unusable - * @param {BodyReadable} bodyReadable - * @returns {boolean} - */ -function isUnusable (bodyReadable) { - return util.isDisturbed(bodyReadable) || isLocked(bodyReadable) -} -/** - * @typedef {'text' | 'json' | 'blob' | 'bytes' | 'arrayBuffer'} ConsumeType - */ + if (this.#buffers[0].length === n) { + this.#byteOffset -= this.#buffers[0].length + return this.#buffers.shift() + } -/** - * @template {ConsumeType} T - * @typedef {T extends 'text' ? string : - * T extends 'json' ? unknown : - * T extends 'blob' ? Blob : - * T extends 'arrayBuffer' ? ArrayBuffer : - * T extends 'bytes' ? Uint8Array : - * never - * } ConsumeReturnType - */ -/** - * @typedef {object} Consume - * @property {ConsumeType} type - * @property {BodyReadable} stream - * @property {((value?: any) => void)} resolve - * @property {((err: Error) => void)} reject - * @property {number} length - * @property {Buffer[]} body - */ + const buffer = Buffer.allocUnsafe(n) + let offset = 0 -/** - * @template {ConsumeType} T - * @param {BodyReadable} stream - * @param {T} type - * @returns {Promise>} - */ -function consume (stream, type) { - assert(!stream[kConsume]) + while (offset !== n) { + const next = this.#buffers[0] + const { length } = next - return new Promise((resolve, reject) => { - if (isUnusable(stream)) { - const rState = stream._readableState - if (rState.destroyed && rState.closeEmitted === false) { - stream - .on('error', reject) - .on('close', () => { - reject(new TypeError('unusable')) - }) + if (length + offset === n) { + buffer.set(this.#buffers.shift(), offset) + break + } else if (length + offset > n) { + buffer.set(next.subarray(0, n - offset), offset) + this.#buffers[0] = next.subarray(n - offset) + break } else { - reject(rState.errored ?? new TypeError('unusable')) + buffer.set(this.#buffers.shift(), offset) + offset += next.length } - } else { - queueMicrotask(() => { - stream[kConsume] = { - type, - stream, - resolve, - reject, - length: 0, - body: [] - } + } - stream - .on('error', function (err) { - consumeFinish(this[kConsume], err) - }) - .on('close', function () { - if (this[kConsume].body !== null) { - consumeFinish(this[kConsume], new RequestAbortedError()) - } - }) + this.#byteOffset -= n - consumeStart(stream[kConsume]) - }) + return buffer + } + + parseCloseBody (data) { + assert(data.length !== 1) + + // https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.5 + /** @type {number|undefined} */ + let code + + if (data.length >= 2) { + // _The WebSocket Connection Close Code_ is + // defined as the status code (Section 7.4) contained in the first Close + // control frame received by the application + code = data.readUInt16BE(0) } - }) -} -/** - * @param {Consume} consume - * @returns {void} - */ -function consumeStart (consume) { - if (consume.body === null) { - return - } + if (code !== undefined && !isValidStatusCode(code)) { + return { code: 1002, reason: 'Invalid status code', error: true } + } - const { _readableState: state } = consume.stream + // https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.6 + /** @type {Buffer} */ + let reason = data.subarray(2) - if (state.bufferIndex) { - const start = state.bufferIndex - const end = state.buffer.length - for (let n = start; n < end; n++) { - consumePush(consume, state.buffer[n]) + // Remove BOM + if (reason[0] === 0xEF && reason[1] === 0xBB && reason[2] === 0xBF) { + reason = reason.subarray(3) } - } else { - for (const chunk of state.buffer) { - consumePush(consume, chunk) + + try { + reason = utf8Decode(reason) + } catch { + return { code: 1007, reason: 'Invalid UTF-8', error: true } } - } - if (state.endEmitted) { - consumeEnd(this[kConsume], this._readableState.encoding) - } else { - consume.stream.on('end', function () { - consumeEnd(this[kConsume], this._readableState.encoding) - }) + return { code, reason, error: false } } - consume.stream.resume() + /** + * Parses control frames. + * @param {Buffer} body + */ + parseControlFrame (body) { + const { opcode, payloadLength } = this.#info - while (consume.stream.read() != null) { - // Loop - } -} + if (opcode === opcodes.CLOSE) { + if (payloadLength === 1) { + failWebsocketConnection(this.ws, 'Received close frame with a 1-byte body.') + return false + } -/** - * @param {Buffer[]} chunks - * @param {number} length - * @param {BufferEncoding} [encoding='utf8'] - * @returns {string} - */ -function chunksDecode (chunks, length, encoding) { - if (chunks.length === 0 || length === 0) { - return '' - } - const buffer = chunks.length === 1 ? chunks[0] : Buffer.concat(chunks, length) - const bufferLength = buffer.length + this.#info.closeInfo = this.parseCloseBody(body) - // Skip BOM. - const start = - bufferLength > 2 && - buffer[0] === 0xef && - buffer[1] === 0xbb && - buffer[2] === 0xbf - ? 3 - : 0 - if (!encoding || encoding === 'utf8' || encoding === 'utf-8') { - return buffer.utf8Slice(start, bufferLength) - } else { - return buffer.subarray(start, bufferLength).toString(encoding) - } -} + if (this.#info.closeInfo.error) { + const { code, reason } = this.#info.closeInfo -/** - * @param {Buffer[]} chunks - * @param {number} length - * @returns {Uint8Array} - */ -function chunksConcat (chunks, length) { - if (chunks.length === 0 || length === 0) { - return new Uint8Array(0) - } - if (chunks.length === 1) { - // fast-path - return new Uint8Array(chunks[0]) - } - const buffer = new Uint8Array(Buffer.allocUnsafeSlow(length).buffer) + closeWebSocketConnection(this.ws, code, reason, reason.length) + failWebsocketConnection(this.ws, reason) + return false + } - let offset = 0 - for (let i = 0; i < chunks.length; ++i) { - const chunk = chunks[i] - buffer.set(chunk, offset) - offset += chunk.length - } + if (this.ws[kSentClose] !== sentCloseFrameState.SENT) { + // If an endpoint receives a Close frame and did not previously send a + // Close frame, the endpoint MUST send a Close frame in response. (When + // sending a Close frame in response, the endpoint typically echos the + // status code it received.) + let body = emptyBuffer + if (this.#info.closeInfo.code) { + body = Buffer.allocUnsafe(2) + body.writeUInt16BE(this.#info.closeInfo.code, 0) + } + const closeFrame = new WebsocketFrameSend(body) - return buffer -} + this.ws[kResponse].socket.write( + closeFrame.createFrame(opcodes.CLOSE), + (err) => { + if (!err) { + this.ws[kSentClose] = sentCloseFrameState.SENT + } + } + ) + } -/** - * @param {Consume} consume - * @param {BufferEncoding} encoding - * @returns {void} - */ -function consumeEnd (consume, encoding) { - const { type, body, resolve, stream, length } = consume + // Upon either sending or receiving a Close control frame, it is said + // that _The WebSocket Closing Handshake is Started_ and that the + // WebSocket connection is in the CLOSING state. + this.ws[kReadyState] = states.CLOSING + this.ws[kReceivedClose] = true - try { - if (type === 'text') { - resolve(chunksDecode(body, length, encoding)) - } else if (type === 'json') { - resolve(JSON.parse(chunksDecode(body, length, encoding))) - } else if (type === 'arrayBuffer') { - resolve(chunksConcat(body, length).buffer) - } else if (type === 'blob') { - resolve(new Blob(body, { type: stream[kContentType] })) - } else if (type === 'bytes') { - resolve(chunksConcat(body, length)) - } + return false + } else if (opcode === opcodes.PING) { + // Upon receipt of a Ping frame, an endpoint MUST send a Pong frame in + // response, unless it already received a Close frame. + // A Pong frame sent in response to a Ping frame must have identical + // "Application data" - consumeFinish(consume) - } catch (err) { - stream.destroy(err) - } -} + if (!this.ws[kReceivedClose]) { + const frame = new WebsocketFrameSend(body) -/** - * @param {Consume} consume - * @param {Buffer} chunk - * @returns {void} - */ -function consumePush (consume, chunk) { - consume.length += chunk.length - consume.body.push(chunk) -} + this.ws[kResponse].socket.write(frame.createFrame(opcodes.PONG)) -/** - * @param {Consume} consume - * @param {Error} [err] - * @returns {void} - */ -function consumeFinish (consume, err) { - if (consume.body === null) { - return - } + if (channels.ping.hasSubscribers) { + channels.ping.publish({ + payload: body + }) + } + } + } else if (opcode === opcodes.PONG) { + // A Pong frame MAY be sent unsolicited. This serves as a + // unidirectional heartbeat. A response to an unsolicited Pong frame is + // not expected. - if (err) { - consume.reject(err) - } else { - consume.resolve() + if (channels.pong.hasSubscribers) { + channels.pong.publish({ + payload: body + }) + } + } + + return true } - // Reset the consume object to allow for garbage collection. - consume.type = null - consume.stream = null - consume.resolve = null - consume.reject = null - consume.length = 0 - consume.body = null + get closingInfo () { + return this.#info.closeInfo + } } module.exports = { - Readable: BodyReadable, - chunksDecode + ByteParser } /***/ }), -/***/ 9972: +/***/ 6590: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -const { Writable } = __nccwpck_require__(7075) -const { EventEmitter } = __nccwpck_require__(8474) -const { assertCacheKey, assertCacheValue } = __nccwpck_require__(630) +const { WebsocketFrameSend } = __nccwpck_require__(8298) +const { opcodes, sendHints } = __nccwpck_require__(8850) +const FixedQueue = __nccwpck_require__(3830) -/** - * @typedef {import('../../types/cache-interceptor.d.ts').default.CacheKey} CacheKey - * @typedef {import('../../types/cache-interceptor.d.ts').default.CacheValue} CacheValue - * @typedef {import('../../types/cache-interceptor.d.ts').default.CacheStore} CacheStore - * @typedef {import('../../types/cache-interceptor.d.ts').default.GetResult} GetResult - */ +/** @type {typeof Uint8Array} */ +const FastBuffer = Buffer[Symbol.species] /** - * @implements {CacheStore} - * @extends {EventEmitter} + * @typedef {object} SendQueueNode + * @property {Promise | null} promise + * @property {((...args: any[]) => any)} callback + * @property {Buffer | null} frame */ -class MemoryCacheStore extends EventEmitter { - #maxCount = 1024 - #maxSize = 104857600 // 100MB - #maxEntrySize = 5242880 // 5MB - - #size = 0 - #count = 0 - #entries = new Map() - #hasEmittedMaxSizeEvent = false +class SendQueue { /** - * @param {import('../../types/cache-interceptor.d.ts').default.MemoryCacheStoreOpts | undefined} [opts] + * @type {FixedQueue} */ - constructor (opts) { - super() - if (opts) { - if (typeof opts !== 'object') { - throw new TypeError('MemoryCacheStore options must be an object') - } + #queue = new FixedQueue() - if (opts.maxCount !== undefined) { - if ( - typeof opts.maxCount !== 'number' || - !Number.isInteger(opts.maxCount) || - opts.maxCount < 0 - ) { - throw new TypeError('MemoryCacheStore options.maxCount must be a non-negative integer') - } - this.#maxCount = opts.maxCount - } + /** + * @type {boolean} + */ + #running = false - if (opts.maxSize !== undefined) { - if ( - typeof opts.maxSize !== 'number' || - !Number.isInteger(opts.maxSize) || - opts.maxSize < 0 - ) { - throw new TypeError('MemoryCacheStore options.maxSize must be a non-negative integer') - } - this.#maxSize = opts.maxSize - } + /** @type {import('node:net').Socket} */ + #socket - if (opts.maxEntrySize !== undefined) { - if ( - typeof opts.maxEntrySize !== 'number' || - !Number.isInteger(opts.maxEntrySize) || - opts.maxEntrySize < 0 - ) { - throw new TypeError('MemoryCacheStore options.maxEntrySize must be a non-negative integer') + constructor (socket) { + this.#socket = socket + } + + add (item, cb, hint) { + if (hint !== sendHints.blob) { + const frame = createFrame(item, hint) + if (!this.#running) { + // fast-path + this.#socket.write(frame, cb) + } else { + /** @type {SendQueueNode} */ + const node = { + promise: null, + callback: cb, + frame } - this.#maxEntrySize = opts.maxEntrySize + this.#queue.push(node) } + return } - } - - /** - * Get the current size of the cache in bytes - * @returns {number} The current size of the cache in bytes - */ - get size () { - return this.#size - } - /** - * Check if the cache is full (either max size or max count reached) - * @returns {boolean} True if the cache is full, false otherwise - */ - isFull () { - return this.#size >= this.#maxSize || this.#count >= this.#maxCount - } + /** @type {SendQueueNode} */ + const node = { + promise: item.arrayBuffer().then((ab) => { + node.promise = null + node.frame = createFrame(ab, hint) + }), + callback: cb, + frame: null + } - /** - * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} req - * @returns {import('../../types/cache-interceptor.d.ts').default.GetResult | undefined} - */ - get (key) { - assertCacheKey(key) + this.#queue.push(node) - const topLevelKey = `${key.origin}:${key.path}` + if (!this.#running) { + this.#run() + } + } - const now = Date.now() - const entries = this.#entries.get(topLevelKey) + async #run () { + this.#running = true + const queue = this.#queue + while (!queue.isEmpty()) { + const node = queue.shift() + // wait pending promise + if (node.promise !== null) { + await node.promise + } + // write + this.#socket.write(node.frame, node.callback) + // cleanup + node.callback = node.frame = null + } + this.#running = false + } +} - const entry = entries ? findEntry(key, entries, now) : null +function createFrame (data, hint) { + return new WebsocketFrameSend(toBuffer(data, hint)).createFrame(hint === sendHints.string ? opcodes.TEXT : opcodes.BINARY) +} - return entry == null - ? undefined - : { - statusMessage: entry.statusMessage, - statusCode: entry.statusCode, - headers: entry.headers, - body: entry.body, - vary: entry.vary ? entry.vary : undefined, - etag: entry.etag, - cacheControlDirectives: entry.cacheControlDirectives, - cachedAt: entry.cachedAt, - staleAt: entry.staleAt, - deleteAt: entry.deleteAt - } +function toBuffer (data, hint) { + switch (hint) { + case sendHints.string: + return Buffer.from(data) + case sendHints.arrayBuffer: + case sendHints.blob: + return new FastBuffer(data) + case sendHints.typedArray: + return new FastBuffer(data.buffer, data.byteOffset, data.byteLength) } +} - /** - * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} key - * @param {import('../../types/cache-interceptor.d.ts').default.CacheValue} val - * @returns {Writable | undefined} - */ - createWriteStream (key, val) { - assertCacheKey(key) - assertCacheValue(val) +module.exports = { SendQueue } - const topLevelKey = `${key.origin}:${key.path}` - const store = this - const entry = { ...key, ...val, body: [], size: 0 } +/***/ }), - return new Writable({ - write (chunk, encoding, callback) { - if (typeof chunk === 'string') { - chunk = Buffer.from(chunk, encoding) - } +/***/ 6178: +/***/ ((module) => { - entry.size += chunk.byteLength - if (entry.size >= store.#maxEntrySize) { - this.destroy() - } else { - entry.body.push(chunk) - } - callback(null) - }, - final (callback) { - let entries = store.#entries.get(topLevelKey) - if (!entries) { - entries = [] - store.#entries.set(topLevelKey, entries) - } - const previousEntry = findEntry(key, entries, Date.now()) - if (previousEntry) { - const index = entries.indexOf(previousEntry) - entries.splice(index, 1, entry) - store.#size -= previousEntry.size - } else { - entries.push(entry) - store.#count += 1 - } +module.exports = { + kWebSocketURL: Symbol('url'), + kReadyState: Symbol('ready state'), + kController: Symbol('controller'), + kResponse: Symbol('response'), + kBinaryType: Symbol('binary type'), + kSentClose: Symbol('sent close'), + kReceivedClose: Symbol('received close'), + kByteParser: Symbol('byte parser') +} - store.#size += entry.size - // Check if cache is full and emit event if needed - if (store.#size > store.#maxSize || store.#count > store.#maxCount) { - // Emit maxSizeExceeded event if we haven't already - if (!store.#hasEmittedMaxSizeEvent) { - store.emit('maxSizeExceeded', { - size: store.#size, - maxSize: store.#maxSize, - count: store.#count, - maxCount: store.#maxCount - }) - store.#hasEmittedMaxSizeEvent = true - } +/***/ }), - // Perform eviction - for (const [key, entries] of store.#entries) { - for (const entry of entries.splice(0, entries.length / 2)) { - store.#size -= entry.size - store.#count -= 1 - } - if (entries.length === 0) { - store.#entries.delete(key) - } - } +/***/ 5695: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - // Reset the event flag after eviction - if (store.#size < store.#maxSize && store.#count < store.#maxCount) { - store.#hasEmittedMaxSizeEvent = false - } - } - callback(null) - } - }) - } - /** - * @param {CacheKey} key - */ - delete (key) { - if (typeof key !== 'object') { - throw new TypeError(`expected key to be object, got ${typeof key}`) - } +const { kReadyState, kController, kResponse, kBinaryType, kWebSocketURL } = __nccwpck_require__(6178) +const { states, opcodes } = __nccwpck_require__(8850) +const { ErrorEvent, createFastMessageEvent } = __nccwpck_require__(8086) +const { isUtf8 } = __nccwpck_require__(4573) +const { collectASequenceOfCodePointsFast, removeHTTPWhitespace } = __nccwpck_require__(6406) - const topLevelKey = `${key.origin}:${key.path}` +/* globals Blob */ - for (const entry of this.#entries.get(topLevelKey) ?? []) { - this.#size -= entry.size - this.#count -= 1 - } - this.#entries.delete(topLevelKey) - } +/** + * @param {import('./websocket').WebSocket} ws + * @returns {boolean} + */ +function isConnecting (ws) { + // If the WebSocket connection is not yet established, and the connection + // is not yet closed, then the WebSocket connection is in the CONNECTING state. + return ws[kReadyState] === states.CONNECTING } -function findEntry (key, entries, now) { - return entries.find((entry) => ( - entry.deleteAt > now && - entry.method === key.method && - (entry.vary == null || Object.keys(entry.vary).every(headerName => { - if (entry.vary[headerName] === null) { - return key.headers[headerName] === undefined - } +/** + * @param {import('./websocket').WebSocket} ws + * @returns {boolean} + */ +function isEstablished (ws) { + // If the server's response is validated as provided for above, it is + // said that _The WebSocket Connection is Established_ and that the + // WebSocket Connection is in the OPEN state. + return ws[kReadyState] === states.OPEN +} - return entry.vary[headerName] === key.headers[headerName] - })) - )) +/** + * @param {import('./websocket').WebSocket} ws + * @returns {boolean} + */ +function isClosing (ws) { + // Upon either sending or receiving a Close control frame, it is said + // that _The WebSocket Closing Handshake is Started_ and that the + // WebSocket connection is in the CLOSING state. + return ws[kReadyState] === states.CLOSING } -module.exports = MemoryCacheStore +/** + * @param {import('./websocket').WebSocket} ws + * @returns {boolean} + */ +function isClosed (ws) { + return ws[kReadyState] === states.CLOSED +} +/** + * @see https://dom.spec.whatwg.org/#concept-event-fire + * @param {string} e + * @param {EventTarget} target + * @param {(...args: ConstructorParameters) => Event} eventFactory + * @param {EventInit | undefined} eventInitDict + */ +function fireEvent (e, target, eventFactory = (type, init) => new Event(type, init), eventInitDict = {}) { + // 1. If eventConstructor is not given, then let eventConstructor be Event. -/***/ }), + // 2. Let event be the result of creating an event given eventConstructor, + // in the relevant realm of target. + // 3. Initialize event’s type attribute to e. + const event = eventFactory(e, eventInitDict) -/***/ 6675: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // 4. Initialize any other IDL attributes of event as described in the + // invocation of this algorithm. -"use strict"; + // 5. Return the result of dispatching event at target, with legacy target + // override flag set if set. + target.dispatchEvent(event) +} +/** + * @see https://websockets.spec.whatwg.org/#feedback-from-the-protocol + * @param {import('./websocket').WebSocket} ws + * @param {number} type Opcode + * @param {Buffer} data application data + */ +function websocketMessageReceived (ws, type, data) { + // 1. If ready state is not OPEN (1), then return. + if (ws[kReadyState] !== states.OPEN) { + return + } -const { Writable } = __nccwpck_require__(7075) -const { assertCacheKey, assertCacheValue } = __nccwpck_require__(630) + // 2. Let dataForEvent be determined by switching on type and binary type: + let dataForEvent -let DatabaseSync + if (type === opcodes.TEXT) { + // -> type indicates that the data is Text + // a new DOMString containing data + try { + dataForEvent = utf8Decode(data) + } catch { + failWebsocketConnection(ws, 'Received invalid UTF-8 in text frame.') + return + } + } else if (type === opcodes.BINARY) { + if (ws[kBinaryType] === 'blob') { + // -> type indicates that the data is Binary and binary type is "blob" + // a new Blob object, created in the relevant Realm of the WebSocket + // object, that represents data as its raw data + dataForEvent = new Blob([data]) + } else { + // -> type indicates that the data is Binary and binary type is "arraybuffer" + // a new ArrayBuffer object, created in the relevant Realm of the + // WebSocket object, whose contents are data + dataForEvent = toArrayBuffer(data) + } + } -const VERSION = 3 + // 3. Fire an event named message at the WebSocket object, using MessageEvent, + // with the origin attribute initialized to the serialization of the WebSocket + // object’s url's origin, and the data attribute initialized to dataForEvent. + fireEvent('message', ws, createFastMessageEvent, { + origin: ws[kWebSocketURL].origin, + data: dataForEvent + }) +} -// 2gb -const MAX_ENTRY_SIZE = 2 * 1000 * 1000 * 1000 +function toArrayBuffer (buffer) { + if (buffer.byteLength === buffer.buffer.byteLength) { + return buffer.buffer + } + return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength) +} /** - * @typedef {import('../../types/cache-interceptor.d.ts').default.CacheStore} CacheStore - * @implements {CacheStore} - * - * @typedef {{ - * id: Readonly, - * body?: Uint8Array - * statusCode: number - * statusMessage: string - * headers?: string - * vary?: string - * etag?: string - * cacheControlDirectives?: string - * cachedAt: number - * staleAt: number - * deleteAt: number - * }} SqliteStoreValue + * @see https://datatracker.ietf.org/doc/html/rfc6455 + * @see https://datatracker.ietf.org/doc/html/rfc2616 + * @see https://bugs.chromium.org/p/chromium/issues/detail?id=398407 + * @param {string} protocol */ -module.exports = class SqliteCacheStore { - #maxEntrySize = MAX_ENTRY_SIZE - #maxCount = Infinity +function isValidSubprotocol (protocol) { + // If present, this value indicates one + // or more comma-separated subprotocol the client wishes to speak, + // ordered by preference. The elements that comprise this value + // MUST be non-empty strings with characters in the range U+0021 to + // U+007E not including separator characters as defined in + // [RFC2616] and MUST all be unique strings. + if (protocol.length === 0) { + return false + } - /** - * @type {import('node:sqlite').DatabaseSync} - */ - #db + for (let i = 0; i < protocol.length; ++i) { + const code = protocol.charCodeAt(i) - /** - * @type {import('node:sqlite').StatementSync} - */ - #getValuesQuery + if ( + code < 0x21 || // CTL, contains SP (0x20) and HT (0x09) + code > 0x7E || + code === 0x22 || // " + code === 0x28 || // ( + code === 0x29 || // ) + code === 0x2C || // , + code === 0x2F || // / + code === 0x3A || // : + code === 0x3B || // ; + code === 0x3C || // < + code === 0x3D || // = + code === 0x3E || // > + code === 0x3F || // ? + code === 0x40 || // @ + code === 0x5B || // [ + code === 0x5C || // \ + code === 0x5D || // ] + code === 0x7B || // { + code === 0x7D // } + ) { + return false + } + } - /** - * @type {import('node:sqlite').StatementSync} - */ - #updateValueQuery + return true +} - /** - * @type {import('node:sqlite').StatementSync} - */ - #insertValueQuery +/** + * @see https://datatracker.ietf.org/doc/html/rfc6455#section-7-4 + * @param {number} code + */ +function isValidStatusCode (code) { + if (code >= 1000 && code < 1015) { + return ( + code !== 1004 && // reserved + code !== 1005 && // "MUST NOT be set as a status code" + code !== 1006 // "MUST NOT be set as a status code" + ) + } - /** - * @type {import('node:sqlite').StatementSync} - */ - #deleteExpiredValuesQuery + return code >= 3000 && code <= 4999 +} - /** - * @type {import('node:sqlite').StatementSync} - */ - #deleteByUrlQuery +/** + * @param {import('./websocket').WebSocket} ws + * @param {string|undefined} reason + */ +function failWebsocketConnection (ws, reason) { + const { [kController]: controller, [kResponse]: response } = ws - /** - * @type {import('node:sqlite').StatementSync} - */ - #countEntriesQuery + controller.abort() - /** - * @type {import('node:sqlite').StatementSync | null} - */ - #deleteOldValuesQuery + if (response?.socket && !response.socket.destroyed) { + response.socket.destroy() + } - /** - * @param {import('../../types/cache-interceptor.d.ts').default.SqliteCacheStoreOpts | undefined} opts - */ - constructor (opts) { - if (opts) { - if (typeof opts !== 'object') { - throw new TypeError('SqliteCacheStore options must be an object') - } + if (reason) { + // TODO: process.nextTick + fireEvent('error', ws, (type, init) => new ErrorEvent(type, init), { + error: new Error(reason), + message: reason + }) + } +} - if (opts.maxEntrySize !== undefined) { - if ( - typeof opts.maxEntrySize !== 'number' || - !Number.isInteger(opts.maxEntrySize) || - opts.maxEntrySize < 0 - ) { - throw new TypeError('SqliteCacheStore options.maxEntrySize must be a non-negative integer') - } +/** + * @see https://datatracker.ietf.org/doc/html/rfc6455#section-5.5 + * @param {number} opcode + */ +function isControlFrame (opcode) { + return ( + opcode === opcodes.CLOSE || + opcode === opcodes.PING || + opcode === opcodes.PONG + ) +} - if (opts.maxEntrySize > MAX_ENTRY_SIZE) { - throw new TypeError('SqliteCacheStore options.maxEntrySize must be less than 2gb') - } +function isContinuationFrame (opcode) { + return opcode === opcodes.CONTINUATION +} - this.#maxEntrySize = opts.maxEntrySize - } +function isTextBinaryFrame (opcode) { + return opcode === opcodes.TEXT || opcode === opcodes.BINARY +} - if (opts.maxCount !== undefined) { - if ( - typeof opts.maxCount !== 'number' || - !Number.isInteger(opts.maxCount) || - opts.maxCount < 0 - ) { - throw new TypeError('SqliteCacheStore options.maxCount must be a non-negative integer') - } - this.#maxCount = opts.maxCount - } - } +function isValidOpcode (opcode) { + return isTextBinaryFrame(opcode) || isContinuationFrame(opcode) || isControlFrame(opcode) +} - if (!DatabaseSync) { - DatabaseSync = (__nccwpck_require__(99).DatabaseSync) - } - this.#db = new DatabaseSync(opts?.location ?? ':memory:') +/** + * Parses a Sec-WebSocket-Extensions header value. + * @param {string} extensions + * @returns {Map} + */ +// TODO(@Uzlopak, @KhafraDev): make compliant https://datatracker.ietf.org/doc/html/rfc6455#section-9.1 +function parseExtensions (extensions) { + const position = { position: 0 } + const extensionList = new Map() - this.#db.exec(` - PRAGMA journal_mode = WAL; - PRAGMA synchronous = NORMAL; - PRAGMA temp_store = memory; - PRAGMA optimize; + while (position.position < extensions.length) { + const pair = collectASequenceOfCodePointsFast(';', extensions, position) + const [name, value = ''] = pair.split('=') - CREATE TABLE IF NOT EXISTS cacheInterceptorV${VERSION} ( - -- Data specific to us - id INTEGER PRIMARY KEY AUTOINCREMENT, - url TEXT NOT NULL, - method TEXT NOT NULL, + extensionList.set( + removeHTTPWhitespace(name, true, false), + removeHTTPWhitespace(value, false, true) + ) - -- Data returned to the interceptor - body BUF NULL, - deleteAt INTEGER NOT NULL, - statusCode INTEGER NOT NULL, - statusMessage TEXT NOT NULL, - headers TEXT NULL, - cacheControlDirectives TEXT NULL, - etag TEXT NULL, - vary TEXT NULL, - cachedAt INTEGER NOT NULL, - staleAt INTEGER NOT NULL - ); + position.position++ + } - CREATE INDEX IF NOT EXISTS idx_cacheInterceptorV${VERSION}_getValuesQuery ON cacheInterceptorV${VERSION}(url, method, deleteAt); - CREATE INDEX IF NOT EXISTS idx_cacheInterceptorV${VERSION}_deleteByUrlQuery ON cacheInterceptorV${VERSION}(deleteAt); - `) + return extensionList +} - this.#getValuesQuery = this.#db.prepare(` - SELECT - id, - body, - deleteAt, - statusCode, - statusMessage, - headers, - etag, - cacheControlDirectives, - vary, - cachedAt, - staleAt - FROM cacheInterceptorV${VERSION} - WHERE - url = ? - AND method = ? - ORDER BY - deleteAt ASC - `) +/** + * @see https://www.rfc-editor.org/rfc/rfc7692#section-7.1.2.2 + * @description "client-max-window-bits = 1*DIGIT" + * @param {string} value + */ +function isValidClientWindowBits (value) { + for (let i = 0; i < value.length; i++) { + const byte = value.charCodeAt(i) - this.#updateValueQuery = this.#db.prepare(` - UPDATE cacheInterceptorV${VERSION} SET - body = ?, - deleteAt = ?, - statusCode = ?, - statusMessage = ?, - headers = ?, - etag = ?, - cacheControlDirectives = ?, - cachedAt = ?, - staleAt = ? - WHERE - id = ? - `) + if (byte < 0x30 || byte > 0x39) { + return false + } + } - this.#insertValueQuery = this.#db.prepare(` - INSERT INTO cacheInterceptorV${VERSION} ( - url, - method, - body, - deleteAt, - statusCode, - statusMessage, - headers, - etag, - cacheControlDirectives, - vary, - cachedAt, - staleAt - ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) - `) + return true +} - this.#deleteByUrlQuery = this.#db.prepare( - `DELETE FROM cacheInterceptorV${VERSION} WHERE url = ?` - ) +// https://nodejs.org/api/intl.html#detecting-internationalization-support +const hasIntl = typeof process.versions.icu === 'string' +const fatalDecoder = hasIntl ? new TextDecoder('utf-8', { fatal: true }) : undefined - this.#countEntriesQuery = this.#db.prepare( - `SELECT COUNT(*) AS total FROM cacheInterceptorV${VERSION}` - ) +/** + * Converts a Buffer to utf-8, even on platforms without icu. + * @param {Buffer} buffer + */ +const utf8Decode = hasIntl + ? fatalDecoder.decode.bind(fatalDecoder) + : function (buffer) { + if (isUtf8(buffer)) { + return buffer.toString('utf-8') + } + throw new TypeError('Invalid utf-8 received.') + } - this.#deleteExpiredValuesQuery = this.#db.prepare( - `DELETE FROM cacheInterceptorV${VERSION} WHERE deleteAt <= ?` - ) +module.exports = { + isConnecting, + isEstablished, + isClosing, + isClosed, + fireEvent, + isValidSubprotocol, + isValidStatusCode, + failWebsocketConnection, + websocketMessageReceived, + utf8Decode, + isControlFrame, + isContinuationFrame, + isTextBinaryFrame, + isValidOpcode, + parseExtensions, + isValidClientWindowBits +} - this.#deleteOldValuesQuery = this.#maxCount === Infinity - ? null - : this.#db.prepare(` - DELETE FROM cacheInterceptorV${VERSION} - WHERE id IN ( - SELECT - id - FROM cacheInterceptorV${VERSION} - ORDER BY cachedAt DESC - LIMIT ? - ) - `) - } - close () { - this.#db.close() - } +/***/ }), - /** - * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} key - * @returns {(import('../../types/cache-interceptor.d.ts').default.GetResult & { body?: Buffer }) | undefined} - */ - get (key) { - assertCacheKey(key) +/***/ 5136: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - const value = this.#findValue(key) - return value - ? { - body: value.body ? Buffer.from(value.body.buffer, value.body.byteOffset, value.body.byteLength) : undefined, - statusCode: value.statusCode, - statusMessage: value.statusMessage, - headers: value.headers ? JSON.parse(value.headers) : undefined, - etag: value.etag ? value.etag : undefined, - vary: value.vary ? JSON.parse(value.vary) : undefined, - cacheControlDirectives: value.cacheControlDirectives - ? JSON.parse(value.cacheControlDirectives) - : undefined, - cachedAt: value.cachedAt, - staleAt: value.staleAt, - deleteAt: value.deleteAt - } - : undefined + + +const { webidl } = __nccwpck_require__(4859) +const { URLSerializer } = __nccwpck_require__(6406) +const { environmentSettingsObject } = __nccwpck_require__(1046) +const { staticPropertyDescriptors, states, sentCloseFrameState, sendHints } = __nccwpck_require__(8850) +const { + kWebSocketURL, + kReadyState, + kController, + kBinaryType, + kResponse, + kSentClose, + kByteParser +} = __nccwpck_require__(6178) +const { + isConnecting, + isEstablished, + isClosing, + isValidSubprotocol, + fireEvent +} = __nccwpck_require__(5695) +const { establishWebSocketConnection, closeWebSocketConnection } = __nccwpck_require__(9107) +const { ByteParser } = __nccwpck_require__(3274) +const { kEnumerableProperty, isBlobLike } = __nccwpck_require__(7234) +const { getGlobalDispatcher } = __nccwpck_require__(1903) +const { types } = __nccwpck_require__(7975) +const { ErrorEvent, CloseEvent } = __nccwpck_require__(8086) +const { SendQueue } = __nccwpck_require__(6590) + +// https://websockets.spec.whatwg.org/#interface-definition +class WebSocket extends EventTarget { + #events = { + open: null, + error: null, + close: null, + message: null } + #bufferedAmount = 0 + #protocol = '' + #extensions = '' + + /** @type {SendQueue} */ + #sendQueue + /** - * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} key - * @param {import('../../types/cache-interceptor.d.ts').default.CacheValue & { body: null | Buffer | Array}} value + * @param {string} url + * @param {string|string[]} protocols */ - set (key, value) { - assertCacheKey(key) + constructor (url, protocols = []) { + super() - const url = this.#makeValueUrl(key) - const body = Array.isArray(value.body) ? Buffer.concat(value.body) : value.body - const size = body?.byteLength + webidl.util.markAsUncloneable(this) - if (size && size > this.#maxEntrySize) { - return - } + const prefix = 'WebSocket constructor' + webidl.argumentLengthCheck(arguments, 1, prefix) - const existingValue = this.#findValue(key, true) - if (existingValue) { - // Updating an existing response, let's overwrite it - this.#updateValueQuery.run( - body, - value.deleteAt, - value.statusCode, - value.statusMessage, - value.headers ? JSON.stringify(value.headers) : null, - value.etag ? value.etag : null, - value.cacheControlDirectives ? JSON.stringify(value.cacheControlDirectives) : null, - value.cachedAt, - value.staleAt, - existingValue.id - ) - } else { - this.#prune() - // New response, let's insert it - this.#insertValueQuery.run( - url, - key.method, - body, - value.deleteAt, - value.statusCode, - value.statusMessage, - value.headers ? JSON.stringify(value.headers) : null, - value.etag ? value.etag : null, - value.cacheControlDirectives ? JSON.stringify(value.cacheControlDirectives) : null, - value.vary ? JSON.stringify(value.vary) : null, - value.cachedAt, - value.staleAt - ) - } - } + const options = webidl.converters['DOMString or sequence or WebSocketInit'](protocols, prefix, 'options') - /** - * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} key - * @param {import('../../types/cache-interceptor.d.ts').default.CacheValue} value - * @returns {Writable | undefined} - */ - createWriteStream (key, value) { - assertCacheKey(key) - assertCacheValue(value) + url = webidl.converters.USVString(url, prefix, 'url') + protocols = options.protocols - let size = 0 - /** - * @type {Buffer[] | null} - */ - const body = [] - const store = this + // 1. Let baseURL be this's relevant settings object's API base URL. + const baseURL = environmentSettingsObject.settingsObject.baseUrl - return new Writable({ - decodeStrings: true, - write (chunk, encoding, callback) { - size += chunk.byteLength + // 1. Let urlRecord be the result of applying the URL parser to url with baseURL. + let urlRecord - if (size < store.#maxEntrySize) { - body.push(chunk) - } else { - this.destroy() - } + try { + urlRecord = new URL(url, baseURL) + } catch (e) { + // 3. If urlRecord is failure, then throw a "SyntaxError" DOMException. + throw new DOMException(e, 'SyntaxError') + } - callback() - }, - final (callback) { - store.set(key, { ...value, body }) - callback() - } - }) - } + // 4. If urlRecord’s scheme is "http", then set urlRecord’s scheme to "ws". + if (urlRecord.protocol === 'http:') { + urlRecord.protocol = 'ws:' + } else if (urlRecord.protocol === 'https:') { + // 5. Otherwise, if urlRecord’s scheme is "https", set urlRecord’s scheme to "wss". + urlRecord.protocol = 'wss:' + } - /** - * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} key - */ - delete (key) { - if (typeof key !== 'object') { - throw new TypeError(`expected key to be object, got ${typeof key}`) + // 6. If urlRecord’s scheme is not "ws" or "wss", then throw a "SyntaxError" DOMException. + if (urlRecord.protocol !== 'ws:' && urlRecord.protocol !== 'wss:') { + throw new DOMException( + `Expected a ws: or wss: protocol, got ${urlRecord.protocol}`, + 'SyntaxError' + ) } - this.#deleteByUrlQuery.run(this.#makeValueUrl(key)) - } + // 7. If urlRecord’s fragment is non-null, then throw a "SyntaxError" + // DOMException. + if (urlRecord.hash || urlRecord.href.endsWith('#')) { + throw new DOMException('Got fragment', 'SyntaxError') + } - #prune () { - if (Number.isFinite(this.#maxCount) && this.size <= this.#maxCount) { - return 0 + // 8. If protocols is a string, set protocols to a sequence consisting + // of just that string. + if (typeof protocols === 'string') { + protocols = [protocols] } - { - const removed = this.#deleteExpiredValuesQuery.run(Date.now()).changes - if (removed) { - return removed - } + // 9. If any of the values in protocols occur more than once or otherwise + // fail to match the requirements for elements that comprise the value + // of `Sec-WebSocket-Protocol` fields as defined by The WebSocket + // protocol, then throw a "SyntaxError" DOMException. + if (protocols.length !== new Set(protocols.map(p => p.toLowerCase())).size) { + throw new DOMException('Invalid Sec-WebSocket-Protocol value', 'SyntaxError') } - { - const removed = this.#deleteOldValuesQuery?.run(Math.max(Math.floor(this.#maxCount * 0.1), 1)).changes - if (removed) { - return removed - } + if (protocols.length > 0 && !protocols.every(p => isValidSubprotocol(p))) { + throw new DOMException('Invalid Sec-WebSocket-Protocol value', 'SyntaxError') } - return 0 - } + // 10. Set this's url to urlRecord. + this[kWebSocketURL] = new URL(urlRecord.href) - /** - * Counts the number of rows in the cache - * @returns {Number} - */ - get size () { - const { total } = this.#countEntriesQuery.get() - return total - } + // 11. Let client be this's relevant settings object. + const client = environmentSettingsObject.settingsObject - /** - * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} key - * @returns {string} - */ - #makeValueUrl (key) { - return `${key.origin}/${key.path}` + // 12. Run this step in parallel: + + // 1. Establish a WebSocket connection given urlRecord, protocols, + // and client. + this[kController] = establishWebSocketConnection( + urlRecord, + protocols, + client, + this, + (response, extensions) => this.#onConnectionEstablished(response, extensions), + options + ) + + // Each WebSocket object has an associated ready state, which is a + // number representing the state of the connection. Initially it must + // be CONNECTING (0). + this[kReadyState] = WebSocket.CONNECTING + + this[kSentClose] = sentCloseFrameState.NOT_SENT + + // The extensions attribute must initially return the empty string. + + // The protocol attribute must initially return the empty string. + + // Each WebSocket object has an associated binary type, which is a + // BinaryType. Initially it must be "blob". + this[kBinaryType] = 'blob' } /** - * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} key - * @param {boolean} [canBeExpired=false] - * @returns {SqliteStoreValue | undefined} + * @see https://websockets.spec.whatwg.org/#dom-websocket-close + * @param {number|undefined} code + * @param {string|undefined} reason */ - #findValue (key, canBeExpired = false) { - const url = this.#makeValueUrl(key) - const { headers, method } = key + close (code = undefined, reason = undefined) { + webidl.brandCheck(this, WebSocket) - /** - * @type {SqliteStoreValue[]} - */ - const values = this.#getValuesQuery.all(url, method) + const prefix = 'WebSocket.close' - if (values.length === 0) { - return undefined + if (code !== undefined) { + code = webidl.converters['unsigned short'](code, prefix, 'code', { clamp: true }) } - const now = Date.now() - for (const value of values) { - if (now >= value.deleteAt && !canBeExpired) { - return undefined - } - - let matches = true - - if (value.vary) { - const vary = JSON.parse(value.vary) - - for (const header in vary) { - if (!headerValueEquals(headers[header], vary[header])) { - matches = false - break - } - } - } + if (reason !== undefined) { + reason = webidl.converters.USVString(reason, prefix, 'reason') + } - if (matches) { - return value + // 1. If code is present, but is neither an integer equal to 1000 nor an + // integer in the range 3000 to 4999, inclusive, throw an + // "InvalidAccessError" DOMException. + if (code !== undefined) { + if (code !== 1000 && (code < 3000 || code > 4999)) { + throw new DOMException('invalid code', 'InvalidAccessError') } } - return undefined - } -} - -/** - * @param {string|string[]|null|undefined} lhs - * @param {string|string[]|null|undefined} rhs - * @returns {boolean} - */ -function headerValueEquals (lhs, rhs) { - if (lhs == null && rhs == null) { - return true - } + let reasonByteLength = 0 - if ((lhs == null && rhs != null) || - (lhs != null && rhs == null)) { - return false - } + // 2. If reason is present, then run these substeps: + if (reason !== undefined) { + // 1. Let reasonBytes be the result of encoding reason. + // 2. If reasonBytes is longer than 123 bytes, then throw a + // "SyntaxError" DOMException. + reasonByteLength = Buffer.byteLength(reason) - if (Array.isArray(lhs) && Array.isArray(rhs)) { - if (lhs.length !== rhs.length) { - return false + if (reasonByteLength > 123) { + throw new DOMException( + `Reason must be less than 123 bytes; received ${reasonByteLength}`, + 'SyntaxError' + ) + } } - return lhs.every((x, i) => x === rhs[i]) + // 3. Run the first matching steps from the following list: + closeWebSocketConnection(this, code, reason, reasonByteLength) } - return lhs === rhs -} + /** + * @see https://websockets.spec.whatwg.org/#dom-websocket-send + * @param {NodeJS.TypedArray|ArrayBuffer|Blob|string} data + */ + send (data) { + webidl.brandCheck(this, WebSocket) + const prefix = 'WebSocket.send' + webidl.argumentLengthCheck(arguments, 1, prefix) -/***/ }), + data = webidl.converters.WebSocketSendData(data, prefix, 'data') -/***/ 978: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // 1. If this's ready state is CONNECTING, then throw an + // "InvalidStateError" DOMException. + if (isConnecting(this)) { + throw new DOMException('Sent before connected.', 'InvalidStateError') + } -"use strict"; + // 2. Run the appropriate set of steps from the following list: + // https://datatracker.ietf.org/doc/html/rfc6455#section-6.1 + // https://datatracker.ietf.org/doc/html/rfc6455#section-5.2 + if (!isEstablished(this) || isClosing(this)) { + return + } -const net = __nccwpck_require__(7030) -const assert = __nccwpck_require__(4589) -const util = __nccwpck_require__(983) -const { InvalidArgumentError } = __nccwpck_require__(4928) + // If data is a string + if (typeof data === 'string') { + // If the WebSocket connection is established and the WebSocket + // closing handshake has not yet started, then the user agent + // must send a WebSocket Message comprised of the data argument + // using a text frame opcode; if the data cannot be sent, e.g. + // because it would need to be buffered but the buffer is full, + // the user agent must flag the WebSocket as full and then close + // the WebSocket connection. Any invocation of this method with a + // string argument that does not throw an exception must increase + // the bufferedAmount attribute by the number of bytes needed to + // express the argument as UTF-8. -let tls // include tls conditionally since it is not always available + const length = Buffer.byteLength(data) -// TODO: session re-use does not wait for the first -// connection to resolve the session and might therefore -// resolve the same servername multiple times even when -// re-use is enabled. + this.#bufferedAmount += length + this.#sendQueue.add(data, () => { + this.#bufferedAmount -= length + }, sendHints.string) + } else if (types.isArrayBuffer(data)) { + // If the WebSocket connection is established, and the WebSocket + // closing handshake has not yet started, then the user agent must + // send a WebSocket Message comprised of data using a binary frame + // opcode; if the data cannot be sent, e.g. because it would need + // to be buffered but the buffer is full, the user agent must flag + // the WebSocket as full and then close the WebSocket connection. + // The data to be sent is the data stored in the buffer described + // by the ArrayBuffer object. Any invocation of this method with an + // ArrayBuffer argument that does not throw an exception must + // increase the bufferedAmount attribute by the length of the + // ArrayBuffer in bytes. -const SessionCache = class WeakSessionCache { - constructor (maxCachedSessions) { - this._maxCachedSessions = maxCachedSessions - this._sessionCache = new Map() - this._sessionRegistry = new FinalizationRegistry((key) => { - if (this._sessionCache.size < this._maxCachedSessions) { - return - } + this.#bufferedAmount += data.byteLength + this.#sendQueue.add(data, () => { + this.#bufferedAmount -= data.byteLength + }, sendHints.arrayBuffer) + } else if (ArrayBuffer.isView(data)) { + // If the WebSocket connection is established, and the WebSocket + // closing handshake has not yet started, then the user agent must + // send a WebSocket Message comprised of data using a binary frame + // opcode; if the data cannot be sent, e.g. because it would need to + // be buffered but the buffer is full, the user agent must flag the + // WebSocket as full and then close the WebSocket connection. The + // data to be sent is the data stored in the section of the buffer + // described by the ArrayBuffer object that data references. Any + // invocation of this method with this kind of argument that does + // not throw an exception must increase the bufferedAmount attribute + // by the length of data’s buffer in bytes. - const ref = this._sessionCache.get(key) - if (ref !== undefined && ref.deref() === undefined) { - this._sessionCache.delete(key) - } - }) + this.#bufferedAmount += data.byteLength + this.#sendQueue.add(data, () => { + this.#bufferedAmount -= data.byteLength + }, sendHints.typedArray) + } else if (isBlobLike(data)) { + // If the WebSocket connection is established, and the WebSocket + // closing handshake has not yet started, then the user agent must + // send a WebSocket Message comprised of data using a binary frame + // opcode; if the data cannot be sent, e.g. because it would need to + // be buffered but the buffer is full, the user agent must flag the + // WebSocket as full and then close the WebSocket connection. The data + // to be sent is the raw data represented by the Blob object. Any + // invocation of this method with a Blob argument that does not throw + // an exception must increase the bufferedAmount attribute by the size + // of the Blob object’s raw data, in bytes. + + this.#bufferedAmount += data.size + this.#sendQueue.add(data, () => { + this.#bufferedAmount -= data.size + }, sendHints.blob) + } } - get (sessionKey) { - const ref = this._sessionCache.get(sessionKey) - return ref ? ref.deref() : null + get readyState () { + webidl.brandCheck(this, WebSocket) + + // The readyState getter steps are to return this's ready state. + return this[kReadyState] } - set (sessionKey, session) { - if (this._maxCachedSessions === 0) { - return + get bufferedAmount () { + webidl.brandCheck(this, WebSocket) + + return this.#bufferedAmount + } + + get url () { + webidl.brandCheck(this, WebSocket) + + // The url getter steps are to return this's url, serialized. + return URLSerializer(this[kWebSocketURL]) + } + + get extensions () { + webidl.brandCheck(this, WebSocket) + + return this.#extensions + } + + get protocol () { + webidl.brandCheck(this, WebSocket) + + return this.#protocol + } + + get onopen () { + webidl.brandCheck(this, WebSocket) + + return this.#events.open + } + + set onopen (fn) { + webidl.brandCheck(this, WebSocket) + + if (this.#events.open) { + this.removeEventListener('open', this.#events.open) } - this._sessionCache.set(sessionKey, new WeakRef(session)) - this._sessionRegistry.register(session, sessionKey) + if (typeof fn === 'function') { + this.#events.open = fn + this.addEventListener('open', fn) + } else { + this.#events.open = null + } } -} -function buildConnector ({ allowH2, useH2c, maxCachedSessions, socketPath, timeout, session: customSession, ...opts }) { - if (maxCachedSessions != null && (!Number.isInteger(maxCachedSessions) || maxCachedSessions < 0)) { - throw new InvalidArgumentError('maxCachedSessions must be a positive integer or zero') + get onerror () { + webidl.brandCheck(this, WebSocket) + + return this.#events.error } - const options = { path: socketPath, ...opts } - const sessionCache = new SessionCache(maxCachedSessions == null ? 100 : maxCachedSessions) - timeout = timeout == null ? 10e3 : timeout - allowH2 = allowH2 != null ? allowH2 : false - return function connect ({ hostname, host, protocol, port, servername, localAddress, httpSocket }, callback) { - let socket - if (protocol === 'https:') { - if (!tls) { - tls = __nccwpck_require__(1692) - } - servername = servername || options.servername || util.getServerName(host) || null + set onerror (fn) { + webidl.brandCheck(this, WebSocket) - const sessionKey = servername || hostname - assert(sessionKey) + if (this.#events.error) { + this.removeEventListener('error', this.#events.error) + } - const session = customSession || sessionCache.get(sessionKey) || null + if (typeof fn === 'function') { + this.#events.error = fn + this.addEventListener('error', fn) + } else { + this.#events.error = null + } + } - port = port || 443 + get onclose () { + webidl.brandCheck(this, WebSocket) - socket = tls.connect({ - highWaterMark: 16384, // TLS in node can't have bigger HWM anyway... - ...options, - servername, - session, - localAddress, - ALPNProtocols: allowH2 ? ['http/1.1', 'h2'] : ['http/1.1'], - socket: httpSocket, // upgrade socket connection - port, - host: hostname - }) + return this.#events.close + } - socket - .on('session', function (session) { - // TODO (fix): Can a session become invalid once established? Don't think so? - sessionCache.set(sessionKey, session) - }) + set onclose (fn) { + webidl.brandCheck(this, WebSocket) + + if (this.#events.close) { + this.removeEventListener('close', this.#events.close) + } + + if (typeof fn === 'function') { + this.#events.close = fn + this.addEventListener('close', fn) } else { - assert(!httpSocket, 'httpSocket can only be sent on TLS update') + this.#events.close = null + } + } - port = port || 80 + get onmessage () { + webidl.brandCheck(this, WebSocket) - socket = net.connect({ - highWaterMark: 64 * 1024, // Same as nodejs fs streams. - ...options, - localAddress, - port, - host: hostname - }) - if (useH2c === true) { - socket.alpnProtocol = 'h2' - } + return this.#events.message + } + + set onmessage (fn) { + webidl.brandCheck(this, WebSocket) + + if (this.#events.message) { + this.removeEventListener('message', this.#events.message) } - // Set TCP keep alive options on the socket here instead of in connect() for the case of assigning the socket - if (options.keepAlive == null || options.keepAlive) { - const keepAliveInitialDelay = options.keepAliveInitialDelay === undefined ? 60e3 : options.keepAliveInitialDelay - socket.setKeepAlive(true, keepAliveInitialDelay) + if (typeof fn === 'function') { + this.#events.message = fn + this.addEventListener('message', fn) + } else { + this.#events.message = null } + } - const clearConnectTimeout = util.setupConnectTimeout(new WeakRef(socket), { timeout, hostname, port }) + get binaryType () { + webidl.brandCheck(this, WebSocket) - socket - .setNoDelay(true) - .once(protocol === 'https:' ? 'secureConnect' : 'connect', function () { - queueMicrotask(clearConnectTimeout) + return this[kBinaryType] + } - if (callback) { - const cb = callback - callback = null - cb(null, this) - } - }) - .on('error', function (err) { - queueMicrotask(clearConnectTimeout) + set binaryType (type) { + webidl.brandCheck(this, WebSocket) - if (callback) { - const cb = callback - callback = null - cb(err) - } - }) + if (type !== 'blob' && type !== 'arraybuffer') { + this[kBinaryType] = 'blob' + } else { + this[kBinaryType] = type + } + } - return socket + /** + * @see https://websockets.spec.whatwg.org/#feedback-from-the-protocol + */ + #onConnectionEstablished (response, parsedExtensions) { + // processResponse is called when the "response’s header list has been received and initialized." + // once this happens, the connection is open + this[kResponse] = response + + const parser = new ByteParser(this, parsedExtensions) + parser.on('drain', onParserDrain) + parser.on('error', onParserError.bind(this)) + + response.socket.ws = this + this[kByteParser] = parser + + this.#sendQueue = new SendQueue(response.socket) + + // 1. Change the ready state to OPEN (1). + this[kReadyState] = states.OPEN + + // 2. Change the extensions attribute’s value to the extensions in use, if + // it is not the null value. + // https://datatracker.ietf.org/doc/html/rfc6455#section-9.1 + const extensions = response.headersList.get('sec-websocket-extensions') + + if (extensions !== null) { + this.#extensions = extensions + } + + // 3. Change the protocol attribute’s value to the subprotocol in use, if + // it is not the null value. + // https://datatracker.ietf.org/doc/html/rfc6455#section-1.9 + const protocol = response.headersList.get('sec-websocket-protocol') + + if (protocol !== null) { + this.#protocol = protocol + } + + // 4. Fire an event named open at the WebSocket object. + fireEvent('open', this) } } -module.exports = buildConnector +// https://websockets.spec.whatwg.org/#dom-websocket-connecting +WebSocket.CONNECTING = WebSocket.prototype.CONNECTING = states.CONNECTING +// https://websockets.spec.whatwg.org/#dom-websocket-open +WebSocket.OPEN = WebSocket.prototype.OPEN = states.OPEN +// https://websockets.spec.whatwg.org/#dom-websocket-closing +WebSocket.CLOSING = WebSocket.prototype.CLOSING = states.CLOSING +// https://websockets.spec.whatwg.org/#dom-websocket-closed +WebSocket.CLOSED = WebSocket.prototype.CLOSED = states.CLOSED +Object.defineProperties(WebSocket.prototype, { + CONNECTING: staticPropertyDescriptors, + OPEN: staticPropertyDescriptors, + CLOSING: staticPropertyDescriptors, + CLOSED: staticPropertyDescriptors, + url: kEnumerableProperty, + readyState: kEnumerableProperty, + bufferedAmount: kEnumerableProperty, + onopen: kEnumerableProperty, + onerror: kEnumerableProperty, + onclose: kEnumerableProperty, + close: kEnumerableProperty, + onmessage: kEnumerableProperty, + binaryType: kEnumerableProperty, + send: kEnumerableProperty, + extensions: kEnumerableProperty, + protocol: kEnumerableProperty, + [Symbol.toStringTag]: { + value: 'WebSocket', + writable: false, + enumerable: false, + configurable: true + } +}) -/***/ }), +Object.defineProperties(WebSocket, { + CONNECTING: staticPropertyDescriptors, + OPEN: staticPropertyDescriptors, + CLOSING: staticPropertyDescriptors, + CLOSED: staticPropertyDescriptors +}) -/***/ 1146: -/***/ ((module) => { +webidl.converters['sequence'] = webidl.sequenceConverter( + webidl.converters.DOMString +) -"use strict"; +webidl.converters['DOMString or sequence'] = function (V, prefix, argument) { + if (webidl.util.Type(V) === 'Object' && Symbol.iterator in V) { + return webidl.converters['sequence'](V) + } + return webidl.converters.DOMString(V, prefix, argument) +} -/** - * @see https://developer.mozilla.org/docs/Web/HTTP/Headers - */ -const wellknownHeaderNames = /** @type {const} */ ([ - 'Accept', - 'Accept-Encoding', - 'Accept-Language', - 'Accept-Ranges', - 'Access-Control-Allow-Credentials', - 'Access-Control-Allow-Headers', - 'Access-Control-Allow-Methods', - 'Access-Control-Allow-Origin', - 'Access-Control-Expose-Headers', - 'Access-Control-Max-Age', - 'Access-Control-Request-Headers', - 'Access-Control-Request-Method', - 'Age', - 'Allow', - 'Alt-Svc', - 'Alt-Used', - 'Authorization', - 'Cache-Control', - 'Clear-Site-Data', - 'Connection', - 'Content-Disposition', - 'Content-Encoding', - 'Content-Language', - 'Content-Length', - 'Content-Location', - 'Content-Range', - 'Content-Security-Policy', - 'Content-Security-Policy-Report-Only', - 'Content-Type', - 'Cookie', - 'Cross-Origin-Embedder-Policy', - 'Cross-Origin-Opener-Policy', - 'Cross-Origin-Resource-Policy', - 'Date', - 'Device-Memory', - 'Downlink', - 'ECT', - 'ETag', - 'Expect', - 'Expect-CT', - 'Expires', - 'Forwarded', - 'From', - 'Host', - 'If-Match', - 'If-Modified-Since', - 'If-None-Match', - 'If-Range', - 'If-Unmodified-Since', - 'Keep-Alive', - 'Last-Modified', - 'Link', - 'Location', - 'Max-Forwards', - 'Origin', - 'Permissions-Policy', - 'Pragma', - 'Proxy-Authenticate', - 'Proxy-Authorization', - 'RTT', - 'Range', - 'Referer', - 'Referrer-Policy', - 'Refresh', - 'Retry-After', - 'Sec-WebSocket-Accept', - 'Sec-WebSocket-Extensions', - 'Sec-WebSocket-Key', - 'Sec-WebSocket-Protocol', - 'Sec-WebSocket-Version', - 'Server', - 'Server-Timing', - 'Service-Worker-Allowed', - 'Service-Worker-Navigation-Preload', - 'Set-Cookie', - 'SourceMap', - 'Strict-Transport-Security', - 'Supports-Loading-Mode', - 'TE', - 'Timing-Allow-Origin', - 'Trailer', - 'Transfer-Encoding', - 'Upgrade', - 'Upgrade-Insecure-Requests', - 'User-Agent', - 'Vary', - 'Via', - 'WWW-Authenticate', - 'X-Content-Type-Options', - 'X-DNS-Prefetch-Control', - 'X-Frame-Options', - 'X-Permitted-Cross-Domain-Policies', - 'X-Powered-By', - 'X-Requested-With', - 'X-XSS-Protection' +// This implements the proposal made in https://github.com/whatwg/websockets/issues/42 +webidl.converters.WebSocketInit = webidl.dictionaryConverter([ + { + key: 'protocols', + converter: webidl.converters['DOMString or sequence'], + defaultValue: () => new Array(0) + }, + { + key: 'dispatcher', + converter: webidl.converters.any, + defaultValue: () => getGlobalDispatcher() + }, + { + key: 'headers', + converter: webidl.nullableConverter(webidl.converters.HeadersInit) + } ]) -/** @type {Record, string>} */ -const headerNameLowerCasedRecord = {} +webidl.converters['DOMString or sequence or WebSocketInit'] = function (V) { + if (webidl.util.Type(V) === 'Object' && !(Symbol.iterator in V)) { + return webidl.converters.WebSocketInit(V) + } -// Note: object prototypes should not be able to be referenced. e.g. `Object#hasOwnProperty`. -Object.setPrototypeOf(headerNameLowerCasedRecord, null) + return { protocols: webidl.converters['DOMString or sequence'](V) } +} -/** - * @type {Record, Buffer>} - */ -const wellknownHeaderNameBuffers = {} +webidl.converters.WebSocketSendData = function (V) { + if (webidl.util.Type(V) === 'Object') { + if (isBlobLike(V)) { + return webidl.converters.Blob(V, { strict: false }) + } -// Note: object prototypes should not be able to be referenced. e.g. `Object#hasOwnProperty`. -Object.setPrototypeOf(wellknownHeaderNameBuffers, null) + if (ArrayBuffer.isView(V) || types.isArrayBuffer(V)) { + return webidl.converters.BufferSource(V) + } + } -/** - * @param {string} header Lowercased header - * @returns {Buffer} - */ -function getHeaderNameAsBuffer (header) { - let buffer = wellknownHeaderNameBuffers[header] + return webidl.converters.USVString(V) +} - if (buffer === undefined) { - buffer = Buffer.from(header) +function onParserDrain () { + this.ws[kResponse].socket.resume() +} + +function onParserError (err) { + let message + let code + + if (err instanceof CloseEvent) { + message = err.reason + code = err.code + } else { + message = err.message } - return buffer -} + fireEvent('error', this, () => new ErrorEvent('error', { error: err, message })) -for (let i = 0; i < wellknownHeaderNames.length; ++i) { - const key = wellknownHeaderNames[i] - const lowerCasedKey = key.toLowerCase() - headerNameLowerCasedRecord[key] = headerNameLowerCasedRecord[lowerCasedKey] = - lowerCasedKey + closeWebSocketConnection(this, code) } module.exports = { - wellknownHeaderNames, - headerNameLowerCasedRecord, - getHeaderNameAsBuffer + WebSocket } /***/ }), -/***/ 6591: +/***/ 2514: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; +var __webpack_unused_export__; -const diagnosticsChannel = __nccwpck_require__(3053) -const util = __nccwpck_require__(7975) +const Client = __nccwpck_require__(1115) +const Dispatcher = __nccwpck_require__(5085) +const Pool = __nccwpck_require__(8034) +const BalancedPool = __nccwpck_require__(1083) +const RoundRobinPool = __nccwpck_require__(4626) +const Agent = __nccwpck_require__(9959) +const ProxyAgent = __nccwpck_require__(2050) +const EnvHttpProxyAgent = __nccwpck_require__(5071) +const RetryAgent = __nccwpck_require__(5908) +const H2CClient = __nccwpck_require__(861) +const errors = __nccwpck_require__(5093) +const util = __nccwpck_require__(2550) +const { InvalidArgumentError } = errors +const api = __nccwpck_require__(8557) +const buildConnector = __nccwpck_require__(1430) +const MockClient = __nccwpck_require__(5627) +const { MockCallHistory, MockCallHistoryLog } = __nccwpck_require__(3285) +const MockAgent = __nccwpck_require__(839) +const MockPool = __nccwpck_require__(6466) +const SnapshotAgent = __nccwpck_require__(4357) +const mockErrors = __nccwpck_require__(3831) +const RetryHandler = __nccwpck_require__(1557) +const { getGlobalDispatcher, setGlobalDispatcher } = __nccwpck_require__(7483) +const DecoratorHandler = __nccwpck_require__(169) +const RedirectHandler = __nccwpck_require__(4628) -const undiciDebugLog = util.debuglog('undici') -const fetchDebuglog = util.debuglog('fetch') -const websocketDebuglog = util.debuglog('websocket') +Object.assign(Dispatcher.prototype, api) -const channels = { - // Client - beforeConnect: diagnosticsChannel.channel('undici:client:beforeConnect'), - connected: diagnosticsChannel.channel('undici:client:connected'), - connectError: diagnosticsChannel.channel('undici:client:connectError'), - sendHeaders: diagnosticsChannel.channel('undici:client:sendHeaders'), - // Request - create: diagnosticsChannel.channel('undici:request:create'), - bodySent: diagnosticsChannel.channel('undici:request:bodySent'), - bodyChunkSent: diagnosticsChannel.channel('undici:request:bodyChunkSent'), - bodyChunkReceived: diagnosticsChannel.channel('undici:request:bodyChunkReceived'), - headers: diagnosticsChannel.channel('undici:request:headers'), - trailers: diagnosticsChannel.channel('undici:request:trailers'), - error: diagnosticsChannel.channel('undici:request:error'), - // WebSocket - open: diagnosticsChannel.channel('undici:websocket:open'), - close: diagnosticsChannel.channel('undici:websocket:close'), - socketError: diagnosticsChannel.channel('undici:websocket:socket_error'), - ping: diagnosticsChannel.channel('undici:websocket:ping'), - pong: diagnosticsChannel.channel('undici:websocket:pong'), - // ProxyAgent - proxyConnected: diagnosticsChannel.channel('undici:proxy:connected') +__webpack_unused_export__ = Dispatcher +__webpack_unused_export__ = Client +__webpack_unused_export__ = Pool +__webpack_unused_export__ = BalancedPool +__webpack_unused_export__ = RoundRobinPool +__webpack_unused_export__ = Agent +__webpack_unused_export__ = ProxyAgent +module.exports.J2 = EnvHttpProxyAgent +__webpack_unused_export__ = RetryAgent +__webpack_unused_export__ = H2CClient +__webpack_unused_export__ = RetryHandler + +__webpack_unused_export__ = DecoratorHandler +__webpack_unused_export__ = RedirectHandler +__webpack_unused_export__ = { + redirect: __nccwpck_require__(3640), + responseError: __nccwpck_require__(4732), + retry: __nccwpck_require__(9128), + dump: __nccwpck_require__(3694), + dns: __nccwpck_require__(3014), + cache: __nccwpck_require__(5668), + decompress: __nccwpck_require__(7355), + deduplicate: __nccwpck_require__(2010) +} + +__webpack_unused_export__ = { + MemoryCacheStore: __nccwpck_require__(2947) +} + +const SqliteCacheStore = __nccwpck_require__(9707) +__webpack_unused_export__ = SqliteCacheStore + +__webpack_unused_export__ = buildConnector +__webpack_unused_export__ = errors +__webpack_unused_export__ = { + parseHeaders: util.parseHeaders, + headerNameToString: util.headerNameToString } -let isTrackingClientEvents = false +function makeDispatcher (fn) { + return (url, opts, handler) => { + if (typeof opts === 'function') { + handler = opts + opts = null + } -function trackClientEvents (debugLog = undiciDebugLog) { - if (isTrackingClientEvents) { - return - } + if (!url || (typeof url !== 'string' && typeof url !== 'object' && !(url instanceof URL))) { + throw new InvalidArgumentError('invalid url') + } - // Check if any of the channels already have subscribers to prevent duplicate subscriptions - // This can happen when both Node.js built-in undici and undici as a dependency are present - if (channels.beforeConnect.hasSubscribers || channels.connected.hasSubscribers || - channels.connectError.hasSubscribers || channels.sendHeaders.hasSubscribers) { - isTrackingClientEvents = true - return - } + if (opts != null && typeof opts !== 'object') { + throw new InvalidArgumentError('invalid opts') + } - isTrackingClientEvents = true + if (opts && opts.path != null) { + if (typeof opts.path !== 'string') { + throw new InvalidArgumentError('invalid opts.path') + } - diagnosticsChannel.subscribe('undici:client:beforeConnect', - evt => { - const { - connectParams: { version, protocol, port, host } - } = evt - debugLog( - 'connecting to %s%s using %s%s', - host, - port ? `:${port}` : '', - protocol, - version - ) - }) + let path = opts.path + if (!opts.path.startsWith('/')) { + path = `/${path}` + } - diagnosticsChannel.subscribe('undici:client:connected', - evt => { - const { - connectParams: { version, protocol, port, host } - } = evt - debugLog( - 'connected to %s%s using %s%s', - host, - port ? `:${port}` : '', - protocol, - version - ) - }) + url = new URL(util.parseOrigin(url).origin + path) + } else { + if (!opts) { + opts = typeof url === 'object' ? url : {} + } - diagnosticsChannel.subscribe('undici:client:connectError', - evt => { - const { - connectParams: { version, protocol, port, host }, - error - } = evt - debugLog( - 'connection to %s%s using %s%s errored - %s', - host, - port ? `:${port}` : '', - protocol, - version, - error.message - ) - }) + url = util.parseURL(url) + } - diagnosticsChannel.subscribe('undici:client:sendHeaders', - evt => { - const { - request: { method, path, origin } - } = evt - debugLog('sending request to %s %s%s', method, origin, path) - }) + const { agent, dispatcher = getGlobalDispatcher() } = opts + + if (agent) { + throw new InvalidArgumentError('unsupported opts.agent. Did you mean opts.client?') + } + + return fn.call(dispatcher, { + ...opts, + origin: url.origin, + path: url.search ? `${url.pathname}${url.search}` : url.pathname, + method: opts.method || (opts.body ? 'PUT' : 'GET') + }, handler) + } } -let isTrackingRequestEvents = false +__webpack_unused_export__ = setGlobalDispatcher +__webpack_unused_export__ = getGlobalDispatcher -function trackRequestEvents (debugLog = undiciDebugLog) { - if (isTrackingRequestEvents) { +const fetchImpl = (__nccwpck_require__(5288).fetch) + +function appendFetchStackTrace (err, filename) { + if (!err || typeof err !== 'object') { return } - // Check if any of the channels already have subscribers to prevent duplicate subscriptions - // This can happen when both Node.js built-in undici and undici as a dependency are present - if (channels.headers.hasSubscribers || channels.trailers.hasSubscribers || - channels.error.hasSubscribers) { - isTrackingRequestEvents = true + const stack = typeof err.stack === 'string' ? err.stack : '' + const normalizedFilename = filename.replace(/\\/g, '/') + + if (stack && (stack.includes(filename) || stack.includes(normalizedFilename))) { return } - isTrackingRequestEvents = true + const capture = {} + Error.captureStackTrace(capture, appendFetchStackTrace) - diagnosticsChannel.subscribe('undici:request:headers', - evt => { - const { - request: { method, path, origin }, - response: { statusCode } - } = evt - debugLog( - 'received response to %s %s%s - HTTP %d', - method, - origin, - path, - statusCode - ) - }) + if (!capture.stack) { + return + } - diagnosticsChannel.subscribe('undici:request:trailers', - evt => { - const { - request: { method, path, origin } - } = evt - debugLog('trailers received from %s %s%s', method, origin, path) - }) + const captureLines = capture.stack.split('\n').slice(1).join('\n') - diagnosticsChannel.subscribe('undici:request:error', - evt => { - const { - request: { method, path, origin }, - error - } = evt - debugLog( - 'request to %s %s%s errored - %s', - method, - origin, - path, - error.message - ) - }) + err.stack = stack ? `${stack}\n${captureLines}` : capture.stack } -let isTrackingWebSocketEvents = false +module.exports.hd = function fetch (init, options = undefined) { + return fetchImpl(init, options).catch(err => { + appendFetchStackTrace(err, __filename) + throw err + }) +} +module.exports.Headers = __nccwpck_require__(7754).Headers +module.exports.Response = __nccwpck_require__(4545).Response +module.exports.Request = __nccwpck_require__(4517).Request +module.exports.FormData = __nccwpck_require__(3756).FormData -function trackWebSocketEvents (debugLog = websocketDebuglog) { - if (isTrackingWebSocketEvents) { - return - } +const { setGlobalOrigin, getGlobalOrigin } = __nccwpck_require__(1393) - // Check if any of the channels already have subscribers to prevent duplicate subscriptions - // This can happen when both Node.js built-in undici and undici as a dependency are present - if (channels.open.hasSubscribers || channels.close.hasSubscribers || - channels.socketError.hasSubscribers || channels.ping.hasSubscribers || - channels.pong.hasSubscribers) { - isTrackingWebSocketEvents = true - return - } +__webpack_unused_export__ = setGlobalOrigin +__webpack_unused_export__ = getGlobalOrigin - isTrackingWebSocketEvents = true +const { CacheStorage } = __nccwpck_require__(2335) +const { kConstruct } = __nccwpck_require__(8261) - diagnosticsChannel.subscribe('undici:websocket:open', - evt => { - const { - address: { address, port } - } = evt - debugLog('connection opened %s%s', address, port ? `:${port}` : '') - }) +__webpack_unused_export__ = new CacheStorage(kConstruct) - diagnosticsChannel.subscribe('undici:websocket:close', - evt => { - const { websocket, code, reason } = evt - debugLog( - 'closed connection to %s - %s %s', - websocket.url, - code, - reason - ) - }) +const { deleteCookie, getCookies, getSetCookies, setCookie, parseCookie } = __nccwpck_require__(1051) - diagnosticsChannel.subscribe('undici:websocket:socket_error', - err => { - debugLog('connection errored - %s', err.message) - }) +__webpack_unused_export__ = deleteCookie +__webpack_unused_export__ = getCookies +__webpack_unused_export__ = getSetCookies +__webpack_unused_export__ = setCookie +__webpack_unused_export__ = parseCookie - diagnosticsChannel.subscribe('undici:websocket:ping', - evt => { - debugLog('ping received') - }) +const { parseMIMEType, serializeAMimeType } = __nccwpck_require__(1410) - diagnosticsChannel.subscribe('undici:websocket:pong', - evt => { - debugLog('pong received') - }) -} +__webpack_unused_export__ = parseMIMEType +__webpack_unused_export__ = serializeAMimeType -if (undiciDebugLog.enabled || fetchDebuglog.enabled) { - trackClientEvents(fetchDebuglog.enabled ? fetchDebuglog : undiciDebugLog) - trackRequestEvents(fetchDebuglog.enabled ? fetchDebuglog : undiciDebugLog) -} +const { CloseEvent, ErrorEvent, MessageEvent } = __nccwpck_require__(1954) +const { WebSocket, ping } = __nccwpck_require__(1652) +module.exports.kb = WebSocket +module.exports.rd = CloseEvent +module.exports.NN = ErrorEvent +module.exports.aM = MessageEvent +__webpack_unused_export__ = ping -if (websocketDebuglog.enabled) { - trackClientEvents(undiciDebugLog.enabled ? undiciDebugLog : websocketDebuglog) - trackWebSocketEvents(websocketDebuglog) -} +/* unused reexport */ __nccwpck_require__(6519).WebSocketStream +/* unused reexport */ __nccwpck_require__(7145).WebSocketError -module.exports = { - channels +__webpack_unused_export__ = makeDispatcher(api.request) +__webpack_unused_export__ = makeDispatcher(api.stream) +__webpack_unused_export__ = makeDispatcher(api.pipeline) +__webpack_unused_export__ = makeDispatcher(api.connect) +__webpack_unused_export__ = makeDispatcher(api.upgrade) + +__webpack_unused_export__ = MockClient +__webpack_unused_export__ = MockCallHistory +__webpack_unused_export__ = MockCallHistoryLog +__webpack_unused_export__ = MockPool +__webpack_unused_export__ = MockAgent +__webpack_unused_export__ = SnapshotAgent +__webpack_unused_export__ = mockErrors + +const { EventSource } = __nccwpck_require__(436) + +module.exports.GD = EventSource + +function install () { + globalThis.fetch = module.exports.hd + globalThis.Headers = module.exports.Headers + globalThis.Response = module.exports.Response + globalThis.Request = module.exports.Request + globalThis.FormData = module.exports.FormData + globalThis.WebSocket = module.exports.kb + globalThis.CloseEvent = module.exports.rd + globalThis.ErrorEvent = module.exports.NN + globalThis.MessageEvent = module.exports.aM + globalThis.EventSource = module.exports.GD } +__webpack_unused_export__ = install + /***/ }), -/***/ 4928: -/***/ ((module) => { +/***/ 3324: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -const kUndiciError = Symbol.for('undici.error.UND_ERR') -class UndiciError extends Error { - constructor (message, options) { - super(message, options) - this.name = 'UndiciError' - this.code = 'UND_ERR' - } +const { addAbortListener } = __nccwpck_require__(2550) +const { RequestAbortedError } = __nccwpck_require__(5093) - static [Symbol.hasInstance] (instance) { - return instance && instance[kUndiciError] === true - } +const kListener = Symbol('kListener') +const kSignal = Symbol('kSignal') - get [kUndiciError] () { - return true +function abort (self) { + if (self.abort) { + self.abort(self[kSignal]?.reason) + } else { + self.reason = self[kSignal]?.reason ?? new RequestAbortedError() } + removeSignal(self) } -const kConnectTimeoutError = Symbol.for('undici.error.UND_ERR_CONNECT_TIMEOUT') -class ConnectTimeoutError extends UndiciError { - constructor (message) { - super(message) - this.name = 'ConnectTimeoutError' - this.message = message || 'Connect Timeout Error' - this.code = 'UND_ERR_CONNECT_TIMEOUT' - } +function addSignal (self, signal) { + self.reason = null - static [Symbol.hasInstance] (instance) { - return instance && instance[kConnectTimeoutError] === true - } + self[kSignal] = null + self[kListener] = null - get [kConnectTimeoutError] () { - return true + if (!signal) { + return } -} -const kHeadersTimeoutError = Symbol.for('undici.error.UND_ERR_HEADERS_TIMEOUT') -class HeadersTimeoutError extends UndiciError { - constructor (message) { - super(message) - this.name = 'HeadersTimeoutError' - this.message = message || 'Headers Timeout Error' - this.code = 'UND_ERR_HEADERS_TIMEOUT' + if (signal.aborted) { + abort(self) + return } - static [Symbol.hasInstance] (instance) { - return instance && instance[kHeadersTimeoutError] === true + self[kSignal] = signal + self[kListener] = () => { + abort(self) } - get [kHeadersTimeoutError] () { - return true - } + addAbortListener(self[kSignal], self[kListener]) } -const kHeadersOverflowError = Symbol.for('undici.error.UND_ERR_HEADERS_OVERFLOW') -class HeadersOverflowError extends UndiciError { - constructor (message) { - super(message) - this.name = 'HeadersOverflowError' - this.message = message || 'Headers Overflow Error' - this.code = 'UND_ERR_HEADERS_OVERFLOW' +function removeSignal (self) { + if (!self[kSignal]) { + return } - static [Symbol.hasInstance] (instance) { - return instance && instance[kHeadersOverflowError] === true + if ('removeEventListener' in self[kSignal]) { + self[kSignal].removeEventListener('abort', self[kListener]) + } else { + self[kSignal].removeListener('abort', self[kListener]) } - get [kHeadersOverflowError] () { - return true - } + self[kSignal] = null + self[kListener] = null } -const kBodyTimeoutError = Symbol.for('undici.error.UND_ERR_BODY_TIMEOUT') -class BodyTimeoutError extends UndiciError { - constructor (message) { - super(message) - this.name = 'BodyTimeoutError' - this.message = message || 'Body Timeout Error' - this.code = 'UND_ERR_BODY_TIMEOUT' - } - - static [Symbol.hasInstance] (instance) { - return instance && instance[kBodyTimeoutError] === true - } - - get [kBodyTimeoutError] () { - return true - } +module.exports = { + addSignal, + removeSignal } -const kInvalidArgumentError = Symbol.for('undici.error.UND_ERR_INVALID_ARG') -class InvalidArgumentError extends UndiciError { - constructor (message) { - super(message) - this.name = 'InvalidArgumentError' - this.message = message || 'Invalid Argument Error' - this.code = 'UND_ERR_INVALID_ARG' - } - static [Symbol.hasInstance] (instance) { - return instance && instance[kInvalidArgumentError] === true - } +/***/ }), - get [kInvalidArgumentError] () { - return true - } -} +/***/ 2898: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -const kInvalidReturnValueError = Symbol.for('undici.error.UND_ERR_INVALID_RETURN_VALUE') -class InvalidReturnValueError extends UndiciError { - constructor (message) { - super(message) - this.name = 'InvalidReturnValueError' - this.message = message || 'Invalid Return Value Error' - this.code = 'UND_ERR_INVALID_RETURN_VALUE' - } - static [Symbol.hasInstance] (instance) { - return instance && instance[kInvalidReturnValueError] === true - } - get [kInvalidReturnValueError] () { - return true - } -} +const assert = __nccwpck_require__(4589) +const { AsyncResource } = __nccwpck_require__(6698) +const { InvalidArgumentError, SocketError } = __nccwpck_require__(5093) +const util = __nccwpck_require__(2550) +const { addSignal, removeSignal } = __nccwpck_require__(3324) -const kAbortError = Symbol.for('undici.error.UND_ERR_ABORT') -class AbortError extends UndiciError { - constructor (message) { - super(message) - this.name = 'AbortError' - this.message = message || 'The operation was aborted' - this.code = 'UND_ERR_ABORT' - } +class ConnectHandler extends AsyncResource { + constructor (opts, callback) { + if (!opts || typeof opts !== 'object') { + throw new InvalidArgumentError('invalid opts') + } - static [Symbol.hasInstance] (instance) { - return instance && instance[kAbortError] === true - } + if (typeof callback !== 'function') { + throw new InvalidArgumentError('invalid callback') + } - get [kAbortError] () { - return true - } -} + const { signal, opaque, responseHeaders } = opts -const kRequestAbortedError = Symbol.for('undici.error.UND_ERR_ABORTED') -class RequestAbortedError extends AbortError { - constructor (message) { - super(message) - this.name = 'AbortError' - this.message = message || 'Request aborted' - this.code = 'UND_ERR_ABORTED' - } + if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { + throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') + } - static [Symbol.hasInstance] (instance) { - return instance && instance[kRequestAbortedError] === true - } + super('UNDICI_CONNECT') - get [kRequestAbortedError] () { - return true - } -} + this.opaque = opaque || null + this.responseHeaders = responseHeaders || null + this.callback = callback + this.abort = null -const kInformationalError = Symbol.for('undici.error.UND_ERR_INFO') -class InformationalError extends UndiciError { - constructor (message) { - super(message) - this.name = 'InformationalError' - this.message = message || 'Request information' - this.code = 'UND_ERR_INFO' + addSignal(this, signal) } - static [Symbol.hasInstance] (instance) { - return instance && instance[kInformationalError] === true - } + onConnect (abort, context) { + if (this.reason) { + abort(this.reason) + return + } - get [kInformationalError] () { - return true - } -} + assert(this.callback) -const kRequestContentLengthMismatchError = Symbol.for('undici.error.UND_ERR_REQ_CONTENT_LENGTH_MISMATCH') -class RequestContentLengthMismatchError extends UndiciError { - constructor (message) { - super(message) - this.name = 'RequestContentLengthMismatchError' - this.message = message || 'Request body length does not match content-length header' - this.code = 'UND_ERR_REQ_CONTENT_LENGTH_MISMATCH' + this.abort = abort + this.context = context } - static [Symbol.hasInstance] (instance) { - return instance && instance[kRequestContentLengthMismatchError] === true + onHeaders () { + throw new SocketError('bad connect', null) } - get [kRequestContentLengthMismatchError] () { - return true - } -} + onUpgrade (statusCode, rawHeaders, socket) { + const { callback, opaque, context } = this -const kResponseContentLengthMismatchError = Symbol.for('undici.error.UND_ERR_RES_CONTENT_LENGTH_MISMATCH') -class ResponseContentLengthMismatchError extends UndiciError { - constructor (message) { - super(message) - this.name = 'ResponseContentLengthMismatchError' - this.message = message || 'Response body length does not match content-length header' - this.code = 'UND_ERR_RES_CONTENT_LENGTH_MISMATCH' - } + removeSignal(this) - static [Symbol.hasInstance] (instance) { - return instance && instance[kResponseContentLengthMismatchError] === true - } + this.callback = null - get [kResponseContentLengthMismatchError] () { - return true - } -} + let headers = rawHeaders + // Indicates is an HTTP2Session + if (headers != null) { + headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) + } -const kClientDestroyedError = Symbol.for('undici.error.UND_ERR_DESTROYED') -class ClientDestroyedError extends UndiciError { - constructor (message) { - super(message) - this.name = 'ClientDestroyedError' - this.message = message || 'The client is destroyed' - this.code = 'UND_ERR_DESTROYED' + this.runInAsyncScope(callback, null, null, { + statusCode, + headers, + socket, + opaque, + context + }) } - static [Symbol.hasInstance] (instance) { - return instance && instance[kClientDestroyedError] === true - } + onError (err) { + const { callback, opaque } = this - get [kClientDestroyedError] () { - return true + removeSignal(this) + + if (callback) { + this.callback = null + queueMicrotask(() => { + this.runInAsyncScope(callback, null, err, { opaque }) + }) + } } } -const kClientClosedError = Symbol.for('undici.error.UND_ERR_CLOSED') -class ClientClosedError extends UndiciError { - constructor (message) { - super(message) - this.name = 'ClientClosedError' - this.message = message || 'The client is closed' - this.code = 'UND_ERR_CLOSED' +function connect (opts, callback) { + if (callback === undefined) { + return new Promise((resolve, reject) => { + connect.call(this, opts, (err, data) => { + return err ? reject(err) : resolve(data) + }) + }) } - static [Symbol.hasInstance] (instance) { - return instance && instance[kClientClosedError] === true - } + try { + const connectHandler = new ConnectHandler(opts, callback) + const connectOptions = { ...opts, method: 'CONNECT' } - get [kClientClosedError] () { - return true + this.dispatch(connectOptions, connectHandler) + } catch (err) { + if (typeof callback !== 'function') { + throw err + } + const opaque = opts?.opaque + queueMicrotask(() => callback(err, { opaque })) } } -const kSocketError = Symbol.for('undici.error.UND_ERR_SOCKET') -class SocketError extends UndiciError { - constructor (message, socket) { - super(message) - this.name = 'SocketError' - this.message = message || 'Socket error' - this.code = 'UND_ERR_SOCKET' - this.socket = socket - } +module.exports = connect - static [Symbol.hasInstance] (instance) { - return instance && instance[kSocketError] === true - } - get [kSocketError] () { - return true - } -} +/***/ }), -const kNotSupportedError = Symbol.for('undici.error.UND_ERR_NOT_SUPPORTED') -class NotSupportedError extends UndiciError { - constructor (message) { - super(message) - this.name = 'NotSupportedError' - this.message = message || 'Not supported error' - this.code = 'UND_ERR_NOT_SUPPORTED' - } +/***/ 6008: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - static [Symbol.hasInstance] (instance) { - return instance && instance[kNotSupportedError] === true - } - get [kNotSupportedError] () { - return true - } -} -const kBalancedPoolMissingUpstreamError = Symbol.for('undici.error.UND_ERR_BPL_MISSING_UPSTREAM') -class BalancedPoolMissingUpstreamError extends UndiciError { - constructor (message) { - super(message) - this.name = 'MissingUpstreamError' - this.message = message || 'No upstream has been added to the BalancedPool' - this.code = 'UND_ERR_BPL_MISSING_UPSTREAM' - } +const { + Readable, + Duplex, + PassThrough +} = __nccwpck_require__(7075) +const assert = __nccwpck_require__(4589) +const { AsyncResource } = __nccwpck_require__(6698) +const { + InvalidArgumentError, + InvalidReturnValueError, + RequestAbortedError +} = __nccwpck_require__(5093) +const util = __nccwpck_require__(2550) +const { addSignal, removeSignal } = __nccwpck_require__(3324) - static [Symbol.hasInstance] (instance) { - return instance && instance[kBalancedPoolMissingUpstreamError] === true - } +function noop () {} - get [kBalancedPoolMissingUpstreamError] () { - return true - } -} +const kResume = Symbol('resume') -const kHTTPParserError = Symbol.for('undici.error.UND_ERR_HTTP_PARSER') -class HTTPParserError extends Error { - constructor (message, code, data) { - super(message) - this.name = 'HTTPParserError' - this.code = code ? `HPE_${code}` : undefined - this.data = data ? data.toString() : undefined - } +class PipelineRequest extends Readable { + constructor () { + super({ autoDestroy: true }) - static [Symbol.hasInstance] (instance) { - return instance && instance[kHTTPParserError] === true + this[kResume] = null } - get [kHTTPParserError] () { - return true - } -} + _read () { + const { [kResume]: resume } = this -const kResponseExceededMaxSizeError = Symbol.for('undici.error.UND_ERR_RES_EXCEEDED_MAX_SIZE') -class ResponseExceededMaxSizeError extends UndiciError { - constructor (message) { - super(message) - this.name = 'ResponseExceededMaxSizeError' - this.message = message || 'Response content exceeded max size' - this.code = 'UND_ERR_RES_EXCEEDED_MAX_SIZE' + if (resume) { + this[kResume] = null + resume() + } } - static [Symbol.hasInstance] (instance) { - return instance && instance[kResponseExceededMaxSizeError] === true - } + _destroy (err, callback) { + this._read() - get [kResponseExceededMaxSizeError] () { - return true + callback(err) } } -const kRequestRetryError = Symbol.for('undici.error.UND_ERR_REQ_RETRY') -class RequestRetryError extends UndiciError { - constructor (message, code, { headers, data }) { - super(message) - this.name = 'RequestRetryError' - this.message = message || 'Request retry error' - this.code = 'UND_ERR_REQ_RETRY' - this.statusCode = code - this.data = data - this.headers = headers +class PipelineResponse extends Readable { + constructor (resume) { + super({ autoDestroy: true }) + this[kResume] = resume } - static [Symbol.hasInstance] (instance) { - return instance && instance[kRequestRetryError] === true + _read () { + this[kResume]() } - get [kRequestRetryError] () { - return true + _destroy (err, callback) { + if (!err && !this._readableState.endEmitted) { + err = new RequestAbortedError() + } + + callback(err) } } -const kResponseError = Symbol.for('undici.error.UND_ERR_RESPONSE') -class ResponseError extends UndiciError { - constructor (message, code, { headers, body }) { - super(message) - this.name = 'ResponseError' - this.message = message || 'Response error' - this.code = 'UND_ERR_RESPONSE' - this.statusCode = code - this.body = body - this.headers = headers - } +class PipelineHandler extends AsyncResource { + constructor (opts, handler) { + if (!opts || typeof opts !== 'object') { + throw new InvalidArgumentError('invalid opts') + } - static [Symbol.hasInstance] (instance) { - return instance && instance[kResponseError] === true - } + if (typeof handler !== 'function') { + throw new InvalidArgumentError('invalid handler') + } - get [kResponseError] () { - return true - } -} + const { signal, method, opaque, onInfo, responseHeaders } = opts -const kSecureProxyConnectionError = Symbol.for('undici.error.UND_ERR_PRX_TLS') -class SecureProxyConnectionError extends UndiciError { - constructor (cause, message, options = {}) { - super(message, { cause, ...options }) - this.name = 'SecureProxyConnectionError' - this.message = message || 'Secure Proxy Connection failed' - this.code = 'UND_ERR_PRX_TLS' - this.cause = cause - } + if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { + throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') + } - static [Symbol.hasInstance] (instance) { - return instance && instance[kSecureProxyConnectionError] === true - } + if (method === 'CONNECT') { + throw new InvalidArgumentError('invalid method') + } - get [kSecureProxyConnectionError] () { - return true - } -} + if (onInfo && typeof onInfo !== 'function') { + throw new InvalidArgumentError('invalid onInfo callback') + } -const kMaxOriginsReachedError = Symbol.for('undici.error.UND_ERR_MAX_ORIGINS_REACHED') -class MaxOriginsReachedError extends UndiciError { - constructor (message) { - super(message) - this.name = 'MaxOriginsReachedError' - this.message = message || 'Maximum allowed origins reached' - this.code = 'UND_ERR_MAX_ORIGINS_REACHED' - } + super('UNDICI_PIPELINE') - static [Symbol.hasInstance] (instance) { - return instance && instance[kMaxOriginsReachedError] === true - } + this.opaque = opaque || null + this.responseHeaders = responseHeaders || null + this.handler = handler + this.abort = null + this.context = null + this.onInfo = onInfo || null - get [kMaxOriginsReachedError] () { - return true - } -} + this.req = new PipelineRequest().on('error', noop) -module.exports = { - AbortError, - HTTPParserError, - UndiciError, - HeadersTimeoutError, - HeadersOverflowError, - BodyTimeoutError, - RequestContentLengthMismatchError, - ConnectTimeoutError, - InvalidArgumentError, - InvalidReturnValueError, - RequestAbortedError, - ClientDestroyedError, - ClientClosedError, - InformationalError, - SocketError, - NotSupportedError, - ResponseContentLengthMismatchError, - BalancedPoolMissingUpstreamError, - ResponseExceededMaxSizeError, - RequestRetryError, - ResponseError, - SecureProxyConnectionError, - MaxOriginsReachedError -} + this.ret = new Duplex({ + readableObjectMode: opts.objectMode, + autoDestroy: true, + read: () => { + const { body } = this + if (body?.resume) { + body.resume() + } + }, + write: (chunk, encoding, callback) => { + const { req } = this -/***/ }), + if (req.push(chunk, encoding) || req._readableState.destroyed) { + callback() + } else { + req[kResume] = callback + } + }, + destroy: (err, callback) => { + const { body, req, res, ret, abort } = this -/***/ 8990: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + if (!err && !ret._readableState.endEmitted) { + err = new RequestAbortedError() + } -"use strict"; + if (abort && err) { + abort() + } + util.destroy(body, err) + util.destroy(req, err) + util.destroy(res, err) -const { - InvalidArgumentError, - NotSupportedError -} = __nccwpck_require__(4928) -const assert = __nccwpck_require__(4589) -const { - isValidHTTPToken, - isValidHeaderValue, - isStream, - destroy, - isBuffer, - isFormDataLike, - isIterable, - isBlobLike, - serializePathWithQuery, - assertRequestHandler, - getServerName, - normalizedMethodRecords, - getProtocolFromUrlString -} = __nccwpck_require__(983) -const { channels } = __nccwpck_require__(6591) -const { headerNameLowerCasedRecord } = __nccwpck_require__(1146) + removeSignal(this) -// Verifies that a given path is valid does not contain control chars \x00 to \x20 -const invalidPathRegex = /[^\u0021-\u00ff]/ + callback(err) + } + }).on('prefinish', () => { + const { req } = this -const kHandler = Symbol('handler') + // Node < 15 does not call _final in same tick. + req.push(null) + }) -class Request { - constructor (origin, { - path, - method, - body, - headers, - query, - idempotent, - blocking, - upgrade, - headersTimeout, - bodyTimeout, - reset, - expectContinue, - servername, - throwOnError, - maxRedirections - }, handler) { - if (typeof path !== 'string') { - throw new InvalidArgumentError('path must be a string') - } else if ( - path[0] !== '/' && - !(path.startsWith('http://') || path.startsWith('https://')) && - method !== 'CONNECT' - ) { - throw new InvalidArgumentError('path must be an absolute URL or start with a slash') - } else if (invalidPathRegex.test(path)) { - throw new InvalidArgumentError('invalid request path') - } + this.res = null - if (typeof method !== 'string') { - throw new InvalidArgumentError('method must be a string') - } else if (normalizedMethodRecords[method] === undefined && !isValidHTTPToken(method)) { - throw new InvalidArgumentError('invalid request method') - } + addSignal(this, signal) + } - if (upgrade && typeof upgrade !== 'string') { - throw new InvalidArgumentError('upgrade must be a string') - } + onConnect (abort, context) { + const { res } = this - if (headersTimeout != null && (!Number.isFinite(headersTimeout) || headersTimeout < 0)) { - throw new InvalidArgumentError('invalid headersTimeout') + if (this.reason) { + abort(this.reason) + return } - if (bodyTimeout != null && (!Number.isFinite(bodyTimeout) || bodyTimeout < 0)) { - throw new InvalidArgumentError('invalid bodyTimeout') - } + assert(!res, 'pipeline cannot be retried') - if (reset != null && typeof reset !== 'boolean') { - throw new InvalidArgumentError('invalid reset') - } + this.abort = abort + this.context = context + } - if (expectContinue != null && typeof expectContinue !== 'boolean') { - throw new InvalidArgumentError('invalid expectContinue') - } + onHeaders (statusCode, rawHeaders, resume) { + const { opaque, handler, context } = this - if (throwOnError != null) { - throw new InvalidArgumentError('invalid throwOnError') + if (statusCode < 200) { + if (this.onInfo) { + const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) + this.onInfo({ statusCode, headers }) + } + return } - if (maxRedirections != null && maxRedirections !== 0) { - throw new InvalidArgumentError('maxRedirections is not supported, use the redirect interceptor') - } + this.res = new PipelineResponse(resume) - this.headersTimeout = headersTimeout + let body + try { + this.handler = null + const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) + body = this.runInAsyncScope(handler, null, { + statusCode, + headers, + opaque, + body: this.res, + context + }) + } catch (err) { + this.res.on('error', noop) + throw err + } - this.bodyTimeout = bodyTimeout + if (!body || typeof body.on !== 'function') { + throw new InvalidReturnValueError('expected Readable') + } - this.method = method + body + .on('data', (chunk) => { + const { ret, body } = this - this.abort = null + if (!ret.push(chunk) && body.pause) { + body.pause() + } + }) + .on('error', (err) => { + const { ret } = this - if (body == null) { - this.body = null - } else if (isStream(body)) { - this.body = body + util.destroy(ret, err) + }) + .on('end', () => { + const { ret } = this - const rState = this.body._readableState - if (!rState || !rState.autoDestroy) { - this.endHandler = function autoDestroy () { - destroy(this) - } - this.body.on('end', this.endHandler) - } + ret.push(null) + }) + .on('close', () => { + const { ret } = this - this.errorHandler = err => { - if (this.abort) { - this.abort(err) - } else { - this.error = err + if (!ret._readableState.ended) { + util.destroy(ret, new RequestAbortedError()) } - } - this.body.on('error', this.errorHandler) - } else if (isBuffer(body)) { - this.body = body.byteLength ? body : null - } else if (ArrayBuffer.isView(body)) { - this.body = body.buffer.byteLength ? Buffer.from(body.buffer, body.byteOffset, body.byteLength) : null - } else if (body instanceof ArrayBuffer) { - this.body = body.byteLength ? Buffer.from(body) : null - } else if (typeof body === 'string') { - this.body = body.length ? Buffer.from(body) : null - } else if (isFormDataLike(body) || isIterable(body) || isBlobLike(body)) { - this.body = body - } else { - throw new InvalidArgumentError('body must be a string, a Buffer, a Readable stream, an iterable, or an async iterable') - } + }) - this.completed = false - this.aborted = false + this.body = body + } - this.upgrade = upgrade || null + onData (chunk) { + const { res } = this + return res.push(chunk) + } - this.path = query ? serializePathWithQuery(path, query) : path + onComplete (trailers) { + const { res } = this + res.push(null) + } - // TODO: shall we maybe standardize it to an URL object? - this.origin = origin + onError (err) { + const { ret } = this + this.handler = null + util.destroy(ret, err) + } +} - this.protocol = getProtocolFromUrlString(origin) +function pipeline (opts, handler) { + try { + const pipelineHandler = new PipelineHandler(opts, handler) + this.dispatch({ ...opts, body: pipelineHandler.req }, pipelineHandler) + return pipelineHandler.ret + } catch (err) { + return new PassThrough().destroy(err) + } +} - this.idempotent = idempotent == null - ? method === 'HEAD' || method === 'GET' - : idempotent +module.exports = pipeline - this.blocking = blocking ?? this.method !== 'HEAD' - this.reset = reset == null ? null : reset +/***/ }), - this.host = null +/***/ 4381: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - this.contentLength = null - this.contentType = null - this.headers = [] +const assert = __nccwpck_require__(4589) +const { AsyncResource } = __nccwpck_require__(6698) +const { Readable } = __nccwpck_require__(5637) +const { InvalidArgumentError, RequestAbortedError } = __nccwpck_require__(5093) +const util = __nccwpck_require__(2550) - // Only for H2 - this.expectContinue = expectContinue != null ? expectContinue : false +function noop () {} - if (Array.isArray(headers)) { - if (headers.length % 2 !== 0) { - throw new InvalidArgumentError('headers array must be even') +class RequestHandler extends AsyncResource { + constructor (opts, callback) { + if (!opts || typeof opts !== 'object') { + throw new InvalidArgumentError('invalid opts') + } + + const { signal, method, opaque, body, onInfo, responseHeaders, highWaterMark } = opts + + try { + if (typeof callback !== 'function') { + throw new InvalidArgumentError('invalid callback') } - for (let i = 0; i < headers.length; i += 2) { - processHeader(this, headers[i], headers[i + 1]) + + if (highWaterMark && (typeof highWaterMark !== 'number' || highWaterMark < 0)) { + throw new InvalidArgumentError('invalid highWaterMark') } - } else if (headers && typeof headers === 'object') { - if (headers[Symbol.iterator]) { - for (const header of headers) { - if (!Array.isArray(header) || header.length !== 2) { - throw new InvalidArgumentError('headers must be in key-value pair format') - } - processHeader(this, header[0], header[1]) - } - } else { - const keys = Object.keys(headers) - for (let i = 0; i < keys.length; ++i) { - processHeader(this, keys[i], headers[keys[i]]) - } + + if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { + throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') } - } else if (headers != null) { - throw new InvalidArgumentError('headers must be an object or an array') - } - assertRequestHandler(handler, method, upgrade) + if (method === 'CONNECT') { + throw new InvalidArgumentError('invalid method') + } - this.servername = servername || getServerName(this.host) || null + if (onInfo && typeof onInfo !== 'function') { + throw new InvalidArgumentError('invalid onInfo callback') + } - this[kHandler] = handler + super('UNDICI_REQUEST') + } catch (err) { + if (util.isStream(body)) { + util.destroy(body.on('error', noop), err) + } + throw err + } - if (channels.create.hasSubscribers) { - channels.create.publish({ request: this }) + this.method = method + this.responseHeaders = responseHeaders || null + this.opaque = opaque || null + this.callback = callback + this.res = null + this.abort = null + this.body = body + this.trailers = {} + this.context = null + this.onInfo = onInfo || null + this.highWaterMark = highWaterMark + this.reason = null + this.removeAbortListener = null + + if (signal?.aborted) { + this.reason = signal.reason ?? new RequestAbortedError() + } else if (signal) { + this.removeAbortListener = util.addAbortListener(signal, () => { + this.reason = signal.reason ?? new RequestAbortedError() + if (this.res) { + util.destroy(this.res.on('error', noop), this.reason) + } else if (this.abort) { + this.abort(this.reason) + } + }) } } - onBodySent (chunk) { - if (channels.bodyChunkSent.hasSubscribers) { - channels.bodyChunkSent.publish({ request: this, chunk }) + onConnect (abort, context) { + if (this.reason) { + abort(this.reason) + return } - if (this[kHandler].onBodySent) { - try { - return this[kHandler].onBodySent(chunk) - } catch (err) { - this.abort(err) + + assert(this.callback) + + this.abort = abort + this.context = context + } + + onHeaders (statusCode, rawHeaders, resume, statusMessage) { + const { callback, opaque, abort, context, responseHeaders, highWaterMark } = this + + const headers = responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) + + if (statusCode < 200) { + if (this.onInfo) { + this.onInfo({ statusCode, headers }) } + return } - } - onRequestSent () { - if (channels.bodySent.hasSubscribers) { - channels.bodySent.publish({ request: this }) + const parsedHeaders = responseHeaders === 'raw' ? util.parseHeaders(rawHeaders) : headers + const contentType = parsedHeaders['content-type'] + const contentLength = parsedHeaders['content-length'] + const res = new Readable({ + resume, + abort, + contentType, + contentLength: this.method !== 'HEAD' && contentLength + ? Number(contentLength) + : null, + highWaterMark + }) + + if (this.removeAbortListener) { + res.on('close', this.removeAbortListener) + this.removeAbortListener = null } - if (this[kHandler].onRequestSent) { + this.callback = null + this.res = res + if (callback !== null) { try { - return this[kHandler].onRequestSent() + this.runInAsyncScope(callback, null, null, { + statusCode, + statusText: statusMessage, + headers, + trailers: this.trailers, + opaque, + body: res, + context + }) } catch (err) { - this.abort(err) + // If the callback throws synchronously, we need to handle it + // Remove reference to res to allow res being garbage collected + this.res = null + + // Destroy the response stream + util.destroy(res.on('error', noop), err) + + // Use queueMicrotask to re-throw the error so it reaches uncaughtException + queueMicrotask(() => { + throw err + }) } } } - onConnect (abort) { - assert(!this.aborted) - assert(!this.completed) - - if (this.error) { - abort(this.error) - } else { - this.abort = abort - return this[kHandler].onConnect(abort) - } + onData (chunk) { + return this.res.push(chunk) } - onResponseStarted () { - return this[kHandler].onResponseStarted?.() + onComplete (trailers) { + util.parseHeaders(trailers, this.trailers) + this.res.push(null) } - onHeaders (statusCode, headers, resume, statusText) { - assert(!this.aborted) - assert(!this.completed) + onError (err) { + const { res, callback, body, opaque } = this - if (channels.headers.hasSubscribers) { - channels.headers.publish({ request: this, response: { statusCode, headers, statusText } }) + if (callback) { + // TODO: Does this need queueMicrotask? + this.callback = null + queueMicrotask(() => { + this.runInAsyncScope(callback, null, err, { opaque }) + }) } - try { - return this[kHandler].onHeaders(statusCode, headers, resume, statusText) - } catch (err) { - this.abort(err) + if (res) { + this.res = null + // Ensure all queued handlers are invoked before destroying res. + queueMicrotask(() => { + util.destroy(res.on('error', noop), err) + }) } - } - onData (chunk) { - assert(!this.aborted) - assert(!this.completed) + if (body) { + this.body = null - if (channels.bodyChunkReceived.hasSubscribers) { - channels.bodyChunkReceived.publish({ request: this, chunk }) + if (util.isStream(body)) { + body.on('error', noop) + util.destroy(body, err) + } } - try { - return this[kHandler].onData(chunk) - } catch (err) { - this.abort(err) - return false + + if (this.removeAbortListener) { + this.removeAbortListener() + this.removeAbortListener = null } } +} - onUpgrade (statusCode, headers, socket) { - assert(!this.aborted) - assert(!this.completed) +function request (opts, callback) { + if (callback === undefined) { + return new Promise((resolve, reject) => { + request.call(this, opts, (err, data) => { + return err ? reject(err) : resolve(data) + }) + }) + } - return this[kHandler].onUpgrade(statusCode, headers, socket) + try { + const handler = new RequestHandler(opts, callback) + + this.dispatch(opts, handler) + } catch (err) { + if (typeof callback !== 'function') { + throw err + } + const opaque = opts?.opaque + queueMicrotask(() => callback(err, { opaque })) } +} - onComplete (trailers) { - this.onFinally() +module.exports = request +module.exports.RequestHandler = RequestHandler - assert(!this.aborted) - assert(!this.completed) - this.completed = true - if (channels.trailers.hasSubscribers) { - channels.trailers.publish({ request: this, trailers }) +/***/ }), + +/***/ 9310: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + + + +const assert = __nccwpck_require__(4589) +const { finished } = __nccwpck_require__(7075) +const { AsyncResource } = __nccwpck_require__(6698) +const { InvalidArgumentError, InvalidReturnValueError } = __nccwpck_require__(5093) +const util = __nccwpck_require__(2550) +const { addSignal, removeSignal } = __nccwpck_require__(3324) + +function noop () {} + +class StreamHandler extends AsyncResource { + constructor (opts, factory, callback) { + if (!opts || typeof opts !== 'object') { + throw new InvalidArgumentError('invalid opts') } + const { signal, method, opaque, body, onInfo, responseHeaders } = opts + try { - return this[kHandler].onComplete(trailers) + if (typeof callback !== 'function') { + throw new InvalidArgumentError('invalid callback') + } + + if (typeof factory !== 'function') { + throw new InvalidArgumentError('invalid factory') + } + + if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { + throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') + } + + if (method === 'CONNECT') { + throw new InvalidArgumentError('invalid method') + } + + if (onInfo && typeof onInfo !== 'function') { + throw new InvalidArgumentError('invalid onInfo callback') + } + + super('UNDICI_STREAM') } catch (err) { - // TODO (fix): This might be a bad idea? - this.onError(err) + if (util.isStream(body)) { + util.destroy(body.on('error', noop), err) + } + throw err } - } - onError (error) { - this.onFinally() + this.responseHeaders = responseHeaders || null + this.opaque = opaque || null + this.factory = factory + this.callback = callback + this.res = null + this.abort = null + this.context = null + this.trailers = null + this.body = body + this.onInfo = onInfo || null - if (channels.error.hasSubscribers) { - channels.error.publish({ request: this, error }) + if (util.isStream(body)) { + body.on('error', (err) => { + this.onError(err) + }) } - if (this.aborted) { + addSignal(this, signal) + } + + onConnect (abort, context) { + if (this.reason) { + abort(this.reason) return } - this.aborted = true - return this[kHandler].onError(error) + assert(this.callback) + + this.abort = abort + this.context = context } - onFinally () { - if (this.errorHandler) { - this.body.off('error', this.errorHandler) - this.errorHandler = null + onHeaders (statusCode, rawHeaders, resume, statusMessage) { + const { factory, opaque, context, responseHeaders } = this + + const headers = responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) + + if (statusCode < 200) { + if (this.onInfo) { + this.onInfo({ statusCode, headers }) + } + return } - if (this.endHandler) { - this.body.off('end', this.endHandler) - this.endHandler = null + this.factory = null + + if (factory === null) { + return } - } - addHeader (key, value) { - processHeader(this, key, value) - return this + const res = this.runInAsyncScope(factory, null, { + statusCode, + headers, + opaque, + context + }) + + if ( + !res || + typeof res.write !== 'function' || + typeof res.end !== 'function' || + typeof res.on !== 'function' + ) { + throw new InvalidReturnValueError('expected Writable') + } + + // TODO: Avoid finished. It registers an unnecessary amount of listeners. + finished(res, { readable: false }, (err) => { + const { callback, res, opaque, trailers, abort } = this + + this.res = null + if (err || !res?.readable) { + util.destroy(res, err) + } + + this.callback = null + this.runInAsyncScope(callback, null, err || null, { opaque, trailers }) + + if (err) { + abort() + } + }) + + res.on('drain', resume) + + this.res = res + + const needDrain = res.writableNeedDrain !== undefined + ? res.writableNeedDrain + : res._writableState?.needDrain + + return needDrain !== true } -} -function processHeader (request, key, val) { - if (val && (typeof val === 'object' && !Array.isArray(val))) { - throw new InvalidArgumentError(`invalid ${key} header`) - } else if (val === undefined) { - return + onData (chunk) { + const { res } = this + + return res ? res.write(chunk) : true } - let headerName = headerNameLowerCasedRecord[key] + onComplete (trailers) { + const { res } = this - if (headerName === undefined) { - headerName = key.toLowerCase() - if (headerNameLowerCasedRecord[headerName] === undefined && !isValidHTTPToken(headerName)) { - throw new InvalidArgumentError('invalid header key') + removeSignal(this) + + if (!res) { + return } + + this.trailers = util.parseHeaders(trailers) + + res.end() } - if (Array.isArray(val)) { - const arr = [] - for (let i = 0; i < val.length; i++) { - if (typeof val[i] === 'string') { - if (!isValidHeaderValue(val[i])) { - throw new InvalidArgumentError(`invalid ${key} header`) - } - arr.push(val[i]) - } else if (val[i] === null) { - arr.push('') - } else if (typeof val[i] === 'object') { - throw new InvalidArgumentError(`invalid ${key} header`) - } else { - arr.push(`${val[i]}`) - } + onError (err) { + const { res, callback, opaque, body } = this + + removeSignal(this) + + this.factory = null + + if (res) { + this.res = null + util.destroy(res, err) + } else if (callback) { + this.callback = null + queueMicrotask(() => { + this.runInAsyncScope(callback, null, err, { opaque }) + }) } - val = arr - } else if (typeof val === 'string') { - if (!isValidHeaderValue(val)) { - throw new InvalidArgumentError(`invalid ${key} header`) + + if (body) { + this.body = null + util.destroy(body, err) } - } else if (val === null) { - val = '' - } else { - val = `${val}` } +} - if (request.host === null && headerName === 'host') { - if (typeof val !== 'string') { - throw new InvalidArgumentError('invalid host header') - } - // Consumed by Client - request.host = val - } else if (request.contentLength === null && headerName === 'content-length') { - request.contentLength = parseInt(val, 10) - if (!Number.isFinite(request.contentLength)) { - throw new InvalidArgumentError('invalid content-length header') - } - } else if (request.contentType === null && headerName === 'content-type') { - request.contentType = val - request.headers.push(key, val) - } else if (headerName === 'transfer-encoding' || headerName === 'keep-alive' || headerName === 'upgrade') { - throw new InvalidArgumentError(`invalid ${headerName} header`) - } else if (headerName === 'connection') { - const value = typeof val === 'string' ? val.toLowerCase() : null - if (value !== 'close' && value !== 'keep-alive') { - throw new InvalidArgumentError('invalid connection header') - } +function stream (opts, factory, callback) { + if (callback === undefined) { + return new Promise((resolve, reject) => { + stream.call(this, opts, factory, (err, data) => { + return err ? reject(err) : resolve(data) + }) + }) + } - if (value === 'close') { - request.reset = true + try { + const handler = new StreamHandler(opts, factory, callback) + + this.dispatch(opts, handler) + } catch (err) { + if (typeof callback !== 'function') { + throw err } - } else if (headerName === 'expect') { - throw new NotSupportedError('expect header not supported') - } else { - request.headers.push(key, val) + const opaque = opts?.opaque + queueMicrotask(() => callback(err, { opaque })) } } -module.exports = Request +module.exports = stream /***/ }), -/***/ 9562: -/***/ ((module) => { +/***/ 2460: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -module.exports = { - kClose: Symbol('close'), - kDestroy: Symbol('destroy'), - kDispatch: Symbol('dispatch'), - kUrl: Symbol('url'), - kWriting: Symbol('writing'), - kResuming: Symbol('resuming'), - kQueue: Symbol('queue'), - kConnect: Symbol('connect'), - kConnecting: Symbol('connecting'), - kKeepAliveDefaultTimeout: Symbol('default keep alive timeout'), - kKeepAliveMaxTimeout: Symbol('max keep alive timeout'), - kKeepAliveTimeoutThreshold: Symbol('keep alive timeout threshold'), - kKeepAliveTimeoutValue: Symbol('keep alive timeout'), - kKeepAlive: Symbol('keep alive'), - kHeadersTimeout: Symbol('headers timeout'), - kBodyTimeout: Symbol('body timeout'), - kServerName: Symbol('server name'), - kLocalAddress: Symbol('local address'), - kHost: Symbol('host'), - kNoRef: Symbol('no ref'), - kBodyUsed: Symbol('used'), - kBody: Symbol('abstracted request body'), - kRunning: Symbol('running'), - kBlocking: Symbol('blocking'), - kPending: Symbol('pending'), - kSize: Symbol('size'), - kBusy: Symbol('busy'), - kQueued: Symbol('queued'), - kFree: Symbol('free'), - kConnected: Symbol('connected'), - kClosed: Symbol('closed'), - kNeedDrain: Symbol('need drain'), - kReset: Symbol('reset'), - kDestroyed: Symbol.for('nodejs.stream.destroyed'), - kResume: Symbol('resume'), - kOnError: Symbol('on error'), - kMaxHeadersSize: Symbol('max headers size'), - kRunningIdx: Symbol('running index'), - kPendingIdx: Symbol('pending index'), - kError: Symbol('error'), - kClients: Symbol('clients'), - kClient: Symbol('client'), - kParser: Symbol('parser'), - kOnDestroyed: Symbol('destroy callbacks'), - kPipelining: Symbol('pipelining'), - kSocket: Symbol('socket'), - kHostHeader: Symbol('host header'), - kConnector: Symbol('connector'), - kStrictContentLength: Symbol('strict content length'), - kMaxRedirections: Symbol('maxRedirections'), - kMaxRequests: Symbol('maxRequestsPerClient'), - kProxy: Symbol('proxy agent options'), - kCounter: Symbol('socket request counter'), - kMaxResponseSize: Symbol('max response size'), - kHTTP2Session: Symbol('http2Session'), - kHTTP2SessionState: Symbol('http2Session state'), - kRetryHandlerDefaultRetry: Symbol('retry agent default retry'), - kConstruct: Symbol('constructable'), - kListeners: Symbol('listeners'), - kHTTPContext: Symbol('http context'), - kMaxConcurrentStreams: Symbol('max concurrent streams'), - kHTTP2InitialWindowSize: Symbol('http2 initial window size'), - kHTTP2ConnectionWindowSize: Symbol('http2 connection window size'), - kEnableConnectProtocol: Symbol('http2session connect protocol'), - kRemoteSettings: Symbol('http2session remote settings'), - kHTTP2Stream: Symbol('http2session client stream'), - kNoProxyAgent: Symbol('no proxy agent'), - kHttpProxyAgent: Symbol('http proxy agent'), - kHttpsProxyAgent: Symbol('https proxy agent') -} +const { InvalidArgumentError, SocketError } = __nccwpck_require__(5093) +const { AsyncResource } = __nccwpck_require__(6698) +const assert = __nccwpck_require__(4589) +const util = __nccwpck_require__(2550) +const { kHTTP2Stream } = __nccwpck_require__(8261) +const { addSignal, removeSignal } = __nccwpck_require__(3324) +class UpgradeHandler extends AsyncResource { + constructor (opts, callback) { + if (!opts || typeof opts !== 'object') { + throw new InvalidArgumentError('invalid opts') + } -/***/ }), + if (typeof callback !== 'function') { + throw new InvalidArgumentError('invalid callback') + } -/***/ 6683: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + const { signal, opaque, responseHeaders } = opts -"use strict"; + if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { + throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') + } + super('UNDICI_UPGRADE') -const { - wellknownHeaderNames, - headerNameLowerCasedRecord -} = __nccwpck_require__(1146) + this.responseHeaders = responseHeaders || null + this.opaque = opaque || null + this.callback = callback + this.abort = null + this.context = null -class TstNode { - /** @type {any} */ - value = null - /** @type {null | TstNode} */ - left = null - /** @type {null | TstNode} */ - middle = null - /** @type {null | TstNode} */ - right = null - /** @type {number} */ - code - /** - * @param {string} key - * @param {any} value - * @param {number} index - */ - constructor (key, value, index) { - if (index === undefined || index >= key.length) { - throw new TypeError('Unreachable') - } - const code = this.code = key.charCodeAt(index) - // check code is ascii string - if (code > 0x7F) { - throw new TypeError('key must be ascii string') - } - if (key.length !== ++index) { - this.middle = new TstNode(key, value, index) - } else { - this.value = value - } + addSignal(this, signal) } - /** - * @param {string} key - * @param {any} value - * @returns {void} - */ - add (key, value) { - const length = key.length - if (length === 0) { - throw new TypeError('Unreachable') - } - let index = 0 - /** - * @type {TstNode} - */ - let node = this - while (true) { - const code = key.charCodeAt(index) - // check code is ascii string - if (code > 0x7F) { - throw new TypeError('key must be ascii string') - } - if (node.code === code) { - if (length === ++index) { - node.value = value - break - } else if (node.middle !== null) { - node = node.middle - } else { - node.middle = new TstNode(key, value, index) - break - } - } else if (node.code < code) { - if (node.left !== null) { - node = node.left - } else { - node.left = new TstNode(key, value, index) - break - } - } else if (node.right !== null) { - node = node.right - } else { - node.right = new TstNode(key, value, index) - break - } + onConnect (abort, context) { + if (this.reason) { + abort(this.reason) + return } + + assert(this.callback) + + this.abort = abort + this.context = null } - /** - * @param {Uint8Array} key - * @returns {TstNode | null} - */ - search (key) { - const keylength = key.length - let index = 0 - /** - * @type {TstNode|null} - */ - let node = this - while (node !== null && index < keylength) { - let code = key[index] - // A-Z - // First check if it is bigger than 0x5a. - // Lowercase letters have higher char codes than uppercase ones. - // Also we assume that headers will mostly contain lowercase characters. - if (code <= 0x5a && code >= 0x41) { - // Lowercase for uppercase. - code |= 32 - } - while (node !== null) { - if (code === node.code) { - if (keylength === ++index) { - // Returns Node since it is the last key. - return node - } - node = node.middle - break - } - node = node.code < code ? node.left : node.right - } - } - return null + onHeaders () { + throw new SocketError('bad upgrade', null) } -} -class TernarySearchTree { - /** @type {TstNode | null} */ - node = null + onUpgrade (statusCode, rawHeaders, socket) { + assert(socket[kHTTP2Stream] === true ? statusCode === 200 : statusCode === 101) - /** - * @param {string} key - * @param {any} value - * @returns {void} - * */ - insert (key, value) { - if (this.node === null) { - this.node = new TstNode(key, value, 0) - } else { - this.node.add(key, value) - } + const { callback, opaque, context } = this + + removeSignal(this) + + this.callback = null + const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) + this.runInAsyncScope(callback, null, null, { + headers, + socket, + opaque, + context + }) } - /** - * @param {Uint8Array} key - * @returns {any} - */ - lookup (key) { - return this.node?.search(key)?.value ?? null + onError (err) { + const { callback, opaque } = this + + removeSignal(this) + + if (callback) { + this.callback = null + queueMicrotask(() => { + this.runInAsyncScope(callback, null, err, { opaque }) + }) + } } } -const tree = new TernarySearchTree() +function upgrade (opts, callback) { + if (callback === undefined) { + return new Promise((resolve, reject) => { + upgrade.call(this, opts, (err, data) => { + return err ? reject(err) : resolve(data) + }) + }) + } -for (let i = 0; i < wellknownHeaderNames.length; ++i) { - const key = headerNameLowerCasedRecord[wellknownHeaderNames[i]] - tree.insert(key, key) -} + try { + const upgradeHandler = new UpgradeHandler(opts, callback) + const upgradeOpts = { + ...opts, + method: opts.method || 'GET', + upgrade: opts.protocol || 'Websocket' + } -module.exports = { - TernarySearchTree, - tree + this.dispatch(upgradeOpts, upgradeHandler) + } catch (err) { + if (typeof callback !== 'function') { + throw err + } + const opaque = opts?.opaque + queueMicrotask(() => callback(err, { opaque })) + } } +module.exports = upgrade + /***/ }), -/***/ 983: +/***/ 8557: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -const assert = __nccwpck_require__(4589) -const { kDestroyed, kBodyUsed, kListeners, kBody } = __nccwpck_require__(9562) -const { IncomingMessage } = __nccwpck_require__(7067) -const stream = __nccwpck_require__(7075) -const net = __nccwpck_require__(7030) -const { stringify } = __nccwpck_require__(1792) -const { EventEmitter: EE } = __nccwpck_require__(8474) -const timers = __nccwpck_require__(7280) -const { InvalidArgumentError, ConnectTimeoutError } = __nccwpck_require__(4928) -const { headerNameLowerCasedRecord } = __nccwpck_require__(1146) -const { tree } = __nccwpck_require__(6683) +module.exports.request = __nccwpck_require__(4381) +module.exports.stream = __nccwpck_require__(9310) +module.exports.pipeline = __nccwpck_require__(6008) +module.exports.upgrade = __nccwpck_require__(2460) +module.exports.connect = __nccwpck_require__(2898) -const [nodeMajor, nodeMinor] = process.versions.node.split('.', 2).map(v => Number(v)) -class BodyAsyncIterable { - constructor (body) { - this[kBody] = body - this[kBodyUsed] = false - } +/***/ }), - async * [Symbol.asyncIterator] () { - assert(!this[kBodyUsed], 'disturbed') - this[kBodyUsed] = true - yield * this[kBody] - } -} +/***/ 5637: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -function noop () {} -/** - * @param {*} body - * @returns {*} - */ -function wrapRequestBody (body) { - if (isStream(body)) { - // TODO (fix): Provide some way for the user to cache the file to e.g. /tmp - // so that it can be dispatched again? - // TODO (fix): Do we need 100-expect support to provide a way to do this properly? - if (bodyLength(body) === 0) { - body - .on('data', function () { - assert(false) - }) - } - if (typeof body.readableDidRead !== 'boolean') { - body[kBodyUsed] = false - EE.prototype.on.call(body, 'data', function () { - this[kBodyUsed] = true - }) - } +const assert = __nccwpck_require__(4589) +const { Readable } = __nccwpck_require__(7075) +const { RequestAbortedError, NotSupportedError, InvalidArgumentError, AbortError } = __nccwpck_require__(5093) +const util = __nccwpck_require__(2550) +const { ReadableStreamFrom } = __nccwpck_require__(2550) - return body - } else if (body && typeof body.pipeTo === 'function') { - // TODO (fix): We can't access ReadableStream internal state - // to determine whether or not it has been disturbed. This is just - // a workaround. - return new BodyAsyncIterable(body) - } else if (body && isFormDataLike(body)) { - return body - } else if ( - body && - typeof body !== 'string' && - !ArrayBuffer.isView(body) && - isIterable(body) - ) { - // TODO: Should we allow re-using iterable if !this.opts.idempotent - // or through some other flag? - return new BodyAsyncIterable(body) - } else { - return body - } -} +const kConsume = Symbol('kConsume') +const kReading = Symbol('kReading') +const kBody = Symbol('kBody') +const kAbort = Symbol('kAbort') +const kContentType = Symbol('kContentType') +const kContentLength = Symbol('kContentLength') +const kUsed = Symbol('kUsed') +const kBytesRead = Symbol('kBytesRead') -/** - * @param {*} obj - * @returns {obj is import('node:stream').Stream} - */ -function isStream (obj) { - return obj && typeof obj === 'object' && typeof obj.pipe === 'function' && typeof obj.on === 'function' -} +const noop = () => {} /** - * @param {*} object - * @returns {object is Blob} - * based on https://github.com/node-fetch/fetch-blob/blob/8ab587d34080de94140b54f07168451e7d0b655e/index.js#L229-L241 (MIT License) + * @class + * @extends {Readable} + * @see https://fetch.spec.whatwg.org/#body */ -function isBlobLike (object) { - if (object === null) { - return false - } else if (object instanceof Blob) { - return true - } else if (typeof object !== 'object') { - return false - } else { - const sTag = object[Symbol.toStringTag] +class BodyReadable extends Readable { + /** + * @param {object} opts + * @param {(this: Readable, size: number) => void} opts.resume + * @param {() => (void | null)} opts.abort + * @param {string} [opts.contentType = ''] + * @param {number} [opts.contentLength] + * @param {number} [opts.highWaterMark = 64 * 1024] + */ + constructor ({ + resume, + abort, + contentType = '', + contentLength, + highWaterMark = 64 * 1024 // Same as nodejs fs streams. + }) { + super({ + autoDestroy: true, + read: resume, + highWaterMark + }) - return (sTag === 'Blob' || sTag === 'File') && ( - ('stream' in object && typeof object.stream === 'function') || - ('arrayBuffer' in object && typeof object.arrayBuffer === 'function') - ) - } -} + this._readableState.dataEmitted = false -/** - * @param {string} url The path to check for query strings or fragments. - * @returns {boolean} Returns true if the path contains a query string or fragment. - */ -function pathHasQueryOrFragment (url) { - return ( - url.includes('?') || - url.includes('#') - ) -} + this[kAbort] = abort -/** - * @param {string} url The URL to add the query params to - * @param {import('node:querystring').ParsedUrlQueryInput} queryParams The object to serialize into a URL query string - * @returns {string} The URL with the query params added - */ -function serializePathWithQuery (url, queryParams) { - if (pathHasQueryOrFragment(url)) { - throw new Error('Query params cannot be passed when url already contains "?" or "#".') - } + /** @type {Consume | null} */ + this[kConsume] = null - const stringified = stringify(queryParams) + /** @type {number} */ + this[kBytesRead] = 0 - if (stringified) { - url += '?' + stringified - } + /** @type {ReadableStream|null} */ + this[kBody] = null - return url -} + /** @type {boolean} */ + this[kUsed] = false -/** - * @param {number|string|undefined} port - * @returns {boolean} - */ -function isValidPort (port) { - const value = parseInt(port, 10) - return ( - value === Number(port) && - value >= 0 && - value <= 65535 - ) -} + /** @type {string} */ + this[kContentType] = contentType -/** - * Check if the value is a valid http or https prefixed string. - * - * @param {string} value - * @returns {boolean} - */ -function isHttpOrHttpsPrefixed (value) { - return ( - value != null && - value[0] === 'h' && - value[1] === 't' && - value[2] === 't' && - value[3] === 'p' && - ( - value[4] === ':' || - ( - value[4] === 's' && - value[5] === ':' - ) - ) - ) -} + /** @type {number|null} */ + this[kContentLength] = Number.isFinite(contentLength) ? contentLength : null -/** - * @param {string|URL|Record} url - * @returns {URL} - */ -function parseURL (url) { - if (typeof url === 'string') { /** - * @type {URL} + * Is stream being consumed through Readable API? + * This is an optimization so that we avoid checking + * for 'data' and 'readable' listeners in the hot path + * inside push(). + * + * @type {boolean} */ - url = new URL(url) + this[kReading] = false + } - if (!isHttpOrHttpsPrefixed(url.origin || url.protocol)) { - throw new InvalidArgumentError('Invalid URL protocol: the URL must start with `http:` or `https:`.') + /** + * @param {Error|null} err + * @param {(error:(Error|null)) => void} callback + * @returns {void} + */ + _destroy (err, callback) { + if (!err && !this._readableState.endEmitted) { + err = new RequestAbortedError() } - return url - } + if (err) { + this[kAbort]() + } - if (!url || typeof url !== 'object') { - throw new InvalidArgumentError('Invalid URL: The URL argument must be a non-null object.') + // Workaround for Node "bug". If the stream is destroyed in same + // tick as it is created, then a user who is waiting for a + // promise (i.e micro tick) for installing an 'error' listener will + // never get a chance and will always encounter an unhandled exception. + if (!this[kUsed]) { + setImmediate(callback, err) + } else { + callback(err) + } } - if (!(url instanceof URL)) { - if (url.port != null && url.port !== '' && isValidPort(url.port) === false) { - throw new InvalidArgumentError('Invalid URL: port must be a valid integer or a string representation of an integer.') + /** + * @param {string|symbol} event + * @param {(...args: any[]) => void} listener + * @returns {this} + */ + on (event, listener) { + if (event === 'data' || event === 'readable') { + this[kReading] = true + this[kUsed] = true } + return super.on(event, listener) + } - if (url.path != null && typeof url.path !== 'string') { - throw new InvalidArgumentError('Invalid URL path: the path must be a string or null/undefined.') - } + /** + * @param {string|symbol} event + * @param {(...args: any[]) => void} listener + * @returns {this} + */ + addListener (event, listener) { + return this.on(event, listener) + } - if (url.pathname != null && typeof url.pathname !== 'string') { - throw new InvalidArgumentError('Invalid URL pathname: the pathname must be a string or null/undefined.') + /** + * @param {string|symbol} event + * @param {(...args: any[]) => void} listener + * @returns {this} + */ + off (event, listener) { + const ret = super.off(event, listener) + if (event === 'data' || event === 'readable') { + this[kReading] = ( + this.listenerCount('data') > 0 || + this.listenerCount('readable') > 0 + ) } + return ret + } - if (url.hostname != null && typeof url.hostname !== 'string') { - throw new InvalidArgumentError('Invalid URL hostname: the hostname must be a string or null/undefined.') - } + /** + * @param {string|symbol} event + * @param {(...args: any[]) => void} listener + * @returns {this} + */ + removeListener (event, listener) { + return this.off(event, listener) + } - if (url.origin != null && typeof url.origin !== 'string') { - throw new InvalidArgumentError('Invalid URL origin: the origin must be a string or null/undefined.') + /** + * @param {Buffer|null} chunk + * @returns {boolean} + */ + push (chunk) { + if (chunk) { + this[kBytesRead] += chunk.length + if (this[kConsume]) { + consumePush(this[kConsume], chunk) + return this[kReading] ? super.push(chunk) : true + } } - if (!isHttpOrHttpsPrefixed(url.origin || url.protocol)) { - throw new InvalidArgumentError('Invalid URL protocol: the URL must start with `http:` or `https:`.') - } + return super.push(chunk) + } - const port = url.port != null - ? url.port - : (url.protocol === 'https:' ? 443 : 80) - let origin = url.origin != null - ? url.origin - : `${url.protocol || ''}//${url.hostname || ''}:${port}` - let path = url.path != null - ? url.path - : `${url.pathname || ''}${url.search || ''}` + /** + * Consumes and returns the body as a string. + * + * @see https://fetch.spec.whatwg.org/#dom-body-text + * @returns {Promise} + */ + text () { + return consume(this, 'text') + } - if (origin[origin.length - 1] === '/') { - origin = origin.slice(0, origin.length - 1) - } + /** + * Consumes and returns the body as a JavaScript Object. + * + * @see https://fetch.spec.whatwg.org/#dom-body-json + * @returns {Promise} + */ + json () { + return consume(this, 'json') + } - if (path && path[0] !== '/') { - path = `/${path}` - } - // new URL(path, origin) is unsafe when `path` contains an absolute URL - // From https://developer.mozilla.org/en-US/docs/Web/API/URL/URL: - // If first parameter is a relative URL, second param is required, and will be used as the base URL. - // If first parameter is an absolute URL, a given second param will be ignored. - return new URL(`${origin}${path}`) + /** + * Consumes and returns the body as a Blob + * + * @see https://fetch.spec.whatwg.org/#dom-body-blob + * @returns {Promise} + */ + blob () { + return consume(this, 'blob') } - if (!isHttpOrHttpsPrefixed(url.origin || url.protocol)) { - throw new InvalidArgumentError('Invalid URL protocol: the URL must start with `http:` or `https:`.') + /** + * Consumes and returns the body as an Uint8Array. + * + * @see https://fetch.spec.whatwg.org/#dom-body-bytes + * @returns {Promise} + */ + bytes () { + return consume(this, 'bytes') } - return url -} + /** + * Consumes and returns the body as an ArrayBuffer. + * + * @see https://fetch.spec.whatwg.org/#dom-body-arraybuffer + * @returns {Promise} + */ + arrayBuffer () { + return consume(this, 'arrayBuffer') + } -/** - * @param {string|URL|Record} url - * @returns {URL} - */ -function parseOrigin (url) { - url = parseURL(url) + /** + * Not implemented + * + * @see https://fetch.spec.whatwg.org/#dom-body-formdata + * @throws {NotSupportedError} + */ + async formData () { + // TODO: Implement. + throw new NotSupportedError() + } - if (url.pathname !== '/' || url.search || url.hash) { - throw new InvalidArgumentError('invalid url') + /** + * Returns true if the body is not null and the body has been consumed. + * Otherwise, returns false. + * + * @see https://fetch.spec.whatwg.org/#dom-body-bodyused + * @readonly + * @returns {boolean} + */ + get bodyUsed () { + return util.isDisturbed(this) } - return url -} + /** + * @see https://fetch.spec.whatwg.org/#dom-body-body + * @readonly + * @returns {ReadableStream} + */ + get body () { + if (!this[kBody]) { + this[kBody] = ReadableStreamFrom(this) + if (this[kConsume]) { + // TODO: Is this the best way to force a lock? + this[kBody].getReader() // Ensure stream is locked. + assert(this[kBody].locked) + } + } + return this[kBody] + } -/** - * @param {string} host - * @returns {string} - */ -function getHostname (host) { - if (host[0] === '[') { - const idx = host.indexOf(']') + /** + * Dumps the response body by reading `limit` number of bytes. + * @param {object} opts + * @param {number} [opts.limit = 131072] Number of bytes to read. + * @param {AbortSignal} [opts.signal] An AbortSignal to cancel the dump. + * @returns {Promise} + */ + dump (opts) { + const signal = opts?.signal - assert(idx !== -1) - return host.substring(1, idx) - } + if (signal != null && (typeof signal !== 'object' || !('aborted' in signal))) { + return Promise.reject(new InvalidArgumentError('signal must be an AbortSignal')) + } - const idx = host.indexOf(':') - if (idx === -1) return host + const limit = opts?.limit && Number.isFinite(opts.limit) + ? opts.limit + : 128 * 1024 - return host.substring(0, idx) -} + if (signal?.aborted) { + return Promise.reject(signal.reason ?? new AbortError()) + } -/** - * IP addresses are not valid server names per RFC6066 - * Currently, the only server names supported are DNS hostnames - * @param {string|null} host - * @returns {string|null} - */ -function getServerName (host) { - if (!host) { - return null - } + if (this._readableState.closeEmitted) { + return Promise.resolve(null) + } - assert(typeof host === 'string') + return new Promise((resolve, reject) => { + if ( + (this[kContentLength] && (this[kContentLength] > limit)) || + this[kBytesRead] > limit + ) { + this.destroy(new AbortError()) + } - const servername = getHostname(host) - if (net.isIP(servername)) { - return '' + if (signal) { + const onAbort = () => { + this.destroy(signal.reason ?? new AbortError()) + } + signal.addEventListener('abort', onAbort) + this + .on('close', function () { + signal.removeEventListener('abort', onAbort) + if (signal.aborted) { + reject(signal.reason ?? new AbortError()) + } else { + resolve(null) + } + }) + } else { + this.on('close', resolve) + } + + this + .on('error', noop) + .on('data', () => { + if (this[kBytesRead] > limit) { + this.destroy() + } + }) + .resume() + }) } - return servername + /** + * @param {BufferEncoding} encoding + * @returns {this} + */ + setEncoding (encoding) { + if (Buffer.isEncoding(encoding)) { + this._readableState.encoding = encoding + } + return this + } } /** - * @function - * @template T - * @param {T} obj - * @returns {T} + * @see https://streams.spec.whatwg.org/#readablestream-locked + * @param {BodyReadable} bodyReadable + * @returns {boolean} */ -function deepClone (obj) { - return JSON.parse(JSON.stringify(obj)) +function isLocked (bodyReadable) { + // Consume is an implicit lock. + return bodyReadable[kBody]?.locked === true || bodyReadable[kConsume] !== null } /** - * @param {*} obj - * @returns {obj is AsyncIterable} + * @see https://fetch.spec.whatwg.org/#body-unusable + * @param {BodyReadable} bodyReadable + * @returns {boolean} */ -function isAsyncIterable (obj) { - return !!(obj != null && typeof obj[Symbol.asyncIterator] === 'function') +function isUnusable (bodyReadable) { + return util.isDisturbed(bodyReadable) || isLocked(bodyReadable) } /** - * @param {*} obj - * @returns {obj is Iterable} + * @typedef {'text' | 'json' | 'blob' | 'bytes' | 'arrayBuffer'} ConsumeType */ -function isIterable (obj) { - return !!(obj != null && (typeof obj[Symbol.iterator] === 'function' || typeof obj[Symbol.asyncIterator] === 'function')) -} /** - * @param {Blob|Buffer|import ('stream').Stream} body - * @returns {number|null} + * @template {ConsumeType} T + * @typedef {T extends 'text' ? string : + * T extends 'json' ? unknown : + * T extends 'blob' ? Blob : + * T extends 'arrayBuffer' ? ArrayBuffer : + * T extends 'bytes' ? Uint8Array : + * never + * } ConsumeReturnType + */ +/** + * @typedef {object} Consume + * @property {ConsumeType} type + * @property {BodyReadable} stream + * @property {((value?: any) => void)} resolve + * @property {((err: Error) => void)} reject + * @property {number} length + * @property {Buffer[]} body */ -function bodyLength (body) { - if (body == null) { - return 0 - } else if (isStream(body)) { - const state = body._readableState - return state && state.objectMode === false && state.ended === true && Number.isFinite(state.length) - ? state.length - : null - } else if (isBlobLike(body)) { - return body.size != null ? body.size : null - } else if (isBuffer(body)) { - return body.byteLength - } - - return null -} /** - * @param {import ('stream').Stream} body - * @returns {boolean} + * @template {ConsumeType} T + * @param {BodyReadable} stream + * @param {T} type + * @returns {Promise>} */ -function isDestroyed (body) { - return body && !!(body.destroyed || body[kDestroyed] || (stream.isDestroyed?.(body))) +function consume (stream, type) { + assert(!stream[kConsume]) + + return new Promise((resolve, reject) => { + if (isUnusable(stream)) { + const rState = stream._readableState + if (rState.destroyed && rState.closeEmitted === false) { + stream + .on('error', reject) + .on('close', () => { + reject(new TypeError('unusable')) + }) + } else { + reject(rState.errored ?? new TypeError('unusable')) + } + } else { + queueMicrotask(() => { + stream[kConsume] = { + type, + stream, + resolve, + reject, + length: 0, + body: [] + } + + stream + .on('error', function (err) { + consumeFinish(this[kConsume], err) + }) + .on('close', function () { + if (this[kConsume].body !== null) { + consumeFinish(this[kConsume], new RequestAbortedError()) + } + }) + + consumeStart(stream[kConsume]) + }) + } + }) } /** - * @param {import ('stream').Stream} stream - * @param {Error} [err] + * @param {Consume} consume * @returns {void} */ -function destroy (stream, err) { - if (stream == null || !isStream(stream) || isDestroyed(stream)) { +function consumeStart (consume) { + if (consume.body === null) { return } - if (typeof stream.destroy === 'function') { - if (Object.getPrototypeOf(stream).constructor === IncomingMessage) { - // See: https://github.com/nodejs/node/pull/38505/files - stream.socket = null + const { _readableState: state } = consume.stream + + if (state.bufferIndex) { + const start = state.bufferIndex + const end = state.buffer.length + for (let n = start; n < end; n++) { + consumePush(consume, state.buffer[n]) + } + } else { + for (const chunk of state.buffer) { + consumePush(consume, chunk) } + } - stream.destroy(err) - } else if (err) { - queueMicrotask(() => { - stream.emit('error', err) + if (state.endEmitted) { + consumeEnd(this[kConsume], this._readableState.encoding) + } else { + consume.stream.on('end', function () { + consumeEnd(this[kConsume], this._readableState.encoding) }) } - if (stream.destroyed !== true) { - stream[kDestroyed] = true - } -} + consume.stream.resume() -const KEEPALIVE_TIMEOUT_EXPR = /timeout=(\d+)/ -/** - * @param {string} val - * @returns {number | null} - */ -function parseKeepAliveTimeout (val) { - const m = val.match(KEEPALIVE_TIMEOUT_EXPR) - return m ? parseInt(m[1], 10) * 1000 : null + while (consume.stream.read() != null) { + // Loop + } } /** - * Retrieves a header name and returns its lowercase value. - * @param {string | Buffer} value Header name + * @param {Buffer[]} chunks + * @param {number} length + * @param {BufferEncoding} [encoding='utf8'] * @returns {string} */ -function headerNameToString (value) { - return typeof value === 'string' - ? headerNameLowerCasedRecord[value] ?? value.toLowerCase() - : tree.lookup(value) ?? value.toString('latin1').toLowerCase() +function chunksDecode (chunks, length, encoding) { + if (chunks.length === 0 || length === 0) { + return '' + } + const buffer = chunks.length === 1 ? chunks[0] : Buffer.concat(chunks, length) + const bufferLength = buffer.length + + // Skip BOM. + const start = + bufferLength > 2 && + buffer[0] === 0xef && + buffer[1] === 0xbb && + buffer[2] === 0xbf + ? 3 + : 0 + if (!encoding || encoding === 'utf8' || encoding === 'utf-8') { + return buffer.utf8Slice(start, bufferLength) + } else { + return buffer.subarray(start, bufferLength).toString(encoding) + } } /** - * Receive the buffer as a string and return its lowercase value. - * @param {Buffer} value Header name - * @returns {string} + * @param {Buffer[]} chunks + * @param {number} length + * @returns {Uint8Array} */ -function bufferToLowerCasedHeaderName (value) { - return tree.lookup(value) ?? value.toString('latin1').toLowerCase() +function chunksConcat (chunks, length) { + if (chunks.length === 0 || length === 0) { + return new Uint8Array(0) + } + if (chunks.length === 1) { + // fast-path + return new Uint8Array(chunks[0]) + } + const buffer = new Uint8Array(Buffer.allocUnsafeSlow(length).buffer) + + let offset = 0 + for (let i = 0; i < chunks.length; ++i) { + const chunk = chunks[i] + buffer.set(chunk, offset) + offset += chunk.length + } + + return buffer } /** - * @param {(Buffer | string)[]} headers - * @param {Record} [obj] - * @returns {Record} + * @param {Consume} consume + * @param {BufferEncoding} encoding + * @returns {void} */ -function parseHeaders (headers, obj) { - if (obj === undefined) obj = {} - - for (let i = 0; i < headers.length; i += 2) { - const key = headerNameToString(headers[i]) - let val = obj[key] +function consumeEnd (consume, encoding) { + const { type, body, resolve, stream, length } = consume - if (val) { - if (typeof val === 'string') { - val = [val] - obj[key] = val - } - val.push(headers[i + 1].toString('utf8')) - } else { - const headersValue = headers[i + 1] - if (typeof headersValue === 'string') { - obj[key] = headersValue - } else { - obj[key] = Array.isArray(headersValue) ? headersValue.map(x => x.toString('utf8')) : headersValue.toString('utf8') - } + try { + if (type === 'text') { + resolve(chunksDecode(body, length, encoding)) + } else if (type === 'json') { + resolve(JSON.parse(chunksDecode(body, length, encoding))) + } else if (type === 'arrayBuffer') { + resolve(chunksConcat(body, length).buffer) + } else if (type === 'blob') { + resolve(new Blob(body, { type: stream[kContentType] })) + } else if (type === 'bytes') { + resolve(chunksConcat(body, length)) } - } - // See https://github.com/nodejs/node/pull/46528 - if ('content-length' in obj && 'content-disposition' in obj) { - obj['content-disposition'] = Buffer.from(obj['content-disposition']).toString('latin1') + consumeFinish(consume) + } catch (err) { + stream.destroy(err) } - - return obj } /** - * @param {Buffer[]} headers - * @returns {string[]} + * @param {Consume} consume + * @param {Buffer} chunk + * @returns {void} */ -function parseRawHeaders (headers) { - const headersLength = headers.length - /** - * @type {string[]} - */ - const ret = new Array(headersLength) - - let hasContentLength = false - let contentDispositionIdx = -1 - let key - let val - let kLen = 0 - - for (let n = 0; n < headersLength; n += 2) { - key = headers[n] - val = headers[n + 1] - - typeof key !== 'string' && (key = key.toString()) - typeof val !== 'string' && (val = val.toString('utf8')) +function consumePush (consume, chunk) { + consume.length += chunk.length + consume.body.push(chunk) +} - kLen = key.length - if (kLen === 14 && key[7] === '-' && (key === 'content-length' || key.toLowerCase() === 'content-length')) { - hasContentLength = true - } else if (kLen === 19 && key[7] === '-' && (key === 'content-disposition' || key.toLowerCase() === 'content-disposition')) { - contentDispositionIdx = n + 1 - } - ret[n] = key - ret[n + 1] = val +/** + * @param {Consume} consume + * @param {Error} [err] + * @returns {void} + */ +function consumeFinish (consume, err) { + if (consume.body === null) { + return } - // See https://github.com/nodejs/node/pull/46528 - if (hasContentLength && contentDispositionIdx !== -1) { - ret[contentDispositionIdx] = Buffer.from(ret[contentDispositionIdx]).toString('latin1') + if (err) { + consume.reject(err) + } else { + consume.resolve() } - return ret + // Reset the consume object to allow for garbage collection. + consume.type = null + consume.stream = null + consume.resolve = null + consume.reject = null + consume.length = 0 + consume.body = null } -/** - * @param {string[]} headers - * @param {Buffer[]} headers - */ -function encodeRawHeaders (headers) { - if (!Array.isArray(headers)) { - throw new TypeError('expected headers to be an array') - } - return headers.map(x => Buffer.from(x)) +module.exports = { + Readable: BodyReadable, + chunksDecode } + +/***/ }), + +/***/ 2947: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + + + +const { Writable } = __nccwpck_require__(7075) +const { EventEmitter } = __nccwpck_require__(8474) +const { assertCacheKey, assertCacheValue } = __nccwpck_require__(4649) + /** - * @param {*} buffer - * @returns {buffer is Buffer} + * @typedef {import('../../types/cache-interceptor.d.ts').default.CacheKey} CacheKey + * @typedef {import('../../types/cache-interceptor.d.ts').default.CacheValue} CacheValue + * @typedef {import('../../types/cache-interceptor.d.ts').default.CacheStore} CacheStore + * @typedef {import('../../types/cache-interceptor.d.ts').default.GetResult} GetResult */ -function isBuffer (buffer) { - // See, https://github.com/mcollina/undici/pull/319 - return buffer instanceof Uint8Array || Buffer.isBuffer(buffer) -} /** - * Asserts that the handler object is a request handler. - * - * @param {object} handler - * @param {string} method - * @param {string} [upgrade] - * @returns {asserts handler is import('../api/api-request').RequestHandler} + * @implements {CacheStore} + * @extends {EventEmitter} */ -function assertRequestHandler (handler, method, upgrade) { - if (!handler || typeof handler !== 'object') { - throw new InvalidArgumentError('handler must be an object') - } +class MemoryCacheStore extends EventEmitter { + #maxCount = 1024 + #maxSize = 104857600 // 100MB + #maxEntrySize = 5242880 // 5MB - if (typeof handler.onRequestStart === 'function') { - // TODO (fix): More checks... - return - } + #size = 0 + #count = 0 + #entries = new Map() + #hasEmittedMaxSizeEvent = false - if (typeof handler.onConnect !== 'function') { - throw new InvalidArgumentError('invalid onConnect method') + /** + * @param {import('../../types/cache-interceptor.d.ts').default.MemoryCacheStoreOpts | undefined} [opts] + */ + constructor (opts) { + super() + if (opts) { + if (typeof opts !== 'object') { + throw new TypeError('MemoryCacheStore options must be an object') + } + + if (opts.maxCount !== undefined) { + if ( + typeof opts.maxCount !== 'number' || + !Number.isInteger(opts.maxCount) || + opts.maxCount < 0 + ) { + throw new TypeError('MemoryCacheStore options.maxCount must be a non-negative integer') + } + this.#maxCount = opts.maxCount + } + + if (opts.maxSize !== undefined) { + if ( + typeof opts.maxSize !== 'number' || + !Number.isInteger(opts.maxSize) || + opts.maxSize < 0 + ) { + throw new TypeError('MemoryCacheStore options.maxSize must be a non-negative integer') + } + this.#maxSize = opts.maxSize + } + + if (opts.maxEntrySize !== undefined) { + if ( + typeof opts.maxEntrySize !== 'number' || + !Number.isInteger(opts.maxEntrySize) || + opts.maxEntrySize < 0 + ) { + throw new TypeError('MemoryCacheStore options.maxEntrySize must be a non-negative integer') + } + this.#maxEntrySize = opts.maxEntrySize + } + } } - if (typeof handler.onError !== 'function') { - throw new InvalidArgumentError('invalid onError method') + /** + * Get the current size of the cache in bytes + * @returns {number} The current size of the cache in bytes + */ + get size () { + return this.#size } - if (typeof handler.onBodySent !== 'function' && handler.onBodySent !== undefined) { - throw new InvalidArgumentError('invalid onBodySent method') + /** + * Check if the cache is full (either max size or max count reached) + * @returns {boolean} True if the cache is full, false otherwise + */ + isFull () { + return this.#size >= this.#maxSize || this.#count >= this.#maxCount } - if (upgrade || method === 'CONNECT') { - if (typeof handler.onUpgrade !== 'function') { - throw new InvalidArgumentError('invalid onUpgrade method') - } - } else { - if (typeof handler.onHeaders !== 'function') { - throw new InvalidArgumentError('invalid onHeaders method') - } + /** + * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} req + * @returns {import('../../types/cache-interceptor.d.ts').default.GetResult | undefined} + */ + get (key) { + assertCacheKey(key) - if (typeof handler.onData !== 'function') { - throw new InvalidArgumentError('invalid onData method') - } + const topLevelKey = `${key.origin}:${key.path}` - if (typeof handler.onComplete !== 'function') { - throw new InvalidArgumentError('invalid onComplete method') - } + const now = Date.now() + const entries = this.#entries.get(topLevelKey) + + const entry = entries ? findEntry(key, entries, now) : null + + return entry == null + ? undefined + : { + statusMessage: entry.statusMessage, + statusCode: entry.statusCode, + headers: entry.headers, + body: entry.body, + vary: entry.vary ? entry.vary : undefined, + etag: entry.etag, + cacheControlDirectives: entry.cacheControlDirectives, + cachedAt: entry.cachedAt, + staleAt: entry.staleAt, + deleteAt: entry.deleteAt + } } -} -/** - * A body is disturbed if it has been read from and it cannot be re-used without - * losing state or data. - * @param {import('node:stream').Readable} body - * @returns {boolean} - */ -function isDisturbed (body) { - // TODO (fix): Why is body[kBodyUsed] needed? - return !!(body && (stream.isDisturbed(body) || body[kBodyUsed])) -} + /** + * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} key + * @param {import('../../types/cache-interceptor.d.ts').default.CacheValue} val + * @returns {Writable | undefined} + */ + createWriteStream (key, val) { + assertCacheKey(key) + assertCacheValue(val) -/** - * @typedef {object} SocketInfo - * @property {string} [localAddress] - * @property {number} [localPort] - * @property {string} [remoteAddress] - * @property {number} [remotePort] - * @property {string} [remoteFamily] - * @property {number} [timeout] - * @property {number} bytesWritten - * @property {number} bytesRead - */ + const topLevelKey = `${key.origin}:${key.path}` -/** - * @param {import('net').Socket} socket - * @returns {SocketInfo} - */ -function getSocketInfo (socket) { - return { - localAddress: socket.localAddress, - localPort: socket.localPort, - remoteAddress: socket.remoteAddress, - remotePort: socket.remotePort, - remoteFamily: socket.remoteFamily, - timeout: socket.timeout, - bytesWritten: socket.bytesWritten, - bytesRead: socket.bytesRead - } -} + const store = this + const entry = { ...key, ...val, body: [], size: 0 } -/** - * @param {Iterable} iterable - * @returns {ReadableStream} - */ -function ReadableStreamFrom (iterable) { - // We cannot use ReadableStream.from here because it does not return a byte stream. + return new Writable({ + write (chunk, encoding, callback) { + if (typeof chunk === 'string') { + chunk = Buffer.from(chunk, encoding) + } - let iterator - return new ReadableStream( - { - start () { - iterator = iterable[Symbol.asyncIterator]() + entry.size += chunk.byteLength + + if (entry.size >= store.#maxEntrySize) { + this.destroy() + } else { + entry.body.push(chunk) + } + + callback(null) }, - pull (controller) { - return iterator.next().then(({ done, value }) => { - if (done) { - return queueMicrotask(() => { - controller.close() - controller.byobRequest?.respond(0) + final (callback) { + let entries = store.#entries.get(topLevelKey) + if (!entries) { + entries = [] + store.#entries.set(topLevelKey, entries) + } + const previousEntry = findEntry(key, entries, Date.now()) + if (previousEntry) { + const index = entries.indexOf(previousEntry) + entries.splice(index, 1, entry) + store.#size -= previousEntry.size + } else { + entries.push(entry) + store.#count += 1 + } + + store.#size += entry.size + + // Check if cache is full and emit event if needed + if (store.#size > store.#maxSize || store.#count > store.#maxCount) { + // Emit maxSizeExceeded event if we haven't already + if (!store.#hasEmittedMaxSizeEvent) { + store.emit('maxSizeExceeded', { + size: store.#size, + maxSize: store.#maxSize, + count: store.#count, + maxCount: store.#maxCount }) - } else { - const buf = Buffer.isBuffer(value) ? value : Buffer.from(value) - if (buf.byteLength) { - return controller.enqueue(new Uint8Array(buf)) - } else { - return this.pull(controller) + store.#hasEmittedMaxSizeEvent = true + } + + // Perform eviction + for (const [key, entries] of store.#entries) { + for (const entry of entries.splice(0, entries.length / 2)) { + store.#size -= entry.size + store.#count -= 1 + } + if (entries.length === 0) { + store.#entries.delete(key) } } - }) - }, - cancel () { - return iterator.return() - }, - type: 'bytes' + + // Reset the event flag after eviction + if (store.#size < store.#maxSize && store.#count < store.#maxCount) { + store.#hasEmittedMaxSizeEvent = false + } + } + + callback(null) + } + }) + } + + /** + * @param {CacheKey} key + */ + delete (key) { + if (typeof key !== 'object') { + throw new TypeError(`expected key to be object, got ${typeof key}`) } - ) -} -/** - * The object should be a FormData instance and contains all the required - * methods. - * @param {*} object - * @returns {object is FormData} - */ -function isFormDataLike (object) { - return ( - object && - typeof object === 'object' && - typeof object.append === 'function' && - typeof object.delete === 'function' && - typeof object.get === 'function' && - typeof object.getAll === 'function' && - typeof object.has === 'function' && - typeof object.set === 'function' && - object[Symbol.toStringTag] === 'FormData' - ) -} + const topLevelKey = `${key.origin}:${key.path}` -function addAbortListener (signal, listener) { - if ('addEventListener' in signal) { - signal.addEventListener('abort', listener, { once: true }) - return () => signal.removeEventListener('abort', listener) + for (const entry of this.#entries.get(topLevelKey) ?? []) { + this.#size -= entry.size + this.#count -= 1 + } + this.#entries.delete(topLevelKey) } - signal.once('abort', listener) - return () => signal.removeListener('abort', listener) } -const validTokenChars = new Uint8Array([ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0-15 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31 - 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, // 32-47 (!"#$%&'()*+,-./) - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48-63 (0-9:;<=>?) - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64-79 (@A-O) - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, // 80-95 (P-Z[\]^_) - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96-111 (`a-o) - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, // 112-127 (p-z{|}~) - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 128-143 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 144-159 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 160-175 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 176-191 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 192-207 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 208-223 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 224-239 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 240-255 -]) +function findEntry (key, entries, now) { + return entries.find((entry) => ( + entry.deleteAt > now && + entry.method === key.method && + (entry.vary == null || Object.keys(entry.vary).every(headerName => { + if (entry.vary[headerName] === null) { + return key.headers[headerName] === undefined + } -/** - * @see https://tools.ietf.org/html/rfc7230#section-3.2.6 - * @param {number} c - * @returns {boolean} - */ -function isTokenCharCode (c) { - return (validTokenChars[c] === 1) + return entry.vary[headerName] === key.headers[headerName] + })) + )) } -const tokenRegExp = /^[\^_`a-zA-Z\-0-9!#$%&'*+.|~]+$/ +module.exports = MemoryCacheStore -/** - * @param {string} characters - * @returns {boolean} - */ -function isValidHTTPToken (characters) { - if (characters.length >= 12) return tokenRegExp.test(characters) - if (characters.length === 0) return false - for (let i = 0; i < characters.length; i++) { - if (validTokenChars[characters.charCodeAt(i)] !== 1) { - return false - } - } - return true -} +/***/ }), -// headerCharRegex have been lifted from -// https://github.com/nodejs/node/blob/main/lib/_http_common.js +/***/ 9707: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -/** - * Matches if val contains an invalid field-vchar - * field-value = *( field-content / obs-fold ) - * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ] - * field-vchar = VCHAR / obs-text - */ -const headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/ -/** - * @param {string} characters - * @returns {boolean} - */ -function isValidHeaderValue (characters) { - return !headerCharRegex.test(characters) -} -const rangeHeaderRegex = /^bytes (\d+)-(\d+)\/(\d+)?$/ +const { Writable } = __nccwpck_require__(7075) +const { assertCacheKey, assertCacheValue } = __nccwpck_require__(4649) -/** - * @typedef {object} RangeHeader - * @property {number} start - * @property {number | null} end - * @property {number | null} size - */ +let DatabaseSync -/** - * Parse accordingly to RFC 9110 - * @see https://www.rfc-editor.org/rfc/rfc9110#field.content-range - * @param {string} [range] - * @returns {RangeHeader|null} - */ -function parseRangeHeader (range) { - if (range == null || range === '') return { start: 0, end: null, size: null } +const VERSION = 3 - const m = range ? range.match(rangeHeaderRegex) : null - return m - ? { - start: parseInt(m[1]), - end: m[2] ? parseInt(m[2]) : null, - size: m[3] ? parseInt(m[3]) : null - } - : null -} +// 2gb +const MAX_ENTRY_SIZE = 2 * 1000 * 1000 * 1000 /** - * @template {import("events").EventEmitter} T - * @param {T} obj - * @param {string} name - * @param {(...args: any[]) => void} listener - * @returns {T} + * @typedef {import('../../types/cache-interceptor.d.ts').default.CacheStore} CacheStore + * @implements {CacheStore} + * + * @typedef {{ + * id: Readonly, + * body?: Uint8Array + * statusCode: number + * statusMessage: string + * headers?: string + * vary?: string + * etag?: string + * cacheControlDirectives?: string + * cachedAt: number + * staleAt: number + * deleteAt: number + * }} SqliteStoreValue */ -function addListener (obj, name, listener) { - const listeners = (obj[kListeners] ??= []) - listeners.push([name, listener]) - obj.on(name, listener) - return obj -} +module.exports = class SqliteCacheStore { + #maxEntrySize = MAX_ENTRY_SIZE + #maxCount = Infinity -/** - * @template {import("events").EventEmitter} T - * @param {T} obj - * @returns {T} - */ -function removeAllListeners (obj) { - if (obj[kListeners] != null) { - for (const [name, listener] of obj[kListeners]) { - obj.removeListener(name, listener) - } - obj[kListeners] = null - } - return obj -} + /** + * @type {import('node:sqlite').DatabaseSync} + */ + #db -/** - * @param {import ('../dispatcher/client')} client - * @param {import ('../core/request')} request - * @param {Error} err - */ -function errorRequest (client, request, err) { - try { - request.onError(err) - assert(request.aborted) - } catch (err) { - client.emit('error', err) - } -} + /** + * @type {import('node:sqlite').StatementSync} + */ + #getValuesQuery -/** - * @param {WeakRef} socketWeakRef - * @param {object} opts - * @param {number} opts.timeout - * @param {string} opts.hostname - * @param {number} opts.port - * @returns {() => void} - */ -const setupConnectTimeout = process.platform === 'win32' - ? (socketWeakRef, opts) => { - if (!opts.timeout) { - return noop - } + /** + * @type {import('node:sqlite').StatementSync} + */ + #updateValueQuery - let s1 = null - let s2 = null - const fastTimer = timers.setFastTimeout(() => { - // setImmediate is added to make sure that we prioritize socket error events over timeouts - s1 = setImmediate(() => { - // Windows needs an extra setImmediate probably due to implementation differences in the socket logic - s2 = setImmediate(() => onConnectTimeout(socketWeakRef.deref(), opts)) - }) - }, opts.timeout) - return () => { - timers.clearFastTimeout(fastTimer) - clearImmediate(s1) - clearImmediate(s2) - } - } - : (socketWeakRef, opts) => { - if (!opts.timeout) { - return noop - } + /** + * @type {import('node:sqlite').StatementSync} + */ + #insertValueQuery - let s1 = null - const fastTimer = timers.setFastTimeout(() => { - // setImmediate is added to make sure that we prioritize socket error events over timeouts - s1 = setImmediate(() => { - onConnectTimeout(socketWeakRef.deref(), opts) - }) - }, opts.timeout) - return () => { - timers.clearFastTimeout(fastTimer) - clearImmediate(s1) - } - } + /** + * @type {import('node:sqlite').StatementSync} + */ + #deleteExpiredValuesQuery -/** - * @param {net.Socket} socket - * @param {object} opts - * @param {number} opts.timeout - * @param {string} opts.hostname - * @param {number} opts.port - */ -function onConnectTimeout (socket, opts) { - // The socket could be already garbage collected - if (socket == null) { - return - } + /** + * @type {import('node:sqlite').StatementSync} + */ + #deleteByUrlQuery - let message = 'Connect Timeout Error' - if (Array.isArray(socket.autoSelectFamilyAttemptedAddresses)) { - message += ` (attempted addresses: ${socket.autoSelectFamilyAttemptedAddresses.join(', ')},` - } else { - message += ` (attempted address: ${opts.hostname}:${opts.port},` - } + /** + * @type {import('node:sqlite').StatementSync} + */ + #countEntriesQuery - message += ` timeout: ${opts.timeout}ms)` + /** + * @type {import('node:sqlite').StatementSync | null} + */ + #deleteOldValuesQuery - destroy(socket, new ConnectTimeoutError(message)) -} + /** + * @param {import('../../types/cache-interceptor.d.ts').default.SqliteCacheStoreOpts | undefined} opts + */ + constructor (opts) { + if (opts) { + if (typeof opts !== 'object') { + throw new TypeError('SqliteCacheStore options must be an object') + } -/** - * @param {string} urlString - * @returns {string} - */ -function getProtocolFromUrlString (urlString) { - if ( - urlString[0] === 'h' && - urlString[1] === 't' && - urlString[2] === 't' && - urlString[3] === 'p' - ) { - switch (urlString[4]) { - case ':': - return 'http:' - case 's': - if (urlString[5] === ':') { - return 'https:' + if (opts.maxEntrySize !== undefined) { + if ( + typeof opts.maxEntrySize !== 'number' || + !Number.isInteger(opts.maxEntrySize) || + opts.maxEntrySize < 0 + ) { + throw new TypeError('SqliteCacheStore options.maxEntrySize must be a non-negative integer') } - } - } - // fallback if none of the usual suspects - return urlString.slice(0, urlString.indexOf(':') + 1) -} - -const kEnumerableProperty = Object.create(null) -kEnumerableProperty.enumerable = true - -const normalizedMethodRecordsBase = { - delete: 'DELETE', - DELETE: 'DELETE', - get: 'GET', - GET: 'GET', - head: 'HEAD', - HEAD: 'HEAD', - options: 'OPTIONS', - OPTIONS: 'OPTIONS', - post: 'POST', - POST: 'POST', - put: 'PUT', - PUT: 'PUT' -} - -const normalizedMethodRecords = { - ...normalizedMethodRecordsBase, - patch: 'patch', - PATCH: 'PATCH' -} - -// Note: object prototypes should not be able to be referenced. e.g. `Object#hasOwnProperty`. -Object.setPrototypeOf(normalizedMethodRecordsBase, null) -Object.setPrototypeOf(normalizedMethodRecords, null) - -module.exports = { - kEnumerableProperty, - isDisturbed, - isBlobLike, - parseOrigin, - parseURL, - getServerName, - isStream, - isIterable, - isAsyncIterable, - isDestroyed, - headerNameToString, - bufferToLowerCasedHeaderName, - addListener, - removeAllListeners, - errorRequest, - parseRawHeaders, - encodeRawHeaders, - parseHeaders, - parseKeepAliveTimeout, - destroy, - bodyLength, - deepClone, - ReadableStreamFrom, - isBuffer, - assertRequestHandler, - getSocketInfo, - isFormDataLike, - pathHasQueryOrFragment, - serializePathWithQuery, - addAbortListener, - isValidHTTPToken, - isValidHeaderValue, - isTokenCharCode, - parseRangeHeader, - normalizedMethodRecordsBase, - normalizedMethodRecords, - isValidPort, - isHttpOrHttpsPrefixed, - nodeMajor, - nodeMinor, - safeHTTPMethods: Object.freeze(['GET', 'HEAD', 'OPTIONS', 'TRACE']), - wrapRequestBody, - setupConnectTimeout, - getProtocolFromUrlString -} + if (opts.maxEntrySize > MAX_ENTRY_SIZE) { + throw new TypeError('SqliteCacheStore options.maxEntrySize must be less than 2gb') + } -/***/ }), + this.#maxEntrySize = opts.maxEntrySize + } -/***/ 2004: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + if (opts.maxCount !== undefined) { + if ( + typeof opts.maxCount !== 'number' || + !Number.isInteger(opts.maxCount) || + opts.maxCount < 0 + ) { + throw new TypeError('SqliteCacheStore options.maxCount must be a non-negative integer') + } + this.#maxCount = opts.maxCount + } + } -"use strict"; + if (!DatabaseSync) { + DatabaseSync = (__nccwpck_require__(99).DatabaseSync) + } + this.#db = new DatabaseSync(opts?.location ?? ':memory:') + this.#db.exec(` + PRAGMA journal_mode = WAL; + PRAGMA synchronous = NORMAL; + PRAGMA temp_store = memory; + PRAGMA optimize; -const { InvalidArgumentError, MaxOriginsReachedError } = __nccwpck_require__(4928) -const { kClients, kRunning, kClose, kDestroy, kDispatch, kUrl } = __nccwpck_require__(9562) -const DispatcherBase = __nccwpck_require__(6612) -const Pool = __nccwpck_require__(8767) -const Client = __nccwpck_require__(226) -const util = __nccwpck_require__(983) + CREATE TABLE IF NOT EXISTS cacheInterceptorV${VERSION} ( + -- Data specific to us + id INTEGER PRIMARY KEY AUTOINCREMENT, + url TEXT NOT NULL, + method TEXT NOT NULL, -const kOnConnect = Symbol('onConnect') -const kOnDisconnect = Symbol('onDisconnect') -const kOnConnectionError = Symbol('onConnectionError') -const kOnDrain = Symbol('onDrain') -const kFactory = Symbol('factory') -const kOptions = Symbol('options') -const kOrigins = Symbol('origins') + -- Data returned to the interceptor + body BUF NULL, + deleteAt INTEGER NOT NULL, + statusCode INTEGER NOT NULL, + statusMessage TEXT NOT NULL, + headers TEXT NULL, + cacheControlDirectives TEXT NULL, + etag TEXT NULL, + vary TEXT NULL, + cachedAt INTEGER NOT NULL, + staleAt INTEGER NOT NULL + ); -function defaultFactory (origin, opts) { - return opts && opts.connections === 1 - ? new Client(origin, opts) - : new Pool(origin, opts) -} + CREATE INDEX IF NOT EXISTS idx_cacheInterceptorV${VERSION}_getValuesQuery ON cacheInterceptorV${VERSION}(url, method, deleteAt); + CREATE INDEX IF NOT EXISTS idx_cacheInterceptorV${VERSION}_deleteByUrlQuery ON cacheInterceptorV${VERSION}(deleteAt); + `) -class Agent extends DispatcherBase { - constructor ({ factory = defaultFactory, maxOrigins = Infinity, connect, ...options } = {}) { - if (typeof factory !== 'function') { - throw new InvalidArgumentError('factory must be a function.') - } + this.#getValuesQuery = this.#db.prepare(` + SELECT + id, + body, + deleteAt, + statusCode, + statusMessage, + headers, + etag, + cacheControlDirectives, + vary, + cachedAt, + staleAt + FROM cacheInterceptorV${VERSION} + WHERE + url = ? + AND method = ? + ORDER BY + deleteAt ASC + `) - if (connect != null && typeof connect !== 'function' && typeof connect !== 'object') { - throw new InvalidArgumentError('connect must be a function or an object') - } + this.#updateValueQuery = this.#db.prepare(` + UPDATE cacheInterceptorV${VERSION} SET + body = ?, + deleteAt = ?, + statusCode = ?, + statusMessage = ?, + headers = ?, + etag = ?, + cacheControlDirectives = ?, + cachedAt = ?, + staleAt = ? + WHERE + id = ? + `) - if (typeof maxOrigins !== 'number' || Number.isNaN(maxOrigins) || maxOrigins <= 0) { - throw new InvalidArgumentError('maxOrigins must be a number greater than 0') - } + this.#insertValueQuery = this.#db.prepare(` + INSERT INTO cacheInterceptorV${VERSION} ( + url, + method, + body, + deleteAt, + statusCode, + statusMessage, + headers, + etag, + cacheControlDirectives, + vary, + cachedAt, + staleAt + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + `) - super() + this.#deleteByUrlQuery = this.#db.prepare( + `DELETE FROM cacheInterceptorV${VERSION} WHERE url = ?` + ) - if (connect && typeof connect !== 'function') { - connect = { ...connect } - } + this.#countEntriesQuery = this.#db.prepare( + `SELECT COUNT(*) AS total FROM cacheInterceptorV${VERSION}` + ) - this[kOptions] = { ...util.deepClone(options), maxOrigins, connect } - this[kFactory] = factory - this[kClients] = new Map() - this[kOrigins] = new Set() + this.#deleteExpiredValuesQuery = this.#db.prepare( + `DELETE FROM cacheInterceptorV${VERSION} WHERE deleteAt <= ?` + ) - this[kOnDrain] = (origin, targets) => { - this.emit('drain', origin, [this, ...targets]) - } + this.#deleteOldValuesQuery = this.#maxCount === Infinity + ? null + : this.#db.prepare(` + DELETE FROM cacheInterceptorV${VERSION} + WHERE id IN ( + SELECT + id + FROM cacheInterceptorV${VERSION} + ORDER BY cachedAt DESC + LIMIT ? + ) + `) + } - this[kOnConnect] = (origin, targets) => { - this.emit('connect', origin, [this, ...targets]) - } + close () { + this.#db.close() + } - this[kOnDisconnect] = (origin, targets, err) => { - this.emit('disconnect', origin, [this, ...targets], err) - } + /** + * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} key + * @returns {(import('../../types/cache-interceptor.d.ts').default.GetResult & { body?: Buffer }) | undefined} + */ + get (key) { + assertCacheKey(key) - this[kOnConnectionError] = (origin, targets, err) => { - this.emit('connectionError', origin, [this, ...targets], err) - } + const value = this.#findValue(key) + return value + ? { + body: value.body ? Buffer.from(value.body.buffer, value.body.byteOffset, value.body.byteLength) : undefined, + statusCode: value.statusCode, + statusMessage: value.statusMessage, + headers: value.headers ? JSON.parse(value.headers) : undefined, + etag: value.etag ? value.etag : undefined, + vary: value.vary ? JSON.parse(value.vary) : undefined, + cacheControlDirectives: value.cacheControlDirectives + ? JSON.parse(value.cacheControlDirectives) + : undefined, + cachedAt: value.cachedAt, + staleAt: value.staleAt, + deleteAt: value.deleteAt + } + : undefined } - get [kRunning] () { - let ret = 0 - for (const { dispatcher } of this[kClients].values()) { - ret += dispatcher[kRunning] - } - return ret - } + /** + * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} key + * @param {import('../../types/cache-interceptor.d.ts').default.CacheValue & { body: null | Buffer | Array}} value + */ + set (key, value) { + assertCacheKey(key) - [kDispatch] (opts, handler) { - let key - if (opts.origin && (typeof opts.origin === 'string' || opts.origin instanceof URL)) { - key = String(opts.origin) - } else { - throw new InvalidArgumentError('opts.origin must be a non-empty string or URL.') - } + const url = this.#makeValueUrl(key) + const body = Array.isArray(value.body) ? Buffer.concat(value.body) : value.body + const size = body?.byteLength - if (this[kOrigins].size >= this[kOptions].maxOrigins && !this[kOrigins].has(key)) { - throw new MaxOriginsReachedError() + if (size && size > this.#maxEntrySize) { + return } - const result = this[kClients].get(key) - let dispatcher = result && result.dispatcher - if (!dispatcher) { - const closeClientIfUnused = (connected) => { - const result = this[kClients].get(key) - if (result) { - if (connected) result.count -= 1 - if (result.count <= 0) { - this[kClients].delete(key) - result.dispatcher.close() - } - this[kOrigins].delete(key) + const existingValue = this.#findValue(key, true) + if (existingValue) { + // Updating an existing response, let's overwrite it + this.#updateValueQuery.run( + body, + value.deleteAt, + value.statusCode, + value.statusMessage, + value.headers ? JSON.stringify(value.headers) : null, + value.etag ? value.etag : null, + value.cacheControlDirectives ? JSON.stringify(value.cacheControlDirectives) : null, + value.cachedAt, + value.staleAt, + existingValue.id + ) + } else { + this.#prune() + // New response, let's insert it + this.#insertValueQuery.run( + url, + key.method, + body, + value.deleteAt, + value.statusCode, + value.statusMessage, + value.headers ? JSON.stringify(value.headers) : null, + value.etag ? value.etag : null, + value.cacheControlDirectives ? JSON.stringify(value.cacheControlDirectives) : null, + value.vary ? JSON.stringify(value.vary) : null, + value.cachedAt, + value.staleAt + ) + } + } + + /** + * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} key + * @param {import('../../types/cache-interceptor.d.ts').default.CacheValue} value + * @returns {Writable | undefined} + */ + createWriteStream (key, value) { + assertCacheKey(key) + assertCacheValue(value) + + let size = 0 + /** + * @type {Buffer[] | null} + */ + const body = [] + const store = this + + return new Writable({ + decodeStrings: true, + write (chunk, encoding, callback) { + size += chunk.byteLength + + if (size < store.#maxEntrySize) { + body.push(chunk) + } else { + this.destroy() } + + callback() + }, + final (callback) { + store.set(key, { ...value, body }) + callback() } - dispatcher = this[kFactory](opts.origin, this[kOptions]) - .on('drain', this[kOnDrain]) - .on('connect', (origin, targets) => { - const result = this[kClients].get(key) - if (result) { - result.count += 1 - } - this[kOnConnect](origin, targets) - }) - .on('disconnect', (origin, targets, err) => { - closeClientIfUnused(true) - this[kOnDisconnect](origin, targets, err) - }) - .on('connectionError', (origin, targets, err) => { - closeClientIfUnused(false) - this[kOnConnectionError](origin, targets, err) - }) + }) + } - this[kClients].set(key, { count: 0, dispatcher }) - this[kOrigins].add(key) + /** + * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} key + */ + delete (key) { + if (typeof key !== 'object') { + throw new TypeError(`expected key to be object, got ${typeof key}`) } - return dispatcher.dispatch(opts, handler) + this.#deleteByUrlQuery.run(this.#makeValueUrl(key)) } - [kClose] () { - const closePromises = [] - for (const { dispatcher } of this[kClients].values()) { - closePromises.push(dispatcher.close()) + #prune () { + if (Number.isFinite(this.#maxCount) && this.size <= this.#maxCount) { + return 0 } - this[kClients].clear() - return Promise.all(closePromises) - } + { + const removed = this.#deleteExpiredValuesQuery.run(Date.now()).changes + if (removed) { + return removed + } + } - [kDestroy] (err) { - const destroyPromises = [] - for (const { dispatcher } of this[kClients].values()) { - destroyPromises.push(dispatcher.destroy(err)) + { + const removed = this.#deleteOldValuesQuery?.run(Math.max(Math.floor(this.#maxCount * 0.1), 1)).changes + if (removed) { + return removed + } } - this[kClients].clear() - return Promise.all(destroyPromises) + return 0 } - get stats () { - const allClientStats = {} - for (const { dispatcher } of this[kClients].values()) { - if (dispatcher.stats) { - allClientStats[dispatcher[kUrl].origin] = dispatcher.stats - } - } - return allClientStats + /** + * Counts the number of rows in the cache + * @returns {Number} + */ + get size () { + const { total } = this.#countEntriesQuery.get() + return total } -} -module.exports = Agent + /** + * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} key + * @returns {string} + */ + #makeValueUrl (key) { + return `${key.origin}/${key.path}` + } + /** + * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} key + * @param {boolean} [canBeExpired=false] + * @returns {SqliteStoreValue | undefined} + */ + #findValue (key, canBeExpired = false) { + const url = this.#makeValueUrl(key) + const { headers, method } = key -/***/ }), + /** + * @type {SqliteStoreValue[]} + */ + const values = this.#getValuesQuery.all(url, method) -/***/ 7604: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + if (values.length === 0) { + return undefined + } -"use strict"; + const now = Date.now() + for (const value of values) { + if (now >= value.deleteAt && !canBeExpired) { + return undefined + } + let matches = true -const { - BalancedPoolMissingUpstreamError, - InvalidArgumentError -} = __nccwpck_require__(4928) -const { - PoolBase, - kClients, - kNeedDrain, - kAddClient, - kRemoveClient, - kGetDispatcher -} = __nccwpck_require__(6469) -const Pool = __nccwpck_require__(8767) -const { kUrl } = __nccwpck_require__(9562) -const { parseOrigin } = __nccwpck_require__(983) -const kFactory = Symbol('factory') + if (value.vary) { + const vary = JSON.parse(value.vary) -const kOptions = Symbol('options') -const kGreatestCommonDivisor = Symbol('kGreatestCommonDivisor') -const kCurrentWeight = Symbol('kCurrentWeight') -const kIndex = Symbol('kIndex') -const kWeight = Symbol('kWeight') -const kMaxWeightPerServer = Symbol('kMaxWeightPerServer') -const kErrorPenalty = Symbol('kErrorPenalty') + for (const header in vary) { + if (!headerValueEquals(headers[header], vary[header])) { + matches = false + break + } + } + } -/** - * Calculate the greatest common divisor of two numbers by - * using the Euclidean algorithm. - * - * @param {number} a - * @param {number} b - * @returns {number} - */ -function getGreatestCommonDivisor (a, b) { - if (a === 0) return b + if (matches) { + return value + } + } - while (b !== 0) { - const t = b - b = a % b - a = t + return undefined } - return a } -function defaultFactory (origin, opts) { - return new Pool(origin, opts) -} +/** + * @param {string|string[]|null|undefined} lhs + * @param {string|string[]|null|undefined} rhs + * @returns {boolean} + */ +function headerValueEquals (lhs, rhs) { + if (lhs == null && rhs == null) { + return true + } -class BalancedPool extends PoolBase { - constructor (upstreams = [], { factory = defaultFactory, ...opts } = {}) { - if (typeof factory !== 'function') { - throw new InvalidArgumentError('factory must be a function.') + if ((lhs == null && rhs != null) || + (lhs != null && rhs == null)) { + return false + } + + if (Array.isArray(lhs) && Array.isArray(rhs)) { + if (lhs.length !== rhs.length) { + return false } - super() + return lhs.every((x, i) => x === rhs[i]) + } - this[kOptions] = opts - this[kIndex] = -1 - this[kCurrentWeight] = 0 + return lhs === rhs +} - this[kMaxWeightPerServer] = this[kOptions].maxWeightPerServer || 100 - this[kErrorPenalty] = this[kOptions].errorPenalty || 15 - if (!Array.isArray(upstreams)) { - upstreams = [upstreams] - } +/***/ }), - this[kFactory] = factory +/***/ 1430: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - for (const upstream of upstreams) { - this.addUpstream(upstream) - } - this._updateBalancedPoolStats() - } - addUpstream (upstream) { - const upstreamOrigin = parseOrigin(upstream).origin - if (this[kClients].find((pool) => ( - pool[kUrl].origin === upstreamOrigin && - pool.closed !== true && - pool.destroyed !== true - ))) { - return this - } - const pool = this[kFactory](upstreamOrigin, Object.assign({}, this[kOptions])) +const net = __nccwpck_require__(7030) +const assert = __nccwpck_require__(4589) +const util = __nccwpck_require__(2550) +const { InvalidArgumentError } = __nccwpck_require__(5093) - this[kAddClient](pool) - pool.on('connect', () => { - pool[kWeight] = Math.min(this[kMaxWeightPerServer], pool[kWeight] + this[kErrorPenalty]) - }) +let tls // include tls conditionally since it is not always available - pool.on('connectionError', () => { - pool[kWeight] = Math.max(1, pool[kWeight] - this[kErrorPenalty]) - this._updateBalancedPoolStats() - }) +// TODO: session re-use does not wait for the first +// connection to resolve the session and might therefore +// resolve the same servername multiple times even when +// re-use is enabled. - pool.on('disconnect', (...args) => { - const err = args[2] - if (err && err.code === 'UND_ERR_SOCKET') { - // decrease the weight of the pool. - pool[kWeight] = Math.max(1, pool[kWeight] - this[kErrorPenalty]) - this._updateBalancedPoolStats() +const SessionCache = class WeakSessionCache { + constructor (maxCachedSessions) { + this._maxCachedSessions = maxCachedSessions + this._sessionCache = new Map() + this._sessionRegistry = new FinalizationRegistry((key) => { + if (this._sessionCache.size < this._maxCachedSessions) { + return } - }) - - for (const client of this[kClients]) { - client[kWeight] = this[kMaxWeightPerServer] - } - this._updateBalancedPoolStats() + const ref = this._sessionCache.get(key) + if (ref !== undefined && ref.deref() === undefined) { + this._sessionCache.delete(key) + } + }) + } - return this + get (sessionKey) { + const ref = this._sessionCache.get(sessionKey) + return ref ? ref.deref() : null } - _updateBalancedPoolStats () { - let result = 0 - for (let i = 0; i < this[kClients].length; i++) { - result = getGreatestCommonDivisor(this[kClients][i][kWeight], result) + set (sessionKey, session) { + if (this._maxCachedSessions === 0) { + return } - this[kGreatestCommonDivisor] = result + this._sessionCache.set(sessionKey, new WeakRef(session)) + this._sessionRegistry.register(session, sessionKey) } +} - removeUpstream (upstream) { - const upstreamOrigin = parseOrigin(upstream).origin - - const pool = this[kClients].find((pool) => ( - pool[kUrl].origin === upstreamOrigin && - pool.closed !== true && - pool.destroyed !== true - )) - - if (pool) { - this[kRemoveClient](pool) - } - - return this +function buildConnector ({ allowH2, useH2c, maxCachedSessions, socketPath, timeout, session: customSession, ...opts }) { + if (maxCachedSessions != null && (!Number.isInteger(maxCachedSessions) || maxCachedSessions < 0)) { + throw new InvalidArgumentError('maxCachedSessions must be a positive integer or zero') } - getUpstream (upstream) { - const upstreamOrigin = parseOrigin(upstream).origin + const options = { path: socketPath, ...opts } + const sessionCache = new SessionCache(maxCachedSessions == null ? 100 : maxCachedSessions) + timeout = timeout == null ? 10e3 : timeout + allowH2 = allowH2 != null ? allowH2 : false + return function connect ({ hostname, host, protocol, port, servername, localAddress, httpSocket }, callback) { + let socket + if (protocol === 'https:') { + if (!tls) { + tls = __nccwpck_require__(1692) + } + servername = servername || options.servername || util.getServerName(host) || null - return this[kClients].find((pool) => ( - pool[kUrl].origin === upstreamOrigin && - pool.closed !== true && - pool.destroyed !== true - )) - } + const sessionKey = servername || hostname + assert(sessionKey) - get upstreams () { - return this[kClients] - .filter(dispatcher => dispatcher.closed !== true && dispatcher.destroyed !== true) - .map((p) => p[kUrl].origin) - } + const session = customSession || sessionCache.get(sessionKey) || null - [kGetDispatcher] () { - // We validate that pools is greater than 0, - // otherwise we would have to wait until an upstream - // is added, which might never happen. - if (this[kClients].length === 0) { - throw new BalancedPoolMissingUpstreamError() - } + port = port || 443 - const dispatcher = this[kClients].find(dispatcher => ( - !dispatcher[kNeedDrain] && - dispatcher.closed !== true && - dispatcher.destroyed !== true - )) + socket = tls.connect({ + highWaterMark: 16384, // TLS in node can't have bigger HWM anyway... + ...options, + servername, + session, + localAddress, + ALPNProtocols: allowH2 ? ['http/1.1', 'h2'] : ['http/1.1'], + socket: httpSocket, // upgrade socket connection + port, + host: hostname + }) - if (!dispatcher) { - return - } + socket + .on('session', function (session) { + // TODO (fix): Can a session become invalid once established? Don't think so? + sessionCache.set(sessionKey, session) + }) + } else { + assert(!httpSocket, 'httpSocket can only be sent on TLS update') - const allClientsBusy = this[kClients].map(pool => pool[kNeedDrain]).reduce((a, b) => a && b, true) + port = port || 80 - if (allClientsBusy) { - return + socket = net.connect({ + highWaterMark: 64 * 1024, // Same as nodejs fs streams. + ...options, + localAddress, + port, + host: hostname + }) + if (useH2c === true) { + socket.alpnProtocol = 'h2' + } } - let counter = 0 - - let maxWeightIndex = this[kClients].findIndex(pool => !pool[kNeedDrain]) + // Set TCP keep alive options on the socket here instead of in connect() for the case of assigning the socket + if (options.keepAlive == null || options.keepAlive) { + const keepAliveInitialDelay = options.keepAliveInitialDelay === undefined ? 60e3 : options.keepAliveInitialDelay + socket.setKeepAlive(true, keepAliveInitialDelay) + } - while (counter++ < this[kClients].length) { - this[kIndex] = (this[kIndex] + 1) % this[kClients].length - const pool = this[kClients][this[kIndex]] + const clearConnectTimeout = util.setupConnectTimeout(new WeakRef(socket), { timeout, hostname, port }) - // find pool index with the largest weight - if (pool[kWeight] > this[kClients][maxWeightIndex][kWeight] && !pool[kNeedDrain]) { - maxWeightIndex = this[kIndex] - } + socket + .setNoDelay(true) + .once(protocol === 'https:' ? 'secureConnect' : 'connect', function () { + queueMicrotask(clearConnectTimeout) - // decrease the current weight every `this[kClients].length`. - if (this[kIndex] === 0) { - // Set the current weight to the next lower weight. - this[kCurrentWeight] = this[kCurrentWeight] - this[kGreatestCommonDivisor] + if (callback) { + const cb = callback + callback = null + cb(null, this) + } + }) + .on('error', function (err) { + queueMicrotask(clearConnectTimeout) - if (this[kCurrentWeight] <= 0) { - this[kCurrentWeight] = this[kMaxWeightPerServer] + if (callback) { + const cb = callback + callback = null + cb(err) } - } - if (pool[kWeight] >= this[kCurrentWeight] && (!pool[kNeedDrain])) { - return pool - } - } + }) - this[kCurrentWeight] = this[kClients][maxWeightIndex][kWeight] - this[kIndex] = maxWeightIndex - return this[kClients][maxWeightIndex] + return socket } } -module.exports = BalancedPool +module.exports = buildConnector /***/ }), -/***/ 1300: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -"use strict"; +/***/ 5337: +/***/ ((module) => { -/* global WebAssembly */ -const assert = __nccwpck_require__(4589) -const util = __nccwpck_require__(983) -const { channels } = __nccwpck_require__(6591) -const timers = __nccwpck_require__(7280) -const { - RequestContentLengthMismatchError, - ResponseContentLengthMismatchError, - RequestAbortedError, - HeadersTimeoutError, - HeadersOverflowError, - SocketError, - InformationalError, - BodyTimeoutError, - HTTPParserError, - ResponseExceededMaxSizeError -} = __nccwpck_require__(4928) -const { - kUrl, - kReset, - kClient, - kParser, - kBlocking, - kRunning, - kPending, - kSize, - kWriting, - kQueue, - kNoRef, - kKeepAliveDefaultTimeout, - kHostHeader, - kPendingIdx, - kRunningIdx, - kError, - kPipelining, - kSocket, - kKeepAliveTimeoutValue, - kMaxHeadersSize, - kKeepAliveMaxTimeout, - kKeepAliveTimeoutThreshold, - kHeadersTimeout, - kBodyTimeout, - kStrictContentLength, - kMaxRequests, - kCounter, - kMaxResponseSize, - kOnError, - kResume, - kHTTPContext, - kClosed -} = __nccwpck_require__(9562) - -const constants = __nccwpck_require__(5849) -const EMPTY_BUF = Buffer.alloc(0) -const FastBuffer = Buffer[Symbol.species] -const removeAllListeners = util.removeAllListeners +/** + * @see https://developer.mozilla.org/docs/Web/HTTP/Headers + */ +const wellknownHeaderNames = /** @type {const} */ ([ + 'Accept', + 'Accept-Encoding', + 'Accept-Language', + 'Accept-Ranges', + 'Access-Control-Allow-Credentials', + 'Access-Control-Allow-Headers', + 'Access-Control-Allow-Methods', + 'Access-Control-Allow-Origin', + 'Access-Control-Expose-Headers', + 'Access-Control-Max-Age', + 'Access-Control-Request-Headers', + 'Access-Control-Request-Method', + 'Age', + 'Allow', + 'Alt-Svc', + 'Alt-Used', + 'Authorization', + 'Cache-Control', + 'Clear-Site-Data', + 'Connection', + 'Content-Disposition', + 'Content-Encoding', + 'Content-Language', + 'Content-Length', + 'Content-Location', + 'Content-Range', + 'Content-Security-Policy', + 'Content-Security-Policy-Report-Only', + 'Content-Type', + 'Cookie', + 'Cross-Origin-Embedder-Policy', + 'Cross-Origin-Opener-Policy', + 'Cross-Origin-Resource-Policy', + 'Date', + 'Device-Memory', + 'Downlink', + 'ECT', + 'ETag', + 'Expect', + 'Expect-CT', + 'Expires', + 'Forwarded', + 'From', + 'Host', + 'If-Match', + 'If-Modified-Since', + 'If-None-Match', + 'If-Range', + 'If-Unmodified-Since', + 'Keep-Alive', + 'Last-Modified', + 'Link', + 'Location', + 'Max-Forwards', + 'Origin', + 'Permissions-Policy', + 'Pragma', + 'Proxy-Authenticate', + 'Proxy-Authorization', + 'RTT', + 'Range', + 'Referer', + 'Referrer-Policy', + 'Refresh', + 'Retry-After', + 'Sec-WebSocket-Accept', + 'Sec-WebSocket-Extensions', + 'Sec-WebSocket-Key', + 'Sec-WebSocket-Protocol', + 'Sec-WebSocket-Version', + 'Server', + 'Server-Timing', + 'Service-Worker-Allowed', + 'Service-Worker-Navigation-Preload', + 'Set-Cookie', + 'SourceMap', + 'Strict-Transport-Security', + 'Supports-Loading-Mode', + 'TE', + 'Timing-Allow-Origin', + 'Trailer', + 'Transfer-Encoding', + 'Upgrade', + 'Upgrade-Insecure-Requests', + 'User-Agent', + 'Vary', + 'Via', + 'WWW-Authenticate', + 'X-Content-Type-Options', + 'X-DNS-Prefetch-Control', + 'X-Frame-Options', + 'X-Permitted-Cross-Domain-Policies', + 'X-Powered-By', + 'X-Requested-With', + 'X-XSS-Protection' +]) -let extractBody +/** @type {Record, string>} */ +const headerNameLowerCasedRecord = {} -function lazyllhttp () { - const llhttpWasmData = process.env.JEST_WORKER_ID ? __nccwpck_require__(571) : undefined +// Note: object prototypes should not be able to be referenced. e.g. `Object#hasOwnProperty`. +Object.setPrototypeOf(headerNameLowerCasedRecord, null) - let mod +/** + * @type {Record, Buffer>} + */ +const wellknownHeaderNameBuffers = {} - // We disable wasm SIMD on ppc64 as it seems to be broken on Power 9 architectures. - let useWasmSIMD = process.arch !== 'ppc64' - // The Env Variable UNDICI_NO_WASM_SIMD allows explicitly overriding the default behavior - if (process.env.UNDICI_NO_WASM_SIMD === '1') { - useWasmSIMD = true - } else if (process.env.UNDICI_NO_WASM_SIMD === '0') { - useWasmSIMD = false - } +// Note: object prototypes should not be able to be referenced. e.g. `Object#hasOwnProperty`. +Object.setPrototypeOf(wellknownHeaderNameBuffers, null) - if (useWasmSIMD) { - try { - mod = new WebAssembly.Module(__nccwpck_require__(7361)) - } catch { - } - } +/** + * @param {string} header Lowercased header + * @returns {Buffer} + */ +function getHeaderNameAsBuffer (header) { + let buffer = wellknownHeaderNameBuffers[header] - if (!mod) { - // We could check if the error was caused by the simd option not - // being enabled, but the occurring of this other error - // * https://github.com/emscripten-core/emscripten/issues/11495 - // got me to remove that check to avoid breaking Node 12. - mod = new WebAssembly.Module(llhttpWasmData || __nccwpck_require__(571)) + if (buffer === undefined) { + buffer = Buffer.from(header) } - return new WebAssembly.Instance(mod, { - env: { - /** - * @param {number} p - * @param {number} at - * @param {number} len - * @returns {number} - */ - wasm_on_url: (p, at, len) => { - return 0 - }, - /** - * @param {number} p - * @param {number} at - * @param {number} len - * @returns {number} - */ - wasm_on_status: (p, at, len) => { - assert(currentParser.ptr === p) - const start = at - currentBufferPtr + currentBufferRef.byteOffset - return currentParser.onStatus(new FastBuffer(currentBufferRef.buffer, start, len)) - }, - /** - * @param {number} p - * @returns {number} - */ - wasm_on_message_begin: (p) => { - assert(currentParser.ptr === p) - return currentParser.onMessageBegin() - }, - /** - * @param {number} p - * @param {number} at - * @param {number} len - * @returns {number} - */ - wasm_on_header_field: (p, at, len) => { - assert(currentParser.ptr === p) - const start = at - currentBufferPtr + currentBufferRef.byteOffset - return currentParser.onHeaderField(new FastBuffer(currentBufferRef.buffer, start, len)) - }, - /** - * @param {number} p - * @param {number} at - * @param {number} len - * @returns {number} - */ - wasm_on_header_value: (p, at, len) => { - assert(currentParser.ptr === p) - const start = at - currentBufferPtr + currentBufferRef.byteOffset - return currentParser.onHeaderValue(new FastBuffer(currentBufferRef.buffer, start, len)) - }, - /** - * @param {number} p - * @param {number} statusCode - * @param {0|1} upgrade - * @param {0|1} shouldKeepAlive - * @returns {number} - */ - wasm_on_headers_complete: (p, statusCode, upgrade, shouldKeepAlive) => { - assert(currentParser.ptr === p) - return currentParser.onHeadersComplete(statusCode, upgrade === 1, shouldKeepAlive === 1) - }, - /** - * @param {number} p - * @param {number} at - * @param {number} len - * @returns {number} - */ - wasm_on_body: (p, at, len) => { - assert(currentParser.ptr === p) - const start = at - currentBufferPtr + currentBufferRef.byteOffset - return currentParser.onBody(new FastBuffer(currentBufferRef.buffer, start, len)) - }, - /** - * @param {number} p - * @returns {number} - */ - wasm_on_message_complete: (p) => { - assert(currentParser.ptr === p) - return currentParser.onMessageComplete() - } + return buffer +} - } - }) +for (let i = 0; i < wellknownHeaderNames.length; ++i) { + const key = wellknownHeaderNames[i] + const lowerCasedKey = key.toLowerCase() + headerNameLowerCasedRecord[key] = headerNameLowerCasedRecord[lowerCasedKey] = + lowerCasedKey } -let llhttpInstance = null +module.exports = { + wellknownHeaderNames, + headerNameLowerCasedRecord, + getHeaderNameAsBuffer +} -/** - * @type {Parser|null} - */ -let currentParser = null -let currentBufferRef = null -/** - * @type {number} - */ -let currentBufferSize = 0 -let currentBufferPtr = null -const USE_NATIVE_TIMER = 0 -const USE_FAST_TIMER = 1 +/***/ }), -// Use fast timers for headers and body to take eventual event loop -// latency into account. -const TIMEOUT_HEADERS = 2 | USE_FAST_TIMER -const TIMEOUT_BODY = 4 | USE_FAST_TIMER +/***/ 2248: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -// Use native timers to ignore event loop latency for keep-alive -// handling. -const TIMEOUT_KEEP_ALIVE = 8 | USE_NATIVE_TIMER -class Parser { - /** - * @param {import('./client.js')} client - * @param {import('net').Socket} socket - * @param {*} llhttp - */ - constructor (client, socket, { exports }) { - this.llhttp = exports - this.ptr = this.llhttp.llhttp_alloc(constants.TYPE.RESPONSE) - this.client = client - /** - * @type {import('net').Socket} - */ - this.socket = socket - this.timeout = null - this.timeoutValue = null - this.timeoutType = null - this.statusCode = 0 - this.statusText = '' - this.upgrade = false - this.headers = [] - this.headersSize = 0 - this.headersMaxSize = client[kMaxHeadersSize] - this.shouldKeepAlive = false - this.paused = false - this.resume = this.resume.bind(this) - this.bytesRead = 0 +const diagnosticsChannel = __nccwpck_require__(3053) +const util = __nccwpck_require__(7975) - this.keepAlive = '' - this.contentLength = '' - this.connection = '' - this.maxResponseSize = client[kMaxResponseSize] - } +const undiciDebugLog = util.debuglog('undici') +const fetchDebuglog = util.debuglog('fetch') +const websocketDebuglog = util.debuglog('websocket') - setTimeout (delay, type) { - // If the existing timer and the new timer are of different timer type - // (fast or native) or have different delay, we need to clear the existing - // timer and set a new one. - if ( - delay !== this.timeoutValue || - (type & USE_FAST_TIMER) ^ (this.timeoutType & USE_FAST_TIMER) - ) { - // If a timeout is already set, clear it with clearTimeout of the fast - // timer implementation, as it can clear fast and native timers. - if (this.timeout) { - timers.clearTimeout(this.timeout) - this.timeout = null - } +const channels = { + // Client + beforeConnect: diagnosticsChannel.channel('undici:client:beforeConnect'), + connected: diagnosticsChannel.channel('undici:client:connected'), + connectError: diagnosticsChannel.channel('undici:client:connectError'), + sendHeaders: diagnosticsChannel.channel('undici:client:sendHeaders'), + // Request + create: diagnosticsChannel.channel('undici:request:create'), + bodySent: diagnosticsChannel.channel('undici:request:bodySent'), + bodyChunkSent: diagnosticsChannel.channel('undici:request:bodyChunkSent'), + bodyChunkReceived: diagnosticsChannel.channel('undici:request:bodyChunkReceived'), + headers: diagnosticsChannel.channel('undici:request:headers'), + trailers: diagnosticsChannel.channel('undici:request:trailers'), + error: diagnosticsChannel.channel('undici:request:error'), + // WebSocket + open: diagnosticsChannel.channel('undici:websocket:open'), + close: diagnosticsChannel.channel('undici:websocket:close'), + socketError: diagnosticsChannel.channel('undici:websocket:socket_error'), + ping: diagnosticsChannel.channel('undici:websocket:ping'), + pong: diagnosticsChannel.channel('undici:websocket:pong'), + // ProxyAgent + proxyConnected: diagnosticsChannel.channel('undici:proxy:connected') +} - if (delay) { - if (type & USE_FAST_TIMER) { - this.timeout = timers.setFastTimeout(onParserTimeout, delay, new WeakRef(this)) - } else { - this.timeout = setTimeout(onParserTimeout, delay, new WeakRef(this)) - this.timeout?.unref() - } - } +let isTrackingClientEvents = false - this.timeoutValue = delay - } else if (this.timeout) { - if (this.timeout.refresh) { - this.timeout.refresh() - } - } +function trackClientEvents (debugLog = undiciDebugLog) { + if (isTrackingClientEvents) { + return + } - this.timeoutType = type + // Check if any of the channels already have subscribers to prevent duplicate subscriptions + // This can happen when both Node.js built-in undici and undici as a dependency are present + if (channels.beforeConnect.hasSubscribers || channels.connected.hasSubscribers || + channels.connectError.hasSubscribers || channels.sendHeaders.hasSubscribers) { + isTrackingClientEvents = true + return } - resume () { - if (this.socket.destroyed || !this.paused) { - return - } + isTrackingClientEvents = true - assert(this.ptr != null) - assert(currentParser === null) + diagnosticsChannel.subscribe('undici:client:beforeConnect', + evt => { + const { + connectParams: { version, protocol, port, host } + } = evt + debugLog( + 'connecting to %s%s using %s%s', + host, + port ? `:${port}` : '', + protocol, + version + ) + }) - this.llhttp.llhttp_resume(this.ptr) + diagnosticsChannel.subscribe('undici:client:connected', + evt => { + const { + connectParams: { version, protocol, port, host } + } = evt + debugLog( + 'connected to %s%s using %s%s', + host, + port ? `:${port}` : '', + protocol, + version + ) + }) - assert(this.timeoutType === TIMEOUT_BODY) - if (this.timeout) { - if (this.timeout.refresh) { - this.timeout.refresh() - } - } + diagnosticsChannel.subscribe('undici:client:connectError', + evt => { + const { + connectParams: { version, protocol, port, host }, + error + } = evt + debugLog( + 'connection to %s%s using %s%s errored - %s', + host, + port ? `:${port}` : '', + protocol, + version, + error.message + ) + }) - this.paused = false - this.execute(this.socket.read() || EMPTY_BUF) // Flush parser. - this.readMore() - } + diagnosticsChannel.subscribe('undici:client:sendHeaders', + evt => { + const { + request: { method, path, origin } + } = evt + debugLog('sending request to %s %s%s', method, origin, path) + }) +} - readMore () { - while (!this.paused && this.ptr) { - const chunk = this.socket.read() - if (chunk === null) { - break - } - this.execute(chunk) - } - } +let isTrackingRequestEvents = false - /** - * @param {Buffer} chunk - */ - execute (chunk) { - assert(currentParser === null) - assert(this.ptr != null) - assert(!this.paused) +function trackRequestEvents (debugLog = undiciDebugLog) { + if (isTrackingRequestEvents) { + return + } - const { socket, llhttp } = this + // Check if any of the channels already have subscribers to prevent duplicate subscriptions + // This can happen when both Node.js built-in undici and undici as a dependency are present + if (channels.headers.hasSubscribers || channels.trailers.hasSubscribers || + channels.error.hasSubscribers) { + isTrackingRequestEvents = true + return + } - // Allocate a new buffer if the current buffer is too small. - if (chunk.length > currentBufferSize) { - if (currentBufferPtr) { - llhttp.free(currentBufferPtr) - } - // Allocate a buffer that is a multiple of 4096 bytes. - currentBufferSize = Math.ceil(chunk.length / 4096) * 4096 - currentBufferPtr = llhttp.malloc(currentBufferSize) - } + isTrackingRequestEvents = true - new Uint8Array(llhttp.memory.buffer, currentBufferPtr, currentBufferSize).set(chunk) + diagnosticsChannel.subscribe('undici:request:headers', + evt => { + const { + request: { method, path, origin }, + response: { statusCode } + } = evt + debugLog( + 'received response to %s %s%s - HTTP %d', + method, + origin, + path, + statusCode + ) + }) - // Call `execute` on the wasm parser. - // We pass the `llhttp_parser` pointer address, the pointer address of buffer view data, - // and finally the length of bytes to parse. - // The return value is an error code or `constants.ERROR.OK`. - try { - let ret + diagnosticsChannel.subscribe('undici:request:trailers', + evt => { + const { + request: { method, path, origin } + } = evt + debugLog('trailers received from %s %s%s', method, origin, path) + }) - try { - currentBufferRef = chunk - currentParser = this - ret = llhttp.llhttp_execute(this.ptr, currentBufferPtr, chunk.length) - } finally { - currentParser = null - currentBufferRef = null - } + diagnosticsChannel.subscribe('undici:request:error', + evt => { + const { + request: { method, path, origin }, + error + } = evt + debugLog( + 'request to %s %s%s errored - %s', + method, + origin, + path, + error.message + ) + }) +} - if (ret !== constants.ERROR.OK) { - const data = chunk.subarray(llhttp.llhttp_get_error_pos(this.ptr) - currentBufferPtr) +let isTrackingWebSocketEvents = false - if (ret === constants.ERROR.PAUSED_UPGRADE) { - this.onUpgrade(data) - } else if (ret === constants.ERROR.PAUSED) { - this.paused = true - socket.unshift(data) - } else { - const ptr = llhttp.llhttp_get_error_reason(this.ptr) - let message = '' - if (ptr) { - const len = new Uint8Array(llhttp.memory.buffer, ptr).indexOf(0) - message = - 'Response does not match the HTTP/1.1 protocol (' + - Buffer.from(llhttp.memory.buffer, ptr, len).toString() + - ')' - } - throw new HTTPParserError(message, constants.ERROR[ret], data) - } - } - } catch (err) { - util.destroy(socket, err) - } +function trackWebSocketEvents (debugLog = websocketDebuglog) { + if (isTrackingWebSocketEvents) { + return } - destroy () { - assert(currentParser === null) - assert(this.ptr != null) + // Check if any of the channels already have subscribers to prevent duplicate subscriptions + // This can happen when both Node.js built-in undici and undici as a dependency are present + if (channels.open.hasSubscribers || channels.close.hasSubscribers || + channels.socketError.hasSubscribers || channels.ping.hasSubscribers || + channels.pong.hasSubscribers) { + isTrackingWebSocketEvents = true + return + } - this.llhttp.llhttp_free(this.ptr) - this.ptr = null + isTrackingWebSocketEvents = true - this.timeout && timers.clearTimeout(this.timeout) - this.timeout = null - this.timeoutValue = null - this.timeoutType = null + diagnosticsChannel.subscribe('undici:websocket:open', + evt => { + const { + address: { address, port } + } = evt + debugLog('connection opened %s%s', address, port ? `:${port}` : '') + }) - this.paused = false - } + diagnosticsChannel.subscribe('undici:websocket:close', + evt => { + const { websocket, code, reason } = evt + debugLog( + 'closed connection to %s - %s %s', + websocket.url, + code, + reason + ) + }) - /** - * @param {Buffer} buf - * @returns {0} - */ - onStatus (buf) { - this.statusText = buf.toString() - return 0 - } + diagnosticsChannel.subscribe('undici:websocket:socket_error', + err => { + debugLog('connection errored - %s', err.message) + }) - /** - * @returns {0|-1} - */ - onMessageBegin () { - const { socket, client } = this + diagnosticsChannel.subscribe('undici:websocket:ping', + evt => { + debugLog('ping received') + }) - if (socket.destroyed) { - return -1 - } + diagnosticsChannel.subscribe('undici:websocket:pong', + evt => { + debugLog('pong received') + }) +} - const request = client[kQueue][client[kRunningIdx]] - if (!request) { - return -1 - } - request.onResponseStarted() +if (undiciDebugLog.enabled || fetchDebuglog.enabled) { + trackClientEvents(fetchDebuglog.enabled ? fetchDebuglog : undiciDebugLog) + trackRequestEvents(fetchDebuglog.enabled ? fetchDebuglog : undiciDebugLog) +} - return 0 - } +if (websocketDebuglog.enabled) { + trackClientEvents(undiciDebugLog.enabled ? undiciDebugLog : websocketDebuglog) + trackWebSocketEvents(websocketDebuglog) +} - /** - * @param {Buffer} buf - * @returns {number} - */ - onHeaderField (buf) { - const len = this.headers.length +module.exports = { + channels +} - if ((len & 1) === 0) { - this.headers.push(buf) - } else { - this.headers[len - 1] = Buffer.concat([this.headers[len - 1], buf]) - } - this.trackHeader(buf.length) +/***/ }), - return 0 - } +/***/ 5093: +/***/ ((module) => { - /** - * @param {Buffer} buf - * @returns {number} - */ - onHeaderValue (buf) { - let len = this.headers.length - if ((len & 1) === 1) { - this.headers.push(buf) - len += 1 - } else { - this.headers[len - 1] = Buffer.concat([this.headers[len - 1], buf]) - } - const key = this.headers[len - 2] - if (key.length === 10) { - const headerName = util.bufferToLowerCasedHeaderName(key) - if (headerName === 'keep-alive') { - this.keepAlive += buf.toString() - } else if (headerName === 'connection') { - this.connection += buf.toString() - } - } else if (key.length === 14 && util.bufferToLowerCasedHeaderName(key) === 'content-length') { - this.contentLength += buf.toString() - } +const kUndiciError = Symbol.for('undici.error.UND_ERR') +class UndiciError extends Error { + constructor (message, options) { + super(message, options) + this.name = 'UndiciError' + this.code = 'UND_ERR' + } - this.trackHeader(buf.length) + static [Symbol.hasInstance] (instance) { + return instance && instance[kUndiciError] === true + } - return 0 + get [kUndiciError] () { + return true } +} - /** - * @param {number} len - */ - trackHeader (len) { - this.headersSize += len - if (this.headersSize >= this.headersMaxSize) { - util.destroy(this.socket, new HeadersOverflowError()) - } +const kConnectTimeoutError = Symbol.for('undici.error.UND_ERR_CONNECT_TIMEOUT') +class ConnectTimeoutError extends UndiciError { + constructor (message) { + super(message) + this.name = 'ConnectTimeoutError' + this.message = message || 'Connect Timeout Error' + this.code = 'UND_ERR_CONNECT_TIMEOUT' } - /** - * @param {Buffer} head - */ - onUpgrade (head) { - const { upgrade, client, socket, headers, statusCode } = this + static [Symbol.hasInstance] (instance) { + return instance && instance[kConnectTimeoutError] === true + } - assert(upgrade) - assert(client[kSocket] === socket) - assert(!socket.destroyed) - assert(!this.paused) - assert((headers.length & 1) === 0) + get [kConnectTimeoutError] () { + return true + } +} - const request = client[kQueue][client[kRunningIdx]] - assert(request) - assert(request.upgrade || request.method === 'CONNECT') +const kHeadersTimeoutError = Symbol.for('undici.error.UND_ERR_HEADERS_TIMEOUT') +class HeadersTimeoutError extends UndiciError { + constructor (message) { + super(message) + this.name = 'HeadersTimeoutError' + this.message = message || 'Headers Timeout Error' + this.code = 'UND_ERR_HEADERS_TIMEOUT' + } - this.statusCode = 0 - this.statusText = '' - this.shouldKeepAlive = false + static [Symbol.hasInstance] (instance) { + return instance && instance[kHeadersTimeoutError] === true + } - this.headers = [] - this.headersSize = 0 + get [kHeadersTimeoutError] () { + return true + } +} - socket.unshift(head) +const kHeadersOverflowError = Symbol.for('undici.error.UND_ERR_HEADERS_OVERFLOW') +class HeadersOverflowError extends UndiciError { + constructor (message) { + super(message) + this.name = 'HeadersOverflowError' + this.message = message || 'Headers Overflow Error' + this.code = 'UND_ERR_HEADERS_OVERFLOW' + } - socket[kParser].destroy() - socket[kParser] = null + static [Symbol.hasInstance] (instance) { + return instance && instance[kHeadersOverflowError] === true + } - socket[kClient] = null - socket[kError] = null + get [kHeadersOverflowError] () { + return true + } +} - removeAllListeners(socket) +const kBodyTimeoutError = Symbol.for('undici.error.UND_ERR_BODY_TIMEOUT') +class BodyTimeoutError extends UndiciError { + constructor (message) { + super(message) + this.name = 'BodyTimeoutError' + this.message = message || 'Body Timeout Error' + this.code = 'UND_ERR_BODY_TIMEOUT' + } - client[kSocket] = null - client[kHTTPContext] = null // TODO (fix): This is hacky... - client[kQueue][client[kRunningIdx]++] = null - client.emit('disconnect', client[kUrl], [client], new InformationalError('upgrade')) + static [Symbol.hasInstance] (instance) { + return instance && instance[kBodyTimeoutError] === true + } - try { - request.onUpgrade(statusCode, headers, socket) - } catch (err) { - util.destroy(socket, err) - } + get [kBodyTimeoutError] () { + return true + } +} - client[kResume]() +const kInvalidArgumentError = Symbol.for('undici.error.UND_ERR_INVALID_ARG') +class InvalidArgumentError extends UndiciError { + constructor (message) { + super(message) + this.name = 'InvalidArgumentError' + this.message = message || 'Invalid Argument Error' + this.code = 'UND_ERR_INVALID_ARG' } - /** - * @param {number} statusCode - * @param {boolean} upgrade - * @param {boolean} shouldKeepAlive - * @returns {number} - */ - onHeadersComplete (statusCode, upgrade, shouldKeepAlive) { - const { client, socket, headers, statusText } = this + static [Symbol.hasInstance] (instance) { + return instance && instance[kInvalidArgumentError] === true + } - if (socket.destroyed) { - return -1 - } + get [kInvalidArgumentError] () { + return true + } +} - const request = client[kQueue][client[kRunningIdx]] +const kInvalidReturnValueError = Symbol.for('undici.error.UND_ERR_INVALID_RETURN_VALUE') +class InvalidReturnValueError extends UndiciError { + constructor (message) { + super(message) + this.name = 'InvalidReturnValueError' + this.message = message || 'Invalid Return Value Error' + this.code = 'UND_ERR_INVALID_RETURN_VALUE' + } - if (!request) { - return -1 - } + static [Symbol.hasInstance] (instance) { + return instance && instance[kInvalidReturnValueError] === true + } - assert(!this.upgrade) - assert(this.statusCode < 200) + get [kInvalidReturnValueError] () { + return true + } +} - if (statusCode === 100) { - util.destroy(socket, new SocketError('bad response', util.getSocketInfo(socket))) - return -1 - } +const kAbortError = Symbol.for('undici.error.UND_ERR_ABORT') +class AbortError extends UndiciError { + constructor (message) { + super(message) + this.name = 'AbortError' + this.message = message || 'The operation was aborted' + this.code = 'UND_ERR_ABORT' + } - /* this can only happen if server is misbehaving */ - if (upgrade && !request.upgrade) { - util.destroy(socket, new SocketError('bad upgrade', util.getSocketInfo(socket))) - return -1 - } + static [Symbol.hasInstance] (instance) { + return instance && instance[kAbortError] === true + } - assert(this.timeoutType === TIMEOUT_HEADERS) + get [kAbortError] () { + return true + } +} - this.statusCode = statusCode - this.shouldKeepAlive = ( - shouldKeepAlive || - // Override llhttp value which does not allow keepAlive for HEAD. - (request.method === 'HEAD' && !socket[kReset] && this.connection.toLowerCase() === 'keep-alive') - ) +const kRequestAbortedError = Symbol.for('undici.error.UND_ERR_ABORTED') +class RequestAbortedError extends AbortError { + constructor (message) { + super(message) + this.name = 'AbortError' + this.message = message || 'Request aborted' + this.code = 'UND_ERR_ABORTED' + } - if (this.statusCode >= 200) { - const bodyTimeout = request.bodyTimeout != null - ? request.bodyTimeout - : client[kBodyTimeout] - this.setTimeout(bodyTimeout, TIMEOUT_BODY) - } else if (this.timeout) { - if (this.timeout.refresh) { - this.timeout.refresh() - } - } + static [Symbol.hasInstance] (instance) { + return instance && instance[kRequestAbortedError] === true + } - if (request.method === 'CONNECT') { - assert(client[kRunning] === 1) - this.upgrade = true - return 2 - } + get [kRequestAbortedError] () { + return true + } +} - if (upgrade) { - assert(client[kRunning] === 1) - this.upgrade = true - return 2 - } +const kInformationalError = Symbol.for('undici.error.UND_ERR_INFO') +class InformationalError extends UndiciError { + constructor (message) { + super(message) + this.name = 'InformationalError' + this.message = message || 'Request information' + this.code = 'UND_ERR_INFO' + } - assert((this.headers.length & 1) === 0) - this.headers = [] - this.headersSize = 0 + static [Symbol.hasInstance] (instance) { + return instance && instance[kInformationalError] === true + } - if (this.shouldKeepAlive && client[kPipelining]) { - const keepAliveTimeout = this.keepAlive ? util.parseKeepAliveTimeout(this.keepAlive) : null + get [kInformationalError] () { + return true + } +} - if (keepAliveTimeout != null) { - const timeout = Math.min( - keepAliveTimeout - client[kKeepAliveTimeoutThreshold], - client[kKeepAliveMaxTimeout] - ) - if (timeout <= 0) { - socket[kReset] = true - } else { - client[kKeepAliveTimeoutValue] = timeout - } - } else { - client[kKeepAliveTimeoutValue] = client[kKeepAliveDefaultTimeout] - } - } else { - // Stop more requests from being dispatched. - socket[kReset] = true - } +const kRequestContentLengthMismatchError = Symbol.for('undici.error.UND_ERR_REQ_CONTENT_LENGTH_MISMATCH') +class RequestContentLengthMismatchError extends UndiciError { + constructor (message) { + super(message) + this.name = 'RequestContentLengthMismatchError' + this.message = message || 'Request body length does not match content-length header' + this.code = 'UND_ERR_REQ_CONTENT_LENGTH_MISMATCH' + } - const pause = request.onHeaders(statusCode, headers, this.resume, statusText) === false + static [Symbol.hasInstance] (instance) { + return instance && instance[kRequestContentLengthMismatchError] === true + } - if (request.aborted) { - return -1 - } + get [kRequestContentLengthMismatchError] () { + return true + } +} - if (request.method === 'HEAD') { - return 1 - } +const kResponseContentLengthMismatchError = Symbol.for('undici.error.UND_ERR_RES_CONTENT_LENGTH_MISMATCH') +class ResponseContentLengthMismatchError extends UndiciError { + constructor (message) { + super(message) + this.name = 'ResponseContentLengthMismatchError' + this.message = message || 'Response body length does not match content-length header' + this.code = 'UND_ERR_RES_CONTENT_LENGTH_MISMATCH' + } - if (statusCode < 200) { - return 1 - } + static [Symbol.hasInstance] (instance) { + return instance && instance[kResponseContentLengthMismatchError] === true + } - if (socket[kBlocking]) { - socket[kBlocking] = false - client[kResume]() - } + get [kResponseContentLengthMismatchError] () { + return true + } +} - return pause ? constants.ERROR.PAUSED : 0 +const kClientDestroyedError = Symbol.for('undici.error.UND_ERR_DESTROYED') +class ClientDestroyedError extends UndiciError { + constructor (message) { + super(message) + this.name = 'ClientDestroyedError' + this.message = message || 'The client is destroyed' + this.code = 'UND_ERR_DESTROYED' } - /** - * @param {Buffer} buf - * @returns {number} - */ - onBody (buf) { - const { client, socket, statusCode, maxResponseSize } = this + static [Symbol.hasInstance] (instance) { + return instance && instance[kClientDestroyedError] === true + } - if (socket.destroyed) { - return -1 - } + get [kClientDestroyedError] () { + return true + } +} - const request = client[kQueue][client[kRunningIdx]] - assert(request) +const kClientClosedError = Symbol.for('undici.error.UND_ERR_CLOSED') +class ClientClosedError extends UndiciError { + constructor (message) { + super(message) + this.name = 'ClientClosedError' + this.message = message || 'The client is closed' + this.code = 'UND_ERR_CLOSED' + } - assert(this.timeoutType === TIMEOUT_BODY) - if (this.timeout) { - if (this.timeout.refresh) { - this.timeout.refresh() - } - } - - assert(statusCode >= 200) - - if (maxResponseSize > -1 && this.bytesRead + buf.length > maxResponseSize) { - util.destroy(socket, new ResponseExceededMaxSizeError()) - return -1 - } - - this.bytesRead += buf.length - - if (request.onData(buf) === false) { - return constants.ERROR.PAUSED - } - - return 0 + static [Symbol.hasInstance] (instance) { + return instance && instance[kClientClosedError] === true } - /** - * @returns {number} - */ - onMessageComplete () { - const { client, socket, statusCode, upgrade, headers, contentLength, bytesRead, shouldKeepAlive } = this + get [kClientClosedError] () { + return true + } +} - if (socket.destroyed && (!statusCode || shouldKeepAlive)) { - return -1 - } +const kSocketError = Symbol.for('undici.error.UND_ERR_SOCKET') +class SocketError extends UndiciError { + constructor (message, socket) { + super(message) + this.name = 'SocketError' + this.message = message || 'Socket error' + this.code = 'UND_ERR_SOCKET' + this.socket = socket + } - if (upgrade) { - return 0 - } + static [Symbol.hasInstance] (instance) { + return instance && instance[kSocketError] === true + } - assert(statusCode >= 100) - assert((this.headers.length & 1) === 0) + get [kSocketError] () { + return true + } +} - const request = client[kQueue][client[kRunningIdx]] - assert(request) +const kNotSupportedError = Symbol.for('undici.error.UND_ERR_NOT_SUPPORTED') +class NotSupportedError extends UndiciError { + constructor (message) { + super(message) + this.name = 'NotSupportedError' + this.message = message || 'Not supported error' + this.code = 'UND_ERR_NOT_SUPPORTED' + } - this.statusCode = 0 - this.statusText = '' - this.bytesRead = 0 - this.contentLength = '' - this.keepAlive = '' - this.connection = '' + static [Symbol.hasInstance] (instance) { + return instance && instance[kNotSupportedError] === true + } - this.headers = [] - this.headersSize = 0 + get [kNotSupportedError] () { + return true + } +} - if (statusCode < 200) { - return 0 - } +const kBalancedPoolMissingUpstreamError = Symbol.for('undici.error.UND_ERR_BPL_MISSING_UPSTREAM') +class BalancedPoolMissingUpstreamError extends UndiciError { + constructor (message) { + super(message) + this.name = 'MissingUpstreamError' + this.message = message || 'No upstream has been added to the BalancedPool' + this.code = 'UND_ERR_BPL_MISSING_UPSTREAM' + } - if (request.method !== 'HEAD' && contentLength && bytesRead !== parseInt(contentLength, 10)) { - util.destroy(socket, new ResponseContentLengthMismatchError()) - return -1 - } + static [Symbol.hasInstance] (instance) { + return instance && instance[kBalancedPoolMissingUpstreamError] === true + } - request.onComplete(headers) + get [kBalancedPoolMissingUpstreamError] () { + return true + } +} - client[kQueue][client[kRunningIdx]++] = null +const kHTTPParserError = Symbol.for('undici.error.UND_ERR_HTTP_PARSER') +class HTTPParserError extends Error { + constructor (message, code, data) { + super(message) + this.name = 'HTTPParserError' + this.code = code ? `HPE_${code}` : undefined + this.data = data ? data.toString() : undefined + } - if (socket[kWriting]) { - assert(client[kRunning] === 0) - // Response completed before request. - util.destroy(socket, new InformationalError('reset')) - return constants.ERROR.PAUSED - } else if (!shouldKeepAlive) { - util.destroy(socket, new InformationalError('reset')) - return constants.ERROR.PAUSED - } else if (socket[kReset] && client[kRunning] === 0) { - // Destroy socket once all requests have completed. - // The request at the tail of the pipeline is the one - // that requested reset and no further requests should - // have been queued since then. - util.destroy(socket, new InformationalError('reset')) - return constants.ERROR.PAUSED - } else if (client[kPipelining] == null || client[kPipelining] === 1) { - // We must wait a full event loop cycle to reuse this socket to make sure - // that non-spec compliant servers are not closing the connection even if they - // said they won't. - setImmediate(client[kResume]) - } else { - client[kResume]() - } + static [Symbol.hasInstance] (instance) { + return instance && instance[kHTTPParserError] === true + } - return 0 + get [kHTTPParserError] () { + return true } } -function onParserTimeout (parser) { - const { socket, timeoutType, client, paused } = parser.deref() +const kResponseExceededMaxSizeError = Symbol.for('undici.error.UND_ERR_RES_EXCEEDED_MAX_SIZE') +class ResponseExceededMaxSizeError extends UndiciError { + constructor (message) { + super(message) + this.name = 'ResponseExceededMaxSizeError' + this.message = message || 'Response content exceeded max size' + this.code = 'UND_ERR_RES_EXCEEDED_MAX_SIZE' + } - if (timeoutType === TIMEOUT_HEADERS) { - if (!socket[kWriting] || socket.writableNeedDrain || client[kRunning] > 1) { - assert(!paused, 'cannot be paused while waiting for headers') - util.destroy(socket, new HeadersTimeoutError()) - } - } else if (timeoutType === TIMEOUT_BODY) { - if (!paused) { - util.destroy(socket, new BodyTimeoutError()) - } - } else if (timeoutType === TIMEOUT_KEEP_ALIVE) { - assert(client[kRunning] === 0 && client[kKeepAliveTimeoutValue]) - util.destroy(socket, new InformationalError('socket idle timeout')) + static [Symbol.hasInstance] (instance) { + return instance && instance[kResponseExceededMaxSizeError] === true } -} -/** - * @param {import ('./client.js')} client - * @param {import('net').Socket} socket - * @returns - */ -function connectH1 (client, socket) { - client[kSocket] = socket + get [kResponseExceededMaxSizeError] () { + return true + } +} - if (!llhttpInstance) { - llhttpInstance = lazyllhttp() +const kRequestRetryError = Symbol.for('undici.error.UND_ERR_REQ_RETRY') +class RequestRetryError extends UndiciError { + constructor (message, code, { headers, data }) { + super(message) + this.name = 'RequestRetryError' + this.message = message || 'Request retry error' + this.code = 'UND_ERR_REQ_RETRY' + this.statusCode = code + this.data = data + this.headers = headers } - if (socket.errored) { - throw socket.errored + static [Symbol.hasInstance] (instance) { + return instance && instance[kRequestRetryError] === true } - if (socket.destroyed) { - throw new SocketError('destroyed') + get [kRequestRetryError] () { + return true } +} - socket[kNoRef] = false - socket[kWriting] = false - socket[kReset] = false - socket[kBlocking] = false - socket[kParser] = new Parser(client, socket, llhttpInstance) +const kResponseError = Symbol.for('undici.error.UND_ERR_RESPONSE') +class ResponseError extends UndiciError { + constructor (message, code, { headers, body }) { + super(message) + this.name = 'ResponseError' + this.message = message || 'Response error' + this.code = 'UND_ERR_RESPONSE' + this.statusCode = code + this.body = body + this.headers = headers + } - util.addListener(socket, 'error', onHttpSocketError) - util.addListener(socket, 'readable', onHttpSocketReadable) - util.addListener(socket, 'end', onHttpSocketEnd) - util.addListener(socket, 'close', onHttpSocketClose) + static [Symbol.hasInstance] (instance) { + return instance && instance[kResponseError] === true + } - socket[kClosed] = false - socket.on('close', onSocketClose) + get [kResponseError] () { + return true + } +} - return { - version: 'h1', - defaultPipelining: 1, - write (request) { - return writeH1(client, request) - }, - resume () { - resumeH1(client) - }, - /** - * @param {Error|undefined} err - * @param {() => void} callback - */ - destroy (err, callback) { - if (socket[kClosed]) { - queueMicrotask(callback) - } else { - socket.on('close', callback) - socket.destroy(err) - } - }, - /** - * @returns {boolean} - */ - get destroyed () { - return socket.destroyed - }, - /** - * @param {import('../core/request.js')} request - * @returns {boolean} - */ - busy (request) { - if (socket[kWriting] || socket[kReset] || socket[kBlocking]) { - return true - } +const kSecureProxyConnectionError = Symbol.for('undici.error.UND_ERR_PRX_TLS') +class SecureProxyConnectionError extends UndiciError { + constructor (cause, message, options = {}) { + super(message, { cause, ...options }) + this.name = 'SecureProxyConnectionError' + this.message = message || 'Secure Proxy Connection failed' + this.code = 'UND_ERR_PRX_TLS' + this.cause = cause + } - if (request) { - if (client[kRunning] > 0 && !request.idempotent) { - // Non-idempotent request cannot be retried. - // Ensure that no other requests are inflight and - // could cause failure. - return true - } + static [Symbol.hasInstance] (instance) { + return instance && instance[kSecureProxyConnectionError] === true + } - if (client[kRunning] > 0 && (request.upgrade || request.method === 'CONNECT')) { - // Don't dispatch an upgrade until all preceding requests have completed. - // A misbehaving server might upgrade the connection before all pipelined - // request has completed. - return true - } + get [kSecureProxyConnectionError] () { + return true + } +} - if (client[kRunning] > 0 && util.bodyLength(request.body) !== 0 && - (util.isStream(request.body) || util.isAsyncIterable(request.body) || util.isFormDataLike(request.body))) { - // Request with stream or iterator body can error while other requests - // are inflight and indirectly error those as well. - // Ensure this doesn't happen by waiting for inflight - // to complete before dispatching. +const kMaxOriginsReachedError = Symbol.for('undici.error.UND_ERR_MAX_ORIGINS_REACHED') +class MaxOriginsReachedError extends UndiciError { + constructor (message) { + super(message) + this.name = 'MaxOriginsReachedError' + this.message = message || 'Maximum allowed origins reached' + this.code = 'UND_ERR_MAX_ORIGINS_REACHED' + } - // Request with stream or iterator body cannot be retried. - // Ensure that no other requests are inflight and - // could cause failure. - return true - } - } + static [Symbol.hasInstance] (instance) { + return instance && instance[kMaxOriginsReachedError] === true + } - return false - } + get [kMaxOriginsReachedError] () { + return true } } -function onHttpSocketError (err) { - assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID') - - const parser = this[kParser] +module.exports = { + AbortError, + HTTPParserError, + UndiciError, + HeadersTimeoutError, + HeadersOverflowError, + BodyTimeoutError, + RequestContentLengthMismatchError, + ConnectTimeoutError, + InvalidArgumentError, + InvalidReturnValueError, + RequestAbortedError, + ClientDestroyedError, + ClientClosedError, + InformationalError, + SocketError, + NotSupportedError, + ResponseContentLengthMismatchError, + BalancedPoolMissingUpstreamError, + ResponseExceededMaxSizeError, + RequestRetryError, + ResponseError, + SecureProxyConnectionError, + MaxOriginsReachedError +} - // On Mac OS, we get an ECONNRESET even if there is a full body to be forwarded - // to the user. - if (err.code === 'ECONNRESET' && parser.statusCode && !parser.shouldKeepAlive) { - // We treat all incoming data so for as a valid response. - parser.onMessageComplete() - return - } - this[kError] = err +/***/ }), - this[kClient][kOnError](err) -} +/***/ 5881: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -function onHttpSocketReadable () { - this[kParser]?.readMore() -} -function onHttpSocketEnd () { - const parser = this[kParser] - if (parser.statusCode && !parser.shouldKeepAlive) { - // We treat all incoming data so far as a valid response. - parser.onMessageComplete() - return - } +const { + InvalidArgumentError, + NotSupportedError +} = __nccwpck_require__(5093) +const assert = __nccwpck_require__(4589) +const { + isValidHTTPToken, + isValidHeaderValue, + isStream, + destroy, + isBuffer, + isFormDataLike, + isIterable, + isBlobLike, + serializePathWithQuery, + assertRequestHandler, + getServerName, + normalizedMethodRecords, + getProtocolFromUrlString +} = __nccwpck_require__(2550) +const { channels } = __nccwpck_require__(2248) +const { headerNameLowerCasedRecord } = __nccwpck_require__(5337) - util.destroy(this, new SocketError('other side closed', util.getSocketInfo(this))) -} +// Verifies that a given path is valid does not contain control chars \x00 to \x20 +const invalidPathRegex = /[^\u0021-\u00ff]/ -function onHttpSocketClose () { - const parser = this[kParser] +const kHandler = Symbol('handler') - if (parser) { - if (!this[kError] && parser.statusCode && !parser.shouldKeepAlive) { - // We treat all incoming data so far as a valid response. - parser.onMessageComplete() +class Request { + constructor (origin, { + path, + method, + body, + headers, + query, + idempotent, + blocking, + upgrade, + headersTimeout, + bodyTimeout, + reset, + expectContinue, + servername, + throwOnError, + maxRedirections + }, handler) { + if (typeof path !== 'string') { + throw new InvalidArgumentError('path must be a string') + } else if ( + path[0] !== '/' && + !(path.startsWith('http://') || path.startsWith('https://')) && + method !== 'CONNECT' + ) { + throw new InvalidArgumentError('path must be an absolute URL or start with a slash') + } else if (invalidPathRegex.test(path)) { + throw new InvalidArgumentError('invalid request path') } - this[kParser].destroy() - this[kParser] = null - } + if (typeof method !== 'string') { + throw new InvalidArgumentError('method must be a string') + } else if (normalizedMethodRecords[method] === undefined && !isValidHTTPToken(method)) { + throw new InvalidArgumentError('invalid request method') + } - const err = this[kError] || new SocketError('closed', util.getSocketInfo(this)) + if (upgrade && typeof upgrade !== 'string') { + throw new InvalidArgumentError('upgrade must be a string') + } - const client = this[kClient] + if (headersTimeout != null && (!Number.isFinite(headersTimeout) || headersTimeout < 0)) { + throw new InvalidArgumentError('invalid headersTimeout') + } - client[kSocket] = null - client[kHTTPContext] = null // TODO (fix): This is hacky... + if (bodyTimeout != null && (!Number.isFinite(bodyTimeout) || bodyTimeout < 0)) { + throw new InvalidArgumentError('invalid bodyTimeout') + } - if (client.destroyed) { - assert(client[kPending] === 0) + if (reset != null && typeof reset !== 'boolean') { + throw new InvalidArgumentError('invalid reset') + } - // Fail entire queue. - const requests = client[kQueue].splice(client[kRunningIdx]) - for (let i = 0; i < requests.length; i++) { - const request = requests[i] - util.errorRequest(client, request, err) + if (expectContinue != null && typeof expectContinue !== 'boolean') { + throw new InvalidArgumentError('invalid expectContinue') } - } else if (client[kRunning] > 0 && err.code !== 'UND_ERR_INFO') { - // Fail head of pipeline. - const request = client[kQueue][client[kRunningIdx]] - client[kQueue][client[kRunningIdx]++] = null - util.errorRequest(client, request, err) - } + if (throwOnError != null) { + throw new InvalidArgumentError('invalid throwOnError') + } - client[kPendingIdx] = client[kRunningIdx] + if (maxRedirections != null && maxRedirections !== 0) { + throw new InvalidArgumentError('maxRedirections is not supported, use the redirect interceptor') + } - assert(client[kRunning] === 0) + this.headersTimeout = headersTimeout - client.emit('disconnect', client[kUrl], [client], err) + this.bodyTimeout = bodyTimeout - client[kResume]() -} + this.method = method -function onSocketClose () { - this[kClosed] = true -} + this.abort = null -/** - * @param {import('./client.js')} client - */ -function resumeH1 (client) { - const socket = client[kSocket] + if (body == null) { + this.body = null + } else if (isStream(body)) { + this.body = body - if (socket && !socket.destroyed) { - if (client[kSize] === 0) { - if (!socket[kNoRef] && socket.unref) { - socket.unref() - socket[kNoRef] = true + const rState = this.body._readableState + if (!rState || !rState.autoDestroy) { + this.endHandler = function autoDestroy () { + destroy(this) + } + this.body.on('end', this.endHandler) } - } else if (socket[kNoRef] && socket.ref) { - socket.ref() - socket[kNoRef] = false - } - if (client[kSize] === 0) { - if (socket[kParser].timeoutType !== TIMEOUT_KEEP_ALIVE) { - socket[kParser].setTimeout(client[kKeepAliveTimeoutValue], TIMEOUT_KEEP_ALIVE) - } - } else if (client[kRunning] > 0 && socket[kParser].statusCode < 200) { - if (socket[kParser].timeoutType !== TIMEOUT_HEADERS) { - const request = client[kQueue][client[kRunningIdx]] - const headersTimeout = request.headersTimeout != null - ? request.headersTimeout - : client[kHeadersTimeout] - socket[kParser].setTimeout(headersTimeout, TIMEOUT_HEADERS) + this.errorHandler = err => { + if (this.abort) { + this.abort(err) + } else { + this.error = err + } } + this.body.on('error', this.errorHandler) + } else if (isBuffer(body)) { + this.body = body.byteLength ? body : null + } else if (ArrayBuffer.isView(body)) { + this.body = body.buffer.byteLength ? Buffer.from(body.buffer, body.byteOffset, body.byteLength) : null + } else if (body instanceof ArrayBuffer) { + this.body = body.byteLength ? Buffer.from(body) : null + } else if (typeof body === 'string') { + this.body = body.length ? Buffer.from(body) : null + } else if (isFormDataLike(body) || isIterable(body) || isBlobLike(body)) { + this.body = body + } else { + throw new InvalidArgumentError('body must be a string, a Buffer, a Readable stream, an iterable, or an async iterable') } - } -} - -// https://www.rfc-editor.org/rfc/rfc7230#section-3.3.2 -function shouldSendContentLength (method) { - return method !== 'GET' && method !== 'HEAD' && method !== 'OPTIONS' && method !== 'TRACE' && method !== 'CONNECT' -} - -/** - * @param {import('./client.js')} client - * @param {import('../core/request.js')} request - * @returns - */ -function writeH1 (client, request) { - const { method, path, host, upgrade, blocking, reset } = request - - let { body, headers, contentLength } = request - - // https://tools.ietf.org/html/rfc7231#section-4.3.1 - // https://tools.ietf.org/html/rfc7231#section-4.3.2 - // https://tools.ietf.org/html/rfc7231#section-4.3.5 - // Sending a payload body on a request that does not - // expect it can cause undefined behavior on some - // servers and corrupt connection state. Do not - // re-use the connection for further requests. + this.completed = false + this.aborted = false - const expectsPayload = ( - method === 'PUT' || - method === 'POST' || - method === 'PATCH' || - method === 'QUERY' || - method === 'PROPFIND' || - method === 'PROPPATCH' - ) + this.upgrade = upgrade || null - if (util.isFormDataLike(body)) { - if (!extractBody) { - extractBody = (__nccwpck_require__(2921).extractBody) - } + this.path = query ? serializePathWithQuery(path, query) : path - const [bodyStream, contentType] = extractBody(body) - if (request.contentType == null) { - headers.push('content-type', contentType) - } - body = bodyStream.stream - contentLength = bodyStream.length - } else if (util.isBlobLike(body) && request.contentType == null && body.type) { - headers.push('content-type', body.type) - } + // TODO: shall we maybe standardize it to an URL object? + this.origin = origin - if (body && typeof body.read === 'function') { - // Try to read EOF in order to get length. - body.read(0) - } + this.protocol = getProtocolFromUrlString(origin) - const bodyLength = util.bodyLength(body) + this.idempotent = idempotent == null + ? method === 'HEAD' || method === 'GET' + : idempotent - contentLength = bodyLength ?? contentLength + this.blocking = blocking ?? this.method !== 'HEAD' - if (contentLength === null) { - contentLength = request.contentLength - } + this.reset = reset == null ? null : reset - if (contentLength === 0 && !expectsPayload) { - // https://tools.ietf.org/html/rfc7230#section-3.3.2 - // A user agent SHOULD NOT send a Content-Length header field when - // the request message does not contain a payload body and the method - // semantics do not anticipate such a body. + this.host = null - contentLength = null - } + this.contentLength = null - // https://github.com/nodejs/undici/issues/2046 - // A user agent may send a Content-Length header with 0 value, this should be allowed. - if (shouldSendContentLength(method) && contentLength > 0 && request.contentLength !== null && request.contentLength !== contentLength) { - if (client[kStrictContentLength]) { - util.errorRequest(client, request, new RequestContentLengthMismatchError()) - return false - } + this.contentType = null - process.emitWarning(new RequestContentLengthMismatchError()) - } + this.headers = [] - const socket = client[kSocket] + // Only for H2 + this.expectContinue = expectContinue != null ? expectContinue : false - /** - * @param {Error} [err] - * @returns {void} - */ - const abort = (err) => { - if (request.aborted || request.completed) { - return + if (Array.isArray(headers)) { + if (headers.length % 2 !== 0) { + throw new InvalidArgumentError('headers array must be even') + } + for (let i = 0; i < headers.length; i += 2) { + processHeader(this, headers[i], headers[i + 1]) + } + } else if (headers && typeof headers === 'object') { + if (headers[Symbol.iterator]) { + for (const header of headers) { + if (!Array.isArray(header) || header.length !== 2) { + throw new InvalidArgumentError('headers must be in key-value pair format') + } + processHeader(this, header[0], header[1]) + } + } else { + const keys = Object.keys(headers) + for (let i = 0; i < keys.length; ++i) { + processHeader(this, keys[i], headers[keys[i]]) + } + } + } else if (headers != null) { + throw new InvalidArgumentError('headers must be an object or an array') } - util.errorRequest(client, request, err || new RequestAbortedError()) + assertRequestHandler(handler, method, upgrade) - util.destroy(body) - util.destroy(socket, new InformationalError('aborted')) - } + this.servername = servername || getServerName(this.host) || null - try { - request.onConnect(abort) - } catch (err) { - util.errorRequest(client, request, err) - } + this[kHandler] = handler - if (request.aborted) { - return false + if (channels.create.hasSubscribers) { + channels.create.publish({ request: this }) + } } - if (method === 'HEAD') { - // https://github.com/mcollina/undici/issues/258 - // Close after a HEAD request to interop with misbehaving servers - // that may send a body in the response. - - socket[kReset] = true + onBodySent (chunk) { + if (channels.bodyChunkSent.hasSubscribers) { + channels.bodyChunkSent.publish({ request: this, chunk }) + } + if (this[kHandler].onBodySent) { + try { + return this[kHandler].onBodySent(chunk) + } catch (err) { + this.abort(err) + } + } } - if (upgrade || method === 'CONNECT') { - // On CONNECT or upgrade, block pipeline from dispatching further - // requests on this connection. - - socket[kReset] = true - } + onRequestSent () { + if (channels.bodySent.hasSubscribers) { + channels.bodySent.publish({ request: this }) + } - if (reset != null) { - socket[kReset] = reset + if (this[kHandler].onRequestSent) { + try { + return this[kHandler].onRequestSent() + } catch (err) { + this.abort(err) + } + } } - if (client[kMaxRequests] && socket[kCounter]++ >= client[kMaxRequests]) { - socket[kReset] = true - } + onConnect (abort) { + assert(!this.aborted) + assert(!this.completed) - if (blocking) { - socket[kBlocking] = true + if (this.error) { + abort(this.error) + } else { + this.abort = abort + return this[kHandler].onConnect(abort) + } } - let header = `${method} ${path} HTTP/1.1\r\n` - - if (typeof host === 'string') { - header += `host: ${host}\r\n` - } else { - header += client[kHostHeader] + onResponseStarted () { + return this[kHandler].onResponseStarted?.() } - if (upgrade) { - header += `connection: upgrade\r\nupgrade: ${upgrade}\r\n` - } else if (client[kPipelining] && !socket[kReset]) { - header += 'connection: keep-alive\r\n' - } else { - header += 'connection: close\r\n' - } + onHeaders (statusCode, headers, resume, statusText) { + assert(!this.aborted) + assert(!this.completed) - if (Array.isArray(headers)) { - for (let n = 0; n < headers.length; n += 2) { - const key = headers[n + 0] - const val = headers[n + 1] + if (channels.headers.hasSubscribers) { + channels.headers.publish({ request: this, response: { statusCode, headers, statusText } }) + } - if (Array.isArray(val)) { - for (let i = 0; i < val.length; i++) { - header += `${key}: ${val[i]}\r\n` - } - } else { - header += `${key}: ${val}\r\n` - } + try { + return this[kHandler].onHeaders(statusCode, headers, resume, statusText) + } catch (err) { + this.abort(err) } } - if (channels.sendHeaders.hasSubscribers) { - channels.sendHeaders.publish({ request, headers: header, socket }) - } + onData (chunk) { + assert(!this.aborted) + assert(!this.completed) - if (!body || bodyLength === 0) { - writeBuffer(abort, null, client, request, socket, contentLength, header, expectsPayload) - } else if (util.isBuffer(body)) { - writeBuffer(abort, body, client, request, socket, contentLength, header, expectsPayload) - } else if (util.isBlobLike(body)) { - if (typeof body.stream === 'function') { - writeIterable(abort, body.stream(), client, request, socket, contentLength, header, expectsPayload) - } else { - writeBlob(abort, body, client, request, socket, contentLength, header, expectsPayload) + if (channels.bodyChunkReceived.hasSubscribers) { + channels.bodyChunkReceived.publish({ request: this, chunk }) + } + try { + return this[kHandler].onData(chunk) + } catch (err) { + this.abort(err) + return false } - } else if (util.isStream(body)) { - writeStream(abort, body, client, request, socket, contentLength, header, expectsPayload) - } else if (util.isIterable(body)) { - writeIterable(abort, body, client, request, socket, contentLength, header, expectsPayload) - } else { - assert(false) } - return true -} + onUpgrade (statusCode, headers, socket) { + assert(!this.aborted) + assert(!this.completed) -/** - * @param {AbortCallback} abort - * @param {import('stream').Stream} body - * @param {import('./client.js')} client - * @param {import('../core/request.js')} request - * @param {import('net').Socket} socket - * @param {number} contentLength - * @param {string} header - * @param {boolean} expectsPayload - */ -function writeStream (abort, body, client, request, socket, contentLength, header, expectsPayload) { - assert(contentLength !== 0 || client[kRunning] === 0, 'stream body cannot be pipelined') + return this[kHandler].onUpgrade(statusCode, headers, socket) + } - let finished = false + onComplete (trailers) { + this.onFinally() - const writer = new AsyncWriter({ abort, socket, request, contentLength, client, expectsPayload, header }) + assert(!this.aborted) + assert(!this.completed) - /** - * @param {Buffer} chunk - * @returns {void} - */ - const onData = function (chunk) { - if (finished) { - return + this.completed = true + if (channels.trailers.hasSubscribers) { + channels.trailers.publish({ request: this, trailers }) } try { - if (!writer.write(chunk) && this.pause) { - this.pause() - } + return this[kHandler].onComplete(trailers) } catch (err) { - util.destroy(this, err) + // TODO (fix): This might be a bad idea? + this.onError(err) } } - /** - * @returns {void} - */ - const onDrain = function () { - if (finished) { - return + onError (error) { + this.onFinally() + + if (channels.error.hasSubscribers) { + channels.error.publish({ request: this, error }) } - if (body.resume) { - body.resume() + if (this.aborted) { + return } - } + this.aborted = true - /** - * @returns {void} - */ - const onClose = function () { - // 'close' might be emitted *before* 'error' for - // broken streams. Wait a tick to avoid this case. - queueMicrotask(() => { - // It's only safe to remove 'error' listener after - // 'close'. - body.removeListener('error', onFinished) - }) + return this[kHandler].onError(error) + } - if (!finished) { - const err = new RequestAbortedError() - queueMicrotask(() => onFinished(err)) + onFinally () { + if (this.errorHandler) { + this.body.off('error', this.errorHandler) + this.errorHandler = null } - } - /** - * @param {Error} [err] - * @returns - */ - const onFinished = function (err) { - if (finished) { - return + if (this.endHandler) { + this.body.off('end', this.endHandler) + this.endHandler = null } + } - finished = true + addHeader (key, value) { + processHeader(this, key, value) + return this + } +} - assert(socket.destroyed || (socket[kWriting] && client[kRunning] <= 1)) +function processHeader (request, key, val) { + if (val && (typeof val === 'object' && !Array.isArray(val))) { + throw new InvalidArgumentError(`invalid ${key} header`) + } else if (val === undefined) { + return + } - socket - .off('drain', onDrain) - .off('error', onFinished) + let headerName = headerNameLowerCasedRecord[key] - body - .removeListener('data', onData) - .removeListener('end', onFinished) - .removeListener('close', onClose) + if (headerName === undefined) { + headerName = key.toLowerCase() + if (headerNameLowerCasedRecord[headerName] === undefined && !isValidHTTPToken(headerName)) { + throw new InvalidArgumentError('invalid header key') + } + } - if (!err) { - try { - writer.end() - } catch (er) { - err = er + if (Array.isArray(val)) { + const arr = [] + for (let i = 0; i < val.length; i++) { + if (typeof val[i] === 'string') { + if (!isValidHeaderValue(val[i])) { + throw new InvalidArgumentError(`invalid ${key} header`) + } + arr.push(val[i]) + } else if (val[i] === null) { + arr.push('') + } else if (typeof val[i] === 'object') { + throw new InvalidArgumentError(`invalid ${key} header`) + } else { + arr.push(`${val[i]}`) } } - - writer.destroy(err) - - if (err && (err.code !== 'UND_ERR_INFO' || err.message !== 'reset')) { - util.destroy(body, err) - } else { - util.destroy(body) + val = arr + } else if (typeof val === 'string') { + if (!isValidHeaderValue(val)) { + throw new InvalidArgumentError(`invalid ${key} header`) } + } else if (val === null) { + val = '' + } else { + val = `${val}` } - body - .on('data', onData) - .on('end', onFinished) - .on('error', onFinished) - .on('close', onClose) + if (request.host === null && headerName === 'host') { + if (typeof val !== 'string') { + throw new InvalidArgumentError('invalid host header') + } + // Consumed by Client + request.host = val + } else if (request.contentLength === null && headerName === 'content-length') { + request.contentLength = parseInt(val, 10) + if (!Number.isFinite(request.contentLength)) { + throw new InvalidArgumentError('invalid content-length header') + } + } else if (request.contentType === null && headerName === 'content-type') { + request.contentType = val + request.headers.push(key, val) + } else if (headerName === 'transfer-encoding' || headerName === 'keep-alive' || headerName === 'upgrade') { + throw new InvalidArgumentError(`invalid ${headerName} header`) + } else if (headerName === 'connection') { + const value = typeof val === 'string' ? val.toLowerCase() : null + if (value !== 'close' && value !== 'keep-alive') { + throw new InvalidArgumentError('invalid connection header') + } - if (body.resume) { - body.resume() + if (value === 'close') { + request.reset = true + } + } else if (headerName === 'expect') { + throw new NotSupportedError('expect header not supported') + } else { + request.headers.push(key, val) } +} - socket - .on('drain', onDrain) - .on('error', onFinished) +module.exports = Request - if (body.errorEmitted ?? body.errored) { - setImmediate(onFinished, body.errored) - } else if (body.endEmitted ?? body.readableEnded) { - setImmediate(onFinished, null) - } - if (body.closeEmitted ?? body.closed) { - setImmediate(onClose) - } -} +/***/ }), -/** - * @typedef AbortCallback - * @type {Function} - * @param {Error} [err] - * @returns {void} - */ +/***/ 8261: +/***/ ((module) => { -/** - * @param {AbortCallback} abort - * @param {Uint8Array|null} body - * @param {import('./client.js')} client - * @param {import('../core/request.js')} request - * @param {import('net').Socket} socket - * @param {number} contentLength - * @param {string} header - * @param {boolean} expectsPayload - * @returns {void} - */ -function writeBuffer (abort, body, client, request, socket, contentLength, header, expectsPayload) { - try { - if (!body) { - if (contentLength === 0) { - socket.write(`${header}content-length: 0\r\n\r\n`, 'latin1') - } else { - assert(contentLength === null, 'no body must not have content length') - socket.write(`${header}\r\n`, 'latin1') - } - } else if (util.isBuffer(body)) { - assert(contentLength === body.byteLength, 'buffer body must have content length') - socket.cork() - socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'latin1') - socket.write(body) - socket.uncork() - request.onBodySent(body) - - if (!expectsPayload && request.reset !== false) { - socket[kReset] = true - } - } - request.onRequestSent() - client[kResume]() - } catch (err) { - abort(err) - } +module.exports = { + kClose: Symbol('close'), + kDestroy: Symbol('destroy'), + kDispatch: Symbol('dispatch'), + kUrl: Symbol('url'), + kWriting: Symbol('writing'), + kResuming: Symbol('resuming'), + kQueue: Symbol('queue'), + kConnect: Symbol('connect'), + kConnecting: Symbol('connecting'), + kKeepAliveDefaultTimeout: Symbol('default keep alive timeout'), + kKeepAliveMaxTimeout: Symbol('max keep alive timeout'), + kKeepAliveTimeoutThreshold: Symbol('keep alive timeout threshold'), + kKeepAliveTimeoutValue: Symbol('keep alive timeout'), + kKeepAlive: Symbol('keep alive'), + kHeadersTimeout: Symbol('headers timeout'), + kBodyTimeout: Symbol('body timeout'), + kServerName: Symbol('server name'), + kLocalAddress: Symbol('local address'), + kHost: Symbol('host'), + kNoRef: Symbol('no ref'), + kBodyUsed: Symbol('used'), + kBody: Symbol('abstracted request body'), + kRunning: Symbol('running'), + kBlocking: Symbol('blocking'), + kPending: Symbol('pending'), + kSize: Symbol('size'), + kBusy: Symbol('busy'), + kQueued: Symbol('queued'), + kFree: Symbol('free'), + kConnected: Symbol('connected'), + kClosed: Symbol('closed'), + kNeedDrain: Symbol('need drain'), + kReset: Symbol('reset'), + kDestroyed: Symbol.for('nodejs.stream.destroyed'), + kResume: Symbol('resume'), + kOnError: Symbol('on error'), + kMaxHeadersSize: Symbol('max headers size'), + kRunningIdx: Symbol('running index'), + kPendingIdx: Symbol('pending index'), + kError: Symbol('error'), + kClients: Symbol('clients'), + kClient: Symbol('client'), + kParser: Symbol('parser'), + kOnDestroyed: Symbol('destroy callbacks'), + kPipelining: Symbol('pipelining'), + kSocket: Symbol('socket'), + kHostHeader: Symbol('host header'), + kConnector: Symbol('connector'), + kStrictContentLength: Symbol('strict content length'), + kMaxRedirections: Symbol('maxRedirections'), + kMaxRequests: Symbol('maxRequestsPerClient'), + kProxy: Symbol('proxy agent options'), + kCounter: Symbol('socket request counter'), + kMaxResponseSize: Symbol('max response size'), + kHTTP2Session: Symbol('http2Session'), + kHTTP2SessionState: Symbol('http2Session state'), + kRetryHandlerDefaultRetry: Symbol('retry agent default retry'), + kConstruct: Symbol('constructable'), + kListeners: Symbol('listeners'), + kHTTPContext: Symbol('http context'), + kMaxConcurrentStreams: Symbol('max concurrent streams'), + kHTTP2InitialWindowSize: Symbol('http2 initial window size'), + kHTTP2ConnectionWindowSize: Symbol('http2 connection window size'), + kEnableConnectProtocol: Symbol('http2session connect protocol'), + kRemoteSettings: Symbol('http2session remote settings'), + kHTTP2Stream: Symbol('http2session client stream'), + kNoProxyAgent: Symbol('no proxy agent'), + kHttpProxyAgent: Symbol('http proxy agent'), + kHttpsProxyAgent: Symbol('https proxy agent') } -/** - * @param {AbortCallback} abort - * @param {Blob} body - * @param {import('./client.js')} client - * @param {import('../core/request.js')} request - * @param {import('net').Socket} socket - * @param {number} contentLength - * @param {string} header - * @param {boolean} expectsPayload - * @returns {Promise} - */ -async function writeBlob (abort, body, client, request, socket, contentLength, header, expectsPayload) { - assert(contentLength === body.size, 'blob body must have content length') - - try { - if (contentLength != null && contentLength !== body.size) { - throw new RequestContentLengthMismatchError() - } - - const buffer = Buffer.from(await body.arrayBuffer()) - socket.cork() - socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'latin1') - socket.write(buffer) - socket.uncork() +/***/ }), - request.onBodySent(buffer) - request.onRequestSent() +/***/ 4650: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - if (!expectsPayload && request.reset !== false) { - socket[kReset] = true - } - client[kResume]() - } catch (err) { - abort(err) - } -} -/** - * @param {AbortCallback} abort - * @param {Iterable} body - * @param {import('./client.js')} client - * @param {import('../core/request.js')} request - * @param {import('net').Socket} socket - * @param {number} contentLength - * @param {string} header - * @param {boolean} expectsPayload - * @returns {Promise} - */ -async function writeIterable (abort, body, client, request, socket, contentLength, header, expectsPayload) { - assert(contentLength !== 0 || client[kRunning] === 0, 'iterator body cannot be pipelined') +const { + wellknownHeaderNames, + headerNameLowerCasedRecord +} = __nccwpck_require__(5337) - let callback = null - function onDrain () { - if (callback) { - const cb = callback - callback = null - cb() +class TstNode { + /** @type {any} */ + value = null + /** @type {null | TstNode} */ + left = null + /** @type {null | TstNode} */ + middle = null + /** @type {null | TstNode} */ + right = null + /** @type {number} */ + code + /** + * @param {string} key + * @param {any} value + * @param {number} index + */ + constructor (key, value, index) { + if (index === undefined || index >= key.length) { + throw new TypeError('Unreachable') } - } - - const waitForDrain = () => new Promise((resolve, reject) => { - assert(callback === null) - - if (socket[kError]) { - reject(socket[kError]) - } else { - callback = resolve + const code = this.code = key.charCodeAt(index) + // check code is ascii string + if (code > 0x7F) { + throw new TypeError('key must be ascii string') } - }) - - socket - .on('close', onDrain) - .on('drain', onDrain) - - const writer = new AsyncWriter({ abort, socket, request, contentLength, client, expectsPayload, header }) - try { - // It's up to the user to somehow abort the async iterable. - for await (const chunk of body) { - if (socket[kError]) { - throw socket[kError] - } - - if (!writer.write(chunk)) { - await waitForDrain() - } + if (key.length !== ++index) { + this.middle = new TstNode(key, value, index) + } else { + this.value = value } - - writer.end() - } catch (err) { - writer.destroy(err) - } finally { - socket - .off('close', onDrain) - .off('drain', onDrain) - } -} - -class AsyncWriter { - /** - * - * @param {object} arg - * @param {AbortCallback} arg.abort - * @param {import('net').Socket} arg.socket - * @param {import('../core/request.js')} arg.request - * @param {number} arg.contentLength - * @param {import('./client.js')} arg.client - * @param {boolean} arg.expectsPayload - * @param {string} arg.header - */ - constructor ({ abort, socket, request, contentLength, client, expectsPayload, header }) { - this.socket = socket - this.request = request - this.contentLength = contentLength - this.client = client - this.bytesWritten = 0 - this.expectsPayload = expectsPayload - this.header = header - this.abort = abort - - socket[kWriting] = true } /** - * @param {Buffer} chunk - * @returns + * @param {string} key + * @param {any} value + * @returns {void} */ - write (chunk) { - const { socket, request, contentLength, client, bytesWritten, expectsPayload, header } = this - - if (socket[kError]) { - throw socket[kError] - } - - if (socket.destroyed) { - return false - } - - const len = Buffer.byteLength(chunk) - if (!len) { - return true - } - - // We should defer writing chunks. - if (contentLength !== null && bytesWritten + len > contentLength) { - if (client[kStrictContentLength]) { - throw new RequestContentLengthMismatchError() - } - - process.emitWarning(new RequestContentLengthMismatchError()) + add (key, value) { + const length = key.length + if (length === 0) { + throw new TypeError('Unreachable') } - - socket.cork() - - if (bytesWritten === 0) { - if (!expectsPayload && request.reset !== false) { - socket[kReset] = true - } - - if (contentLength === null) { - socket.write(`${header}transfer-encoding: chunked\r\n`, 'latin1') - } else { - socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'latin1') + let index = 0 + /** + * @type {TstNode} + */ + let node = this + while (true) { + const code = key.charCodeAt(index) + // check code is ascii string + if (code > 0x7F) { + throw new TypeError('key must be ascii string') } - } - - if (contentLength === null) { - socket.write(`\r\n${len.toString(16)}\r\n`, 'latin1') - } - - this.bytesWritten += len - - const ret = socket.write(chunk) - - socket.uncork() - - request.onBodySent(chunk) - - if (!ret) { - if (socket[kParser].timeout && socket[kParser].timeoutType === TIMEOUT_HEADERS) { - if (socket[kParser].timeout.refresh) { - socket[kParser].timeout.refresh() + if (node.code === code) { + if (length === ++index) { + node.value = value + break + } else if (node.middle !== null) { + node = node.middle + } else { + node.middle = new TstNode(key, value, index) + break + } + } else if (node.code < code) { + if (node.left !== null) { + node = node.left + } else { + node.left = new TstNode(key, value, index) + break } + } else if (node.right !== null) { + node = node.right + } else { + node.right = new TstNode(key, value, index) + break } } - - return ret } /** - * @returns {void} + * @param {Uint8Array} key + * @returns {TstNode | null} */ - end () { - const { socket, contentLength, client, bytesWritten, expectsPayload, header, request } = this - request.onRequestSent() - - socket[kWriting] = false - - if (socket[kError]) { - throw socket[kError] - } - - if (socket.destroyed) { - return - } - - if (bytesWritten === 0) { - if (expectsPayload) { - // https://tools.ietf.org/html/rfc7230#section-3.3.2 - // A user agent SHOULD send a Content-Length in a request message when - // no Transfer-Encoding is sent and the request method defines a meaning - // for an enclosed payload body. - - socket.write(`${header}content-length: 0\r\n\r\n`, 'latin1') - } else { - socket.write(`${header}\r\n`, 'latin1') + search (key) { + const keylength = key.length + let index = 0 + /** + * @type {TstNode|null} + */ + let node = this + while (node !== null && index < keylength) { + let code = key[index] + // A-Z + // First check if it is bigger than 0x5a. + // Lowercase letters have higher char codes than uppercase ones. + // Also we assume that headers will mostly contain lowercase characters. + if (code <= 0x5a && code >= 0x41) { + // Lowercase for uppercase. + code |= 32 } - } else if (contentLength === null) { - socket.write('\r\n0\r\n\r\n', 'latin1') - } - - if (contentLength !== null && bytesWritten !== contentLength) { - if (client[kStrictContentLength]) { - throw new RequestContentLengthMismatchError() - } else { - process.emitWarning(new RequestContentLengthMismatchError()) + while (node !== null) { + if (code === node.code) { + if (keylength === ++index) { + // Returns Node since it is the last key. + return node + } + node = node.middle + break + } + node = node.code < code ? node.left : node.right } } + return null + } +} - if (socket[kParser].timeout && socket[kParser].timeoutType === TIMEOUT_HEADERS) { - if (socket[kParser].timeout.refresh) { - socket[kParser].timeout.refresh() - } - } +class TernarySearchTree { + /** @type {TstNode | null} */ + node = null - client[kResume]() + /** + * @param {string} key + * @param {any} value + * @returns {void} + * */ + insert (key, value) { + if (this.node === null) { + this.node = new TstNode(key, value, 0) + } else { + this.node.add(key, value) + } } /** - * @param {Error} [err] - * @returns {void} + * @param {Uint8Array} key + * @returns {any} */ - destroy (err) { - const { socket, client, abort } = this + lookup (key) { + return this.node?.search(key)?.value ?? null + } +} - socket[kWriting] = false +const tree = new TernarySearchTree() - if (err) { - assert(client[kRunning] <= 1, 'pipeline should only contain this request') - abort(err) - } - } +for (let i = 0; i < wellknownHeaderNames.length; ++i) { + const key = headerNameLowerCasedRecord[wellknownHeaderNames[i]] + tree.insert(key, key) } -module.exports = connectH1 +module.exports = { + TernarySearchTree, + tree +} /***/ }), -/***/ 9181: +/***/ 2550: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; const assert = __nccwpck_require__(4589) -const { pipeline } = __nccwpck_require__(7075) -const util = __nccwpck_require__(983) -const { - RequestContentLengthMismatchError, - RequestAbortedError, - SocketError, - InformationalError, - InvalidArgumentError -} = __nccwpck_require__(4928) -const { - kUrl, - kReset, - kClient, - kRunning, - kPending, - kQueue, - kPendingIdx, - kRunningIdx, - kError, - kSocket, - kStrictContentLength, - kOnError, - kMaxConcurrentStreams, - kHTTP2Session, - kHTTP2InitialWindowSize, - kHTTP2ConnectionWindowSize, - kResume, - kSize, - kHTTPContext, - kClosed, - kBodyTimeout, - kEnableConnectProtocol, - kRemoteSettings, - kHTTP2Stream -} = __nccwpck_require__(9562) -const { channels } = __nccwpck_require__(6591) - -const kOpenStreams = Symbol('open streams') +const { kDestroyed, kBodyUsed, kListeners, kBody } = __nccwpck_require__(8261) +const { IncomingMessage } = __nccwpck_require__(7067) +const stream = __nccwpck_require__(7075) +const net = __nccwpck_require__(7030) +const { stringify } = __nccwpck_require__(1792) +const { EventEmitter: EE } = __nccwpck_require__(8474) +const timers = __nccwpck_require__(8621) +const { InvalidArgumentError, ConnectTimeoutError } = __nccwpck_require__(5093) +const { headerNameLowerCasedRecord } = __nccwpck_require__(5337) +const { tree } = __nccwpck_require__(4650) -let extractBody +const [nodeMajor, nodeMinor] = process.versions.node.split('.', 2).map(v => Number(v)) -/** @type {import('http2')} */ -let http2 -try { - http2 = __nccwpck_require__(2467) -} catch { - // @ts-ignore - http2 = { constants: {} } -} +class BodyAsyncIterable { + constructor (body) { + this[kBody] = body + this[kBodyUsed] = false + } -const { - constants: { - HTTP2_HEADER_AUTHORITY, - HTTP2_HEADER_METHOD, - HTTP2_HEADER_PATH, - HTTP2_HEADER_SCHEME, - HTTP2_HEADER_CONTENT_LENGTH, - HTTP2_HEADER_EXPECT, - HTTP2_HEADER_STATUS, - HTTP2_HEADER_PROTOCOL, - NGHTTP2_REFUSED_STREAM, - NGHTTP2_CANCEL + async * [Symbol.asyncIterator] () { + assert(!this[kBodyUsed], 'disturbed') + this[kBodyUsed] = true + yield * this[kBody] } -} = http2 +} -function parseH2Headers (headers) { - const result = [] +function noop () {} - for (const [name, value] of Object.entries(headers)) { - // h2 may concat the header value by array - // e.g. Set-Cookie - if (Array.isArray(value)) { - for (const subvalue of value) { - // we need to provide each header value of header name - // because the headers handler expect name-value pair - result.push(Buffer.from(name), Buffer.from(subvalue)) - } - } else { - result.push(Buffer.from(name), Buffer.from(value)) +/** + * @param {*} body + * @returns {*} + */ +function wrapRequestBody (body) { + if (isStream(body)) { + // TODO (fix): Provide some way for the user to cache the file to e.g. /tmp + // so that it can be dispatched again? + // TODO (fix): Do we need 100-expect support to provide a way to do this properly? + if (bodyLength(body) === 0) { + body + .on('data', function () { + assert(false) + }) } - } - - return result -} - -function connectH2 (client, socket) { - client[kSocket] = socket - - const http2InitialWindowSize = client[kHTTP2InitialWindowSize] - const http2ConnectionWindowSize = client[kHTTP2ConnectionWindowSize] - const session = http2.connect(client[kUrl], { - createConnection: () => socket, - peerMaxConcurrentStreams: client[kMaxConcurrentStreams], - settings: { - // TODO(metcoder95): add support for PUSH - enablePush: false, - ...(http2InitialWindowSize != null ? { initialWindowSize: http2InitialWindowSize } : null) + if (typeof body.readableDidRead !== 'boolean') { + body[kBodyUsed] = false + EE.prototype.on.call(body, 'data', function () { + this[kBodyUsed] = true + }) } - }) - - session[kOpenStreams] = 0 - session[kClient] = client - session[kSocket] = socket - session[kHTTP2Session] = null - // We set it to true by default in a best-effort; however once connected to an H2 server - // we will check if extended CONNECT protocol is supported or not - // and set this value accordingly. - session[kEnableConnectProtocol] = false - // States whether or not we have received the remote settings from the server - session[kRemoteSettings] = false - // Apply connection-level flow control once connected (if supported). - if (http2ConnectionWindowSize) { - util.addListener(session, 'connect', applyConnectionWindowSize.bind(session, http2ConnectionWindowSize)) + return body + } else if (body && typeof body.pipeTo === 'function') { + // TODO (fix): We can't access ReadableStream internal state + // to determine whether or not it has been disturbed. This is just + // a workaround. + return new BodyAsyncIterable(body) + } else if (body && isFormDataLike(body)) { + return body + } else if ( + body && + typeof body !== 'string' && + !ArrayBuffer.isView(body) && + isIterable(body) + ) { + // TODO: Should we allow re-using iterable if !this.opts.idempotent + // or through some other flag? + return new BodyAsyncIterable(body) + } else { + return body } +} - util.addListener(session, 'error', onHttp2SessionError) - util.addListener(session, 'frameError', onHttp2FrameError) - util.addListener(session, 'end', onHttp2SessionEnd) - util.addListener(session, 'goaway', onHttp2SessionGoAway) - util.addListener(session, 'close', onHttp2SessionClose) - util.addListener(session, 'remoteSettings', onHttp2RemoteSettings) - // TODO (@metcoder95): implement SETTINGS support - // util.addListener(session, 'localSettings', onHttp2RemoteSettings) - - session.unref() - - client[kHTTP2Session] = session - socket[kHTTP2Session] = session - - util.addListener(socket, 'error', onHttp2SocketError) - util.addListener(socket, 'end', onHttp2SocketEnd) - util.addListener(socket, 'close', onHttp2SocketClose) - - socket[kClosed] = false - socket.on('close', onSocketClose) - - return { - version: 'h2', - defaultPipelining: Infinity, - /** - * @param {import('../core/request.js')} request - * @returns {boolean} - */ - write (request) { - return writeH2(client, request) - }, - /** - * @returns {void} - */ - resume () { - resumeH2(client) - }, - /** - * @param {Error | null} err - * @param {() => void} callback - */ - destroy (err, callback) { - if (socket[kClosed]) { - queueMicrotask(callback) - } else { - socket.destroy(err).on('close', callback) - } - }, - /** - * @type {boolean} - */ - get destroyed () { - return socket.destroyed - }, - /** - * @param {import('../core/request.js')} request - * @returns {boolean} - */ - busy (request) { - if (request != null) { - if (client[kRunning] > 0) { - // We are already processing requests - - // Non-idempotent request cannot be retried. - // Ensure that no other requests are inflight and - // could cause failure. - if (request.idempotent === false) return true - // Don't dispatch an upgrade until all preceding requests have completed. - // Possibly, we do not have remote settings confirmed yet. - if ((request.upgrade === 'websocket' || request.method === 'CONNECT') && session[kRemoteSettings] === false) return true - // Request with stream or iterator body can error while other requests - // are inflight and indirectly error those as well. - // Ensure this doesn't happen by waiting for inflight - // to complete before dispatching. - - // Request with stream or iterator body cannot be retried. - // Ensure that no other requests are inflight and - // could cause failure. - if (util.bodyLength(request.body) !== 0 && - (util.isStream(request.body) || util.isAsyncIterable(request.body) || util.isFormDataLike(request.body))) return true - } else { - return (request.upgrade === 'websocket' || request.method === 'CONNECT') && session[kRemoteSettings] === false - } - } - - return false - } - } +/** + * @param {*} obj + * @returns {obj is import('node:stream').Stream} + */ +function isStream (obj) { + return obj && typeof obj === 'object' && typeof obj.pipe === 'function' && typeof obj.on === 'function' } -function resumeH2 (client) { - const socket = client[kSocket] +/** + * @param {*} object + * @returns {object is Blob} + * based on https://github.com/node-fetch/fetch-blob/blob/8ab587d34080de94140b54f07168451e7d0b655e/index.js#L229-L241 (MIT License) + */ +function isBlobLike (object) { + if (object === null) { + return false + } else if (object instanceof Blob) { + return true + } else if (typeof object !== 'object') { + return false + } else { + const sTag = object[Symbol.toStringTag] - if (socket?.destroyed === false) { - if (client[kSize] === 0 || client[kMaxConcurrentStreams] === 0) { - socket.unref() - client[kHTTP2Session].unref() - } else { - socket.ref() - client[kHTTP2Session].ref() - } + return (sTag === 'Blob' || sTag === 'File') && ( + ('stream' in object && typeof object.stream === 'function') || + ('arrayBuffer' in object && typeof object.arrayBuffer === 'function') + ) } } -function applyConnectionWindowSize (connectionWindowSize) { - try { - if (typeof this.setLocalWindowSize === 'function') { - this.setLocalWindowSize(connectionWindowSize) - } - } catch { - // Best-effort only. - } +/** + * @param {string} url The path to check for query strings or fragments. + * @returns {boolean} Returns true if the path contains a query string or fragment. + */ +function pathHasQueryOrFragment (url) { + return ( + url.includes('?') || + url.includes('#') + ) } -function onHttp2RemoteSettings (settings) { - // Fallbacks are a safe bet, remote setting will always override - this[kClient][kMaxConcurrentStreams] = settings.maxConcurrentStreams ?? this[kClient][kMaxConcurrentStreams] - /** - * From RFC-8441 - * A sender MUST NOT send a SETTINGS_ENABLE_CONNECT_PROTOCOL parameter - * with the value of 0 after previously sending a value of 1. - */ - // Note: Cannot be tested in Node, it does not supports disabling the extended CONNECT protocol once enabled - if (this[kRemoteSettings] === true && this[kEnableConnectProtocol] === true && settings.enableConnectProtocol === false) { - const err = new InformationalError('HTTP/2: Server disabled extended CONNECT protocol against RFC-8441') - this[kSocket][kError] = err - this[kClient][kOnError](err) - return +/** + * @param {string} url The URL to add the query params to + * @param {import('node:querystring').ParsedUrlQueryInput} queryParams The object to serialize into a URL query string + * @returns {string} The URL with the query params added + */ +function serializePathWithQuery (url, queryParams) { + if (pathHasQueryOrFragment(url)) { + throw new Error('Query params cannot be passed when url already contains "?" or "#".') } - this[kEnableConnectProtocol] = settings.enableConnectProtocol ?? this[kEnableConnectProtocol] - this[kRemoteSettings] = true - this[kClient][kResume]() -} - -function onHttp2SessionError (err) { - assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID') - - this[kSocket][kError] = err - this[kClient][kOnError](err) -} + const stringified = stringify(queryParams) -function onHttp2FrameError (type, code, id) { - if (id === 0) { - const err = new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`) - this[kSocket][kError] = err - this[kClient][kOnError](err) + if (stringified) { + url += '?' + stringified } + + return url } -function onHttp2SessionEnd () { - const err = new SocketError('other side closed', util.getSocketInfo(this[kSocket])) - this.destroy(err) - util.destroy(this[kSocket], err) +/** + * @param {number|string|undefined} port + * @returns {boolean} + */ +function isValidPort (port) { + const value = parseInt(port, 10) + return ( + value === Number(port) && + value >= 0 && + value <= 65535 + ) } /** - * This is the root cause of #3011 - * We need to handle GOAWAY frames properly, and trigger the session close - * along with the socket right away + * Check if the value is a valid http or https prefixed string. * - * @this {import('http2').ClientHttp2Session} - * @param {number} errorCode + * @param {string} value + * @returns {boolean} */ -function onHttp2SessionGoAway (errorCode) { - // TODO(mcollina): Verify if GOAWAY implements the spec correctly: - // https://datatracker.ietf.org/doc/html/rfc7540#section-6.8 - // Specifically, we do not verify the "valid" stream id. - - const err = this[kError] || new SocketError(`HTTP/2: "GOAWAY" frame received with code ${errorCode}`, util.getSocketInfo(this[kSocket])) - const client = this[kClient] +function isHttpOrHttpsPrefixed (value) { + return ( + value != null && + value[0] === 'h' && + value[1] === 't' && + value[2] === 't' && + value[3] === 'p' && + ( + value[4] === ':' || + ( + value[4] === 's' && + value[5] === ':' + ) + ) + ) +} - client[kSocket] = null - client[kHTTPContext] = null +/** + * @param {string|URL|Record} url + * @returns {URL} + */ +function parseURL (url) { + if (typeof url === 'string') { + /** + * @type {URL} + */ + url = new URL(url) - // this is an HTTP2 session - this.close() - this[kHTTP2Session] = null + if (!isHttpOrHttpsPrefixed(url.origin || url.protocol)) { + throw new InvalidArgumentError('Invalid URL protocol: the URL must start with `http:` or `https:`.') + } - util.destroy(this[kSocket], err) + return url + } - // Fail head of pipeline. - if (client[kRunningIdx] < client[kQueue].length) { - const request = client[kQueue][client[kRunningIdx]] - client[kQueue][client[kRunningIdx]++] = null - util.errorRequest(client, request, err) - client[kPendingIdx] = client[kRunningIdx] + if (!url || typeof url !== 'object') { + throw new InvalidArgumentError('Invalid URL: The URL argument must be a non-null object.') } - assert(client[kRunning] === 0) + if (!(url instanceof URL)) { + if (url.port != null && url.port !== '' && isValidPort(url.port) === false) { + throw new InvalidArgumentError('Invalid URL: port must be a valid integer or a string representation of an integer.') + } - client.emit('disconnect', client[kUrl], [client], err) - client.emit('connectionError', client[kUrl], [client], err) + if (url.path != null && typeof url.path !== 'string') { + throw new InvalidArgumentError('Invalid URL path: the path must be a string or null/undefined.') + } - client[kResume]() -} + if (url.pathname != null && typeof url.pathname !== 'string') { + throw new InvalidArgumentError('Invalid URL pathname: the pathname must be a string or null/undefined.') + } -function onHttp2SessionClose () { - const { [kClient]: client } = this - const { [kSocket]: socket } = client + if (url.hostname != null && typeof url.hostname !== 'string') { + throw new InvalidArgumentError('Invalid URL hostname: the hostname must be a string or null/undefined.') + } - const err = this[kSocket][kError] || this[kError] || new SocketError('closed', util.getSocketInfo(socket)) + if (url.origin != null && typeof url.origin !== 'string') { + throw new InvalidArgumentError('Invalid URL origin: the origin must be a string or null/undefined.') + } - client[kSocket] = null - client[kHTTPContext] = null + if (!isHttpOrHttpsPrefixed(url.origin || url.protocol)) { + throw new InvalidArgumentError('Invalid URL protocol: the URL must start with `http:` or `https:`.') + } - if (client.destroyed) { - assert(client[kPending] === 0) + const port = url.port != null + ? url.port + : (url.protocol === 'https:' ? 443 : 80) + let origin = url.origin != null + ? url.origin + : `${url.protocol || ''}//${url.hostname || ''}:${port}` + let path = url.path != null + ? url.path + : `${url.pathname || ''}${url.search || ''}` - // Fail entire queue. - const requests = client[kQueue].splice(client[kRunningIdx]) - for (let i = 0; i < requests.length; i++) { - const request = requests[i] - util.errorRequest(client, request, err) + if (origin[origin.length - 1] === '/') { + origin = origin.slice(0, origin.length - 1) + } + + if (path && path[0] !== '/') { + path = `/${path}` } + // new URL(path, origin) is unsafe when `path` contains an absolute URL + // From https://developer.mozilla.org/en-US/docs/Web/API/URL/URL: + // If first parameter is a relative URL, second param is required, and will be used as the base URL. + // If first parameter is an absolute URL, a given second param will be ignored. + return new URL(`${origin}${path}`) } -} -function onHttp2SocketClose () { - const err = this[kError] || new SocketError('closed', util.getSocketInfo(this)) + if (!isHttpOrHttpsPrefixed(url.origin || url.protocol)) { + throw new InvalidArgumentError('Invalid URL protocol: the URL must start with `http:` or `https:`.') + } - const client = this[kHTTP2Session][kClient] + return url +} - client[kSocket] = null - client[kHTTPContext] = null +/** + * @param {string|URL|Record} url + * @returns {URL} + */ +function parseOrigin (url) { + url = parseURL(url) - if (this[kHTTP2Session] !== null) { - this[kHTTP2Session].destroy(err) + if (url.pathname !== '/' || url.search || url.hash) { + throw new InvalidArgumentError('invalid url') } - client[kPendingIdx] = client[kRunningIdx] + return url +} - assert(client[kRunning] === 0) +/** + * @param {string} host + * @returns {string} + */ +function getHostname (host) { + if (host[0] === '[') { + const idx = host.indexOf(']') - client.emit('disconnect', client[kUrl], [client], err) + assert(idx !== -1) + return host.substring(1, idx) + } - client[kResume]() + const idx = host.indexOf(':') + if (idx === -1) return host + + return host.substring(0, idx) } -function onHttp2SocketError (err) { - assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID') +/** + * IP addresses are not valid server names per RFC6066 + * Currently, the only server names supported are DNS hostnames + * @param {string|null} host + * @returns {string|null} + */ +function getServerName (host) { + if (!host) { + return null + } - this[kError] = err + assert(typeof host === 'string') - this[kClient][kOnError](err) -} + const servername = getHostname(host) + if (net.isIP(servername)) { + return '' + } -function onHttp2SocketEnd () { - util.destroy(this, new SocketError('other side closed', util.getSocketInfo(this))) + return servername } -function onSocketClose () { - this[kClosed] = true +/** + * @function + * @template T + * @param {T} obj + * @returns {T} + */ +function deepClone (obj) { + return JSON.parse(JSON.stringify(obj)) } -// https://www.rfc-editor.org/rfc/rfc7230#section-3.3.2 -function shouldSendContentLength (method) { - return method !== 'GET' && method !== 'HEAD' && method !== 'OPTIONS' && method !== 'TRACE' && method !== 'CONNECT' +/** + * @param {*} obj + * @returns {obj is AsyncIterable} + */ +function isAsyncIterable (obj) { + return !!(obj != null && typeof obj[Symbol.asyncIterator] === 'function') } -function writeH2 (client, request) { - const requestTimeout = request.bodyTimeout ?? client[kBodyTimeout] - const session = client[kHTTP2Session] - const { method, path, host, upgrade, expectContinue, signal, protocol, headers: reqHeaders } = request - let { body } = request +/** + * @param {*} obj + * @returns {obj is Iterable} + */ +function isIterable (obj) { + return !!(obj != null && (typeof obj[Symbol.iterator] === 'function' || typeof obj[Symbol.asyncIterator] === 'function')) +} - if (upgrade != null && upgrade !== 'websocket') { - util.errorRequest(client, request, new InvalidArgumentError(`Custom upgrade "${upgrade}" not supported over HTTP/2`)) - return false +/** + * @param {Blob|Buffer|import ('stream').Stream} body + * @returns {number|null} + */ +function bodyLength (body) { + if (body == null) { + return 0 + } else if (isStream(body)) { + const state = body._readableState + return state && state.objectMode === false && state.ended === true && Number.isFinite(state.length) + ? state.length + : null + } else if (isBlobLike(body)) { + return body.size != null ? body.size : null + } else if (isBuffer(body)) { + return body.byteLength } - const headers = {} - for (let n = 0; n < reqHeaders.length; n += 2) { - const key = reqHeaders[n + 0] - const val = reqHeaders[n + 1] + return null +} - if (key === 'cookie') { - if (headers[key] != null) { - headers[key] = Array.isArray(headers[key]) ? (headers[key].push(val), headers[key]) : [headers[key], val] - } else { - headers[key] = val - } - - continue - } +/** + * @param {import ('stream').Stream} body + * @returns {boolean} + */ +function isDestroyed (body) { + return body && !!(body.destroyed || body[kDestroyed] || (stream.isDestroyed?.(body))) +} - if (Array.isArray(val)) { - for (let i = 0; i < val.length; i++) { - if (headers[key]) { - headers[key] += `, ${val[i]}` - } else { - headers[key] = val[i] - } - } - } else if (headers[key]) { - headers[key] += `, ${val}` - } else { - headers[key] = val - } +/** + * @param {import ('stream').Stream} stream + * @param {Error} [err] + * @returns {void} + */ +function destroy (stream, err) { + if (stream == null || !isStream(stream) || isDestroyed(stream)) { + return } - /** @type {import('node:http2').ClientHttp2Stream} */ - let stream = null - - const { hostname, port } = client[kUrl] - - headers[HTTP2_HEADER_AUTHORITY] = host || `${hostname}${port ? `:${port}` : ''}` - headers[HTTP2_HEADER_METHOD] = method - - const abort = (err) => { - if (request.aborted || request.completed) { - return - } - - err = err || new RequestAbortedError() - - util.errorRequest(client, request, err) - - if (stream != null) { - // Some chunks might still come after abort, - // let's ignore them - stream.removeAllListeners('data') - - // On Abort, we close the stream to send RST_STREAM frame - stream.close() - - // We move the running index to the next request - client[kOnError](err) - client[kResume]() + if (typeof stream.destroy === 'function') { + if (Object.getPrototypeOf(stream).constructor === IncomingMessage) { + // See: https://github.com/nodejs/node/pull/38505/files + stream.socket = null } - // We do not destroy the socket as we can continue using the session - // the stream gets destroyed and the session remains to create new streams - util.destroy(body, err) + stream.destroy(err) + } else if (err) { + queueMicrotask(() => { + stream.emit('error', err) + }) } - try { - // We are already connected, streams are pending. - // We can call on connect, and wait for abort - request.onConnect(abort) - } catch (err) { - util.errorRequest(client, request, err) + if (stream.destroyed !== true) { + stream[kDestroyed] = true } +} - if (request.aborted) { - return false - } +const KEEPALIVE_TIMEOUT_EXPR = /timeout=(\d+)/ +/** + * @param {string} val + * @returns {number | null} + */ +function parseKeepAliveTimeout (val) { + const m = val.match(KEEPALIVE_TIMEOUT_EXPR) + return m ? parseInt(m[1], 10) * 1000 : null +} - if (upgrade || method === 'CONNECT') { - session.ref() +/** + * Retrieves a header name and returns its lowercase value. + * @param {string | Buffer} value Header name + * @returns {string} + */ +function headerNameToString (value) { + return typeof value === 'string' + ? headerNameLowerCasedRecord[value] ?? value.toLowerCase() + : tree.lookup(value) ?? value.toString('latin1').toLowerCase() +} - if (upgrade === 'websocket') { - // We cannot upgrade to websocket if extended CONNECT protocol is not supported - if (session[kEnableConnectProtocol] === false) { - util.errorRequest(client, request, new InformationalError('HTTP/2: Extended CONNECT protocol not supported by server')) - session.unref() - return false - } +/** + * Receive the buffer as a string and return its lowercase value. + * @param {Buffer} value Header name + * @returns {string} + */ +function bufferToLowerCasedHeaderName (value) { + return tree.lookup(value) ?? value.toString('latin1').toLowerCase() +} - // We force the method to CONNECT - // as per RFC-8441 - // https://datatracker.ietf.org/doc/html/rfc8441#section-4 - headers[HTTP2_HEADER_METHOD] = 'CONNECT' - headers[HTTP2_HEADER_PROTOCOL] = 'websocket' - // :path and :scheme headers must be omitted when sending CONNECT but set if extended-CONNECT - headers[HTTP2_HEADER_PATH] = path +/** + * @param {(Buffer | string)[]} headers + * @param {Record} [obj] + * @returns {Record} + */ +function parseHeaders (headers, obj) { + if (obj === undefined) obj = {} - if (protocol === 'ws:' || protocol === 'wss:') { - headers[HTTP2_HEADER_SCHEME] = protocol === 'ws:' ? 'http' : 'https' + for (let i = 0; i < headers.length; i += 2) { + const key = headerNameToString(headers[i]) + let val = obj[key] + + if (val) { + if (typeof val === 'string') { + val = [val] + obj[key] = val + } + val.push(headers[i + 1].toString('latin1')) + } else { + const headersValue = headers[i + 1] + if (typeof headersValue === 'string') { + obj[key] = headersValue } else { - headers[HTTP2_HEADER_SCHEME] = protocol === 'http:' ? 'http' : 'https' + obj[key] = Array.isArray(headersValue) ? headersValue.map(x => x.toString('latin1')) : headersValue.toString('latin1') } - - stream = session.request(headers, { endStream: false, signal }) - stream[kHTTP2Stream] = true - - stream.once('response', (headers, _flags) => { - const { [HTTP2_HEADER_STATUS]: statusCode, ...realHeaders } = headers - - request.onUpgrade(statusCode, parseH2Headers(realHeaders), stream) - - ++session[kOpenStreams] - client[kQueue][client[kRunningIdx]++] = null - }) - - stream.on('error', () => { - if (stream.rstCode === NGHTTP2_REFUSED_STREAM || stream.rstCode === NGHTTP2_CANCEL) { - // NGHTTP2_REFUSED_STREAM (7) or NGHTTP2_CANCEL (8) - // We do not treat those as errors as the server might - // not support websockets and refuse the stream - abort(new InformationalError(`HTTP/2: "stream error" received - code ${stream.rstCode}`)) - } - }) - - stream.once('close', () => { - session[kOpenStreams] -= 1 - if (session[kOpenStreams] === 0) session.unref() - }) - - stream.setTimeout(requestTimeout) - return true } + } - // TODO: consolidate once we support CONNECT properly - // NOTE: We are already connected, streams are pending, first request - // will create a new stream. We trigger a request to create the stream and wait until - // `ready` event is triggered - // We disabled endStream to allow the user to write to the stream - stream = session.request(headers, { endStream: false, signal }) - stream[kHTTP2Stream] = true - stream.on('response', headers => { - const { [HTTP2_HEADER_STATUS]: statusCode, ...realHeaders } = headers + return obj +} - request.onUpgrade(statusCode, parseH2Headers(realHeaders), stream) - ++session[kOpenStreams] - client[kQueue][client[kRunningIdx]++] = null - }) - stream.once('close', () => { - session[kOpenStreams] -= 1 - if (session[kOpenStreams] === 0) session.unref() - }) - stream.setTimeout(requestTimeout) +/** + * @param {Buffer[]} headers + * @returns {string[]} + */ +function parseRawHeaders (headers) { + const headersLength = headers.length + /** + * @type {string[]} + */ + const ret = new Array(headersLength) - return true - } + let key + let val - // https://tools.ietf.org/html/rfc7540#section-8.3 - // :path and :scheme headers must be omitted when sending CONNECT - headers[HTTP2_HEADER_PATH] = path - headers[HTTP2_HEADER_SCHEME] = protocol === 'http:' ? 'http' : 'https' + for (let n = 0; n < headersLength; n += 2) { + key = headers[n] + val = headers[n + 1] - // https://tools.ietf.org/html/rfc7231#section-4.3.1 - // https://tools.ietf.org/html/rfc7231#section-4.3.2 - // https://tools.ietf.org/html/rfc7231#section-4.3.5 + typeof key !== 'string' && (key = key.toString()) + typeof val !== 'string' && (val = val.toString('latin1')) - // Sending a payload body on a request that does not - // expect it can cause undefined behavior on some - // servers and corrupt connection state. Do not - // re-use the connection for further requests. + ret[n] = key + ret[n + 1] = val + } - const expectsPayload = ( - method === 'PUT' || - method === 'POST' || - method === 'PATCH' - ) + return ret +} - if (body && typeof body.read === 'function') { - // Try to read EOF in order to get length. - body.read(0) +/** + * @param {string[]} headers + * @param {Buffer[]} headers + */ +function encodeRawHeaders (headers) { + if (!Array.isArray(headers)) { + throw new TypeError('expected headers to be an array') } + return headers.map(x => Buffer.from(x)) +} - let contentLength = util.bodyLength(body) +/** + * @param {*} buffer + * @returns {buffer is Buffer} + */ +function isBuffer (buffer) { + // See, https://github.com/mcollina/undici/pull/319 + return buffer instanceof Uint8Array || Buffer.isBuffer(buffer) +} - if (util.isFormDataLike(body)) { - extractBody ??= (__nccwpck_require__(2921).extractBody) +/** + * Asserts that the handler object is a request handler. + * + * @param {object} handler + * @param {string} method + * @param {string} [upgrade] + * @returns {asserts handler is import('../api/api-request').RequestHandler} + */ +function assertRequestHandler (handler, method, upgrade) { + if (!handler || typeof handler !== 'object') { + throw new InvalidArgumentError('handler must be an object') + } - const [bodyStream, contentType] = extractBody(body) - headers['content-type'] = contentType + if (typeof handler.onRequestStart === 'function') { + // TODO (fix): More checks... + return + } - body = bodyStream.stream - contentLength = bodyStream.length + if (typeof handler.onConnect !== 'function') { + throw new InvalidArgumentError('invalid onConnect method') } - if (contentLength == null) { - contentLength = request.contentLength + if (typeof handler.onError !== 'function') { + throw new InvalidArgumentError('invalid onError method') } - if (!expectsPayload) { - // https://tools.ietf.org/html/rfc7230#section-3.3.2 - // A user agent SHOULD NOT send a Content-Length header field when - // the request message does not contain a payload body and the method - // semantics do not anticipate such a body. - // And for methods that don't expect a payload, omit Content-Length. - contentLength = null + if (typeof handler.onBodySent !== 'function' && handler.onBodySent !== undefined) { + throw new InvalidArgumentError('invalid onBodySent method') } - // https://github.com/nodejs/undici/issues/2046 - // A user agent may send a Content-Length header with 0 value, this should be allowed. - if (shouldSendContentLength(method) && contentLength > 0 && request.contentLength != null && request.contentLength !== contentLength) { - if (client[kStrictContentLength]) { - util.errorRequest(client, request, new RequestContentLengthMismatchError()) - return false + if (upgrade || method === 'CONNECT') { + if (typeof handler.onUpgrade !== 'function') { + throw new InvalidArgumentError('invalid onUpgrade method') + } + } else { + if (typeof handler.onHeaders !== 'function') { + throw new InvalidArgumentError('invalid onHeaders method') } - process.emitWarning(new RequestContentLengthMismatchError()) - } + if (typeof handler.onData !== 'function') { + throw new InvalidArgumentError('invalid onData method') + } - if (contentLength != null) { - assert(body || contentLength === 0, 'no body must not have content length') - headers[HTTP2_HEADER_CONTENT_LENGTH] = `${contentLength}` + if (typeof handler.onComplete !== 'function') { + throw new InvalidArgumentError('invalid onComplete method') + } } +} - session.ref() +/** + * A body is disturbed if it has been read from and it cannot be re-used without + * losing state or data. + * @param {import('node:stream').Readable} body + * @returns {boolean} + */ +function isDisturbed (body) { + // TODO (fix): Why is body[kBodyUsed] needed? + return !!(body && (stream.isDisturbed(body) || body[kBodyUsed])) +} - if (channels.sendHeaders.hasSubscribers) { - let header = '' - for (const key in headers) { - header += `${key}: ${headers[key]}\r\n` - } - channels.sendHeaders.publish({ request, headers: header, socket: session[kSocket] }) +/** + * @typedef {object} SocketInfo + * @property {string} [localAddress] + * @property {number} [localPort] + * @property {string} [remoteAddress] + * @property {number} [remotePort] + * @property {string} [remoteFamily] + * @property {number} [timeout] + * @property {number} bytesWritten + * @property {number} bytesRead + */ + +/** + * @param {import('net').Socket} socket + * @returns {SocketInfo} + */ +function getSocketInfo (socket) { + return { + localAddress: socket.localAddress, + localPort: socket.localPort, + remoteAddress: socket.remoteAddress, + remotePort: socket.remotePort, + remoteFamily: socket.remoteFamily, + timeout: socket.timeout, + bytesWritten: socket.bytesWritten, + bytesRead: socket.bytesRead } +} - // TODO(metcoder95): add support for sending trailers - const shouldEndStream = method === 'GET' || method === 'HEAD' || body === null - if (expectContinue) { - headers[HTTP2_HEADER_EXPECT] = '100-continue' - stream = session.request(headers, { endStream: shouldEndStream, signal }) - stream[kHTTP2Stream] = true +/** + * @param {Iterable} iterable + * @returns {ReadableStream} + */ +function ReadableStreamFrom (iterable) { + // We cannot use ReadableStream.from here because it does not return a byte stream. - stream.once('continue', writeBodyH2) - } else { - stream = session.request(headers, { - endStream: shouldEndStream, - signal - }) - stream[kHTTP2Stream] = true + let iterator + return new ReadableStream( + { + start () { + iterator = iterable[Symbol.asyncIterator]() + }, + pull (controller) { + return iterator.next().then(({ done, value }) => { + if (done) { + return queueMicrotask(() => { + controller.close() + controller.byobRequest?.respond(0) + }) + } else { + const buf = Buffer.isBuffer(value) ? value : Buffer.from(value) + if (buf.byteLength) { + return controller.enqueue(new Uint8Array(buf)) + } else { + return this.pull(controller) + } + } + }) + }, + cancel () { + return iterator.return() + }, + type: 'bytes' + } + ) +} - writeBodyH2() +/** + * The object should be a FormData instance and contains all the required + * methods. + * @param {*} object + * @returns {object is FormData} + */ +function isFormDataLike (object) { + return ( + object && + typeof object === 'object' && + typeof object.append === 'function' && + typeof object.delete === 'function' && + typeof object.get === 'function' && + typeof object.getAll === 'function' && + typeof object.has === 'function' && + typeof object.set === 'function' && + object[Symbol.toStringTag] === 'FormData' + ) +} + +function addAbortListener (signal, listener) { + if ('addEventListener' in signal) { + signal.addEventListener('abort', listener, { once: true }) + return () => signal.removeEventListener('abort', listener) } + signal.once('abort', listener) + return () => signal.removeListener('abort', listener) +} - // Increment counter as we have new streams open - ++session[kOpenStreams] - stream.setTimeout(requestTimeout) +const validTokenChars = new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0-15 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31 + 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, // 32-47 (!"#$%&'()*+,-./) + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48-63 (0-9:;<=>?) + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64-79 (@A-O) + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, // 80-95 (P-Z[\]^_) + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96-111 (`a-o) + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, // 112-127 (p-z{|}~) + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 128-143 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 144-159 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 160-175 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 176-191 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 192-207 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 208-223 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 224-239 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 240-255 +]) - stream.once('response', headers => { - const { [HTTP2_HEADER_STATUS]: statusCode, ...realHeaders } = headers - request.onResponseStarted() +/** + * @see https://tools.ietf.org/html/rfc7230#section-3.2.6 + * @param {number} c + * @returns {boolean} + */ +function isTokenCharCode (c) { + return (validTokenChars[c] === 1) +} - // Due to the stream nature, it is possible we face a race condition - // where the stream has been assigned, but the request has been aborted - // the request remains in-flight and headers hasn't been received yet - // for those scenarios, best effort is to destroy the stream immediately - // as there's no value to keep it open. - if (request.aborted) { - stream.removeAllListeners('data') - return - } +const tokenRegExp = /^[\^_`a-zA-Z\-0-9!#$%&'*+.|~]+$/ - if (request.onHeaders(Number(statusCode), parseH2Headers(realHeaders), stream.resume.bind(stream), '') === false) { - stream.pause() - } - }) +/** + * @param {string} characters + * @returns {boolean} + */ +function isValidHTTPToken (characters) { + if (characters.length >= 12) return tokenRegExp.test(characters) + if (characters.length === 0) return false - stream.on('data', (chunk) => { - if (request.onData(chunk) === false) { - stream.pause() + for (let i = 0; i < characters.length; i++) { + if (validTokenChars[characters.charCodeAt(i)] !== 1) { + return false } - }) + } + return true +} - stream.once('end', (err) => { - stream.removeAllListeners('data') - // When state is null, it means we haven't consumed body and the stream still do not have - // a state. - // Present specially when using pipeline or stream - if (stream.state?.state == null || stream.state.state < 6) { - // Do not complete the request if it was aborted - // Not prone to happen for as safety net to avoid race conditions with 'trailers' - if (!request.aborted && !request.completed) { - request.onComplete({}) - } - - client[kQueue][client[kRunningIdx]++] = null - client[kResume]() - } else { - // Stream is closed or half-closed-remote (6), decrement counter and cleanup - // It does not have sense to continue working with the stream as we do not - // have yet RST_STREAM support on client-side - --session[kOpenStreams] - if (session[kOpenStreams] === 0) { - session.unref() - } - - abort(err ?? new InformationalError('HTTP/2: stream half-closed (remote)')) - client[kQueue][client[kRunningIdx]++] = null - client[kPendingIdx] = client[kRunningIdx] - client[kResume]() - } - }) - - stream.once('close', () => { - stream.removeAllListeners('data') - session[kOpenStreams] -= 1 - if (session[kOpenStreams] === 0) { - session.unref() - } - }) - - stream.once('error', function (err) { - stream.removeAllListeners('data') - abort(err) - }) - - stream.once('frameError', (type, code) => { - stream.removeAllListeners('data') - abort(new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`)) - }) +// headerCharRegex have been lifted from +// https://github.com/nodejs/node/blob/main/lib/_http_common.js - stream.on('aborted', () => { - stream.removeAllListeners('data') - }) +/** + * Matches if val contains an invalid field-vchar + * field-value = *( field-content / obs-fold ) + * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ] + * field-vchar = VCHAR / obs-text + */ +const headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/ - stream.on('timeout', () => { - const err = new InformationalError(`HTTP/2: "stream timeout after ${requestTimeout}"`) - stream.removeAllListeners('data') - session[kOpenStreams] -= 1 +/** + * @param {string} characters + * @returns {boolean} + */ +function isValidHeaderValue (characters) { + return !headerCharRegex.test(characters) +} - if (session[kOpenStreams] === 0) { - session.unref() - } +const rangeHeaderRegex = /^bytes (\d+)-(\d+)\/(\d+)?$/ - abort(err) - }) +/** + * @typedef {object} RangeHeader + * @property {number} start + * @property {number | null} end + * @property {number | null} size + */ - stream.once('trailers', trailers => { - if (request.aborted || request.completed) { - return - } +/** + * Parse accordingly to RFC 9110 + * @see https://www.rfc-editor.org/rfc/rfc9110#field.content-range + * @param {string} [range] + * @returns {RangeHeader|null} + */ +function parseRangeHeader (range) { + if (range == null || range === '') return { start: 0, end: null, size: null } - request.onComplete(trailers) - }) + const m = range ? range.match(rangeHeaderRegex) : null + return m + ? { + start: parseInt(m[1]), + end: m[2] ? parseInt(m[2]) : null, + size: m[3] ? parseInt(m[3]) : null + } + : null +} - return true +/** + * @template {import("events").EventEmitter} T + * @param {T} obj + * @param {string} name + * @param {(...args: any[]) => void} listener + * @returns {T} + */ +function addListener (obj, name, listener) { + const listeners = (obj[kListeners] ??= []) + listeners.push([name, listener]) + obj.on(name, listener) + return obj +} - function writeBodyH2 () { - if (!body || contentLength === 0) { - writeBuffer( - abort, - stream, - null, - client, - request, - client[kSocket], - contentLength, - expectsPayload - ) - } else if (util.isBuffer(body)) { - writeBuffer( - abort, - stream, - body, - client, - request, - client[kSocket], - contentLength, - expectsPayload - ) - } else if (util.isBlobLike(body)) { - if (typeof body.stream === 'function') { - writeIterable( - abort, - stream, - body.stream(), - client, - request, - client[kSocket], - contentLength, - expectsPayload - ) - } else { - writeBlob( - abort, - stream, - body, - client, - request, - client[kSocket], - contentLength, - expectsPayload - ) - } - } else if (util.isStream(body)) { - writeStream( - abort, - client[kSocket], - expectsPayload, - stream, - body, - client, - request, - contentLength - ) - } else if (util.isIterable(body)) { - writeIterable( - abort, - stream, - body, - client, - request, - client[kSocket], - contentLength, - expectsPayload - ) - } else { - assert(false) +/** + * @template {import("events").EventEmitter} T + * @param {T} obj + * @returns {T} + */ +function removeAllListeners (obj) { + if (obj[kListeners] != null) { + for (const [name, listener] of obj[kListeners]) { + obj.removeListener(name, listener) } + obj[kListeners] = null } + return obj } -function writeBuffer (abort, h2stream, body, client, request, socket, contentLength, expectsPayload) { +/** + * @param {import ('../dispatcher/client')} client + * @param {import ('../core/request')} request + * @param {Error} err + */ +function errorRequest (client, request, err) { try { - if (body != null && util.isBuffer(body)) { - assert(contentLength === body.byteLength, 'buffer body must have content length') - h2stream.cork() - h2stream.write(body) - h2stream.uncork() - h2stream.end() + request.onError(err) + assert(request.aborted) + } catch (err) { + client.emit('error', err) + } +} - request.onBodySent(body) +/** + * @param {WeakRef} socketWeakRef + * @param {object} opts + * @param {number} opts.timeout + * @param {string} opts.hostname + * @param {number} opts.port + * @returns {() => void} + */ +const setupConnectTimeout = process.platform === 'win32' + ? (socketWeakRef, opts) => { + if (!opts.timeout) { + return noop + } + + let s1 = null + let s2 = null + const fastTimer = timers.setFastTimeout(() => { + // setImmediate is added to make sure that we prioritize socket error events over timeouts + s1 = setImmediate(() => { + // Windows needs an extra setImmediate probably due to implementation differences in the socket logic + s2 = setImmediate(() => onConnectTimeout(socketWeakRef.deref(), opts)) + }) + }, opts.timeout) + return () => { + timers.clearFastTimeout(fastTimer) + clearImmediate(s1) + clearImmediate(s2) + } } + : (socketWeakRef, opts) => { + if (!opts.timeout) { + return noop + } - if (!expectsPayload) { - socket[kReset] = true + let s1 = null + const fastTimer = timers.setFastTimeout(() => { + // setImmediate is added to make sure that we prioritize socket error events over timeouts + s1 = setImmediate(() => { + onConnectTimeout(socketWeakRef.deref(), opts) + }) + }, opts.timeout) + return () => { + timers.clearFastTimeout(fastTimer) + clearImmediate(s1) + } } - request.onRequestSent() - client[kResume]() - } catch (error) { - abort(error) +/** + * @param {net.Socket} socket + * @param {object} opts + * @param {number} opts.timeout + * @param {string} opts.hostname + * @param {number} opts.port + */ +function onConnectTimeout (socket, opts) { + // The socket could be already garbage collected + if (socket == null) { + return } -} -function writeStream (abort, socket, expectsPayload, h2stream, body, client, request, contentLength) { - assert(contentLength !== 0 || client[kRunning] === 0, 'stream body cannot be pipelined') + let message = 'Connect Timeout Error' + if (Array.isArray(socket.autoSelectFamilyAttemptedAddresses)) { + message += ` (attempted addresses: ${socket.autoSelectFamilyAttemptedAddresses.join(', ')},` + } else { + message += ` (attempted address: ${opts.hostname}:${opts.port},` + } - // For HTTP/2, is enough to pipe the stream - const pipe = pipeline( - body, - h2stream, - (err) => { - if (err) { - util.destroy(pipe, err) - abort(err) - } else { - util.removeAllListeners(pipe) - request.onRequestSent() + message += ` timeout: ${opts.timeout}ms)` - if (!expectsPayload) { - socket[kReset] = true - } + destroy(socket, new ConnectTimeoutError(message)) +} - client[kResume]() - } +/** + * @param {string} urlString + * @returns {string} + */ +function getProtocolFromUrlString (urlString) { + if ( + urlString[0] === 'h' && + urlString[1] === 't' && + urlString[2] === 't' && + urlString[3] === 'p' + ) { + switch (urlString[4]) { + case ':': + return 'http:' + case 's': + if (urlString[5] === ':') { + return 'https:' + } } - ) - - util.addListener(pipe, 'data', onPipeData) - - function onPipeData (chunk) { - request.onBodySent(chunk) } + // fallback if none of the usual suspects + return urlString.slice(0, urlString.indexOf(':') + 1) } -async function writeBlob (abort, h2stream, body, client, request, socket, contentLength, expectsPayload) { - assert(contentLength === body.size, 'blob body must have content length') +const kEnumerableProperty = Object.create(null) +kEnumerableProperty.enumerable = true - try { - if (contentLength != null && contentLength !== body.size) { - throw new RequestContentLengthMismatchError() - } +const normalizedMethodRecordsBase = { + delete: 'DELETE', + DELETE: 'DELETE', + get: 'GET', + GET: 'GET', + head: 'HEAD', + HEAD: 'HEAD', + options: 'OPTIONS', + OPTIONS: 'OPTIONS', + post: 'POST', + POST: 'POST', + put: 'PUT', + PUT: 'PUT' +} - const buffer = Buffer.from(await body.arrayBuffer()) +const normalizedMethodRecords = { + ...normalizedMethodRecordsBase, + patch: 'patch', + PATCH: 'PATCH' +} - h2stream.cork() - h2stream.write(buffer) - h2stream.uncork() - h2stream.end() +// Note: object prototypes should not be able to be referenced. e.g. `Object#hasOwnProperty`. +Object.setPrototypeOf(normalizedMethodRecordsBase, null) +Object.setPrototypeOf(normalizedMethodRecords, null) - request.onBodySent(buffer) - request.onRequestSent() +module.exports = { + kEnumerableProperty, + isDisturbed, + isBlobLike, + parseOrigin, + parseURL, + getServerName, + isStream, + isIterable, + isAsyncIterable, + isDestroyed, + headerNameToString, + bufferToLowerCasedHeaderName, + addListener, + removeAllListeners, + errorRequest, + parseRawHeaders, + encodeRawHeaders, + parseHeaders, + parseKeepAliveTimeout, + destroy, + bodyLength, + deepClone, + ReadableStreamFrom, + isBuffer, + assertRequestHandler, + getSocketInfo, + isFormDataLike, + pathHasQueryOrFragment, + serializePathWithQuery, + addAbortListener, + isValidHTTPToken, + isValidHeaderValue, + isTokenCharCode, + parseRangeHeader, + normalizedMethodRecordsBase, + normalizedMethodRecords, + isValidPort, + isHttpOrHttpsPrefixed, + nodeMajor, + nodeMinor, + safeHTTPMethods: Object.freeze(['GET', 'HEAD', 'OPTIONS', 'TRACE']), + wrapRequestBody, + setupConnectTimeout, + getProtocolFromUrlString +} - if (!expectsPayload) { - socket[kReset] = true - } - client[kResume]() - } catch (err) { - abort(err) - } -} +/***/ }), -async function writeIterable (abort, h2stream, body, client, request, socket, contentLength, expectsPayload) { - assert(contentLength !== 0 || client[kRunning] === 0, 'iterator body cannot be pipelined') +/***/ 9959: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - let callback = null - function onDrain () { - if (callback) { - const cb = callback - callback = null - cb() - } - } - const waitForDrain = () => new Promise((resolve, reject) => { - assert(callback === null) - if (socket[kError]) { - reject(socket[kError]) - } else { - callback = resolve - } - }) +const { InvalidArgumentError, MaxOriginsReachedError } = __nccwpck_require__(5093) +const { kClients, kRunning, kClose, kDestroy, kDispatch, kUrl } = __nccwpck_require__(8261) +const DispatcherBase = __nccwpck_require__(6223) +const Pool = __nccwpck_require__(8034) +const Client = __nccwpck_require__(1115) +const util = __nccwpck_require__(2550) - h2stream - .on('close', onDrain) - .on('drain', onDrain) +const kOnConnect = Symbol('onConnect') +const kOnDisconnect = Symbol('onDisconnect') +const kOnConnectionError = Symbol('onConnectionError') +const kOnDrain = Symbol('onDrain') +const kFactory = Symbol('factory') +const kOptions = Symbol('options') +const kOrigins = Symbol('origins') - try { - // It's up to the user to somehow abort the async iterable. - for await (const chunk of body) { - if (socket[kError]) { - throw socket[kError] - } +function defaultFactory (origin, opts) { + return opts && opts.connections === 1 + ? new Client(origin, opts) + : new Pool(origin, opts) +} - const res = h2stream.write(chunk) - request.onBodySent(chunk) - if (!res) { - await waitForDrain() - } +class Agent extends DispatcherBase { + constructor ({ factory = defaultFactory, maxOrigins = Infinity, connect, ...options } = {}) { + if (typeof factory !== 'function') { + throw new InvalidArgumentError('factory must be a function.') } - h2stream.end() - - request.onRequestSent() + if (connect != null && typeof connect !== 'function' && typeof connect !== 'object') { + throw new InvalidArgumentError('connect must be a function or an object') + } - if (!expectsPayload) { - socket[kReset] = true + if (typeof maxOrigins !== 'number' || Number.isNaN(maxOrigins) || maxOrigins <= 0) { + throw new InvalidArgumentError('maxOrigins must be a number greater than 0') } - client[kResume]() - } catch (err) { - abort(err) - } finally { - h2stream - .off('close', onDrain) - .off('drain', onDrain) - } -} + super() -module.exports = connectH2 + if (connect && typeof connect !== 'function') { + connect = { ...connect } + } + this[kOptions] = { ...util.deepClone(options), maxOrigins, connect } + this[kFactory] = factory + this[kClients] = new Map() + this[kOrigins] = new Set() -/***/ }), + this[kOnDrain] = (origin, targets) => { + this.emit('drain', origin, [this, ...targets]) + } -/***/ 226: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + this[kOnConnect] = (origin, targets) => { + this.emit('connect', origin, [this, ...targets]) + } -"use strict"; + this[kOnDisconnect] = (origin, targets, err) => { + this.emit('disconnect', origin, [this, ...targets], err) + } + this[kOnConnectionError] = (origin, targets, err) => { + this.emit('connectionError', origin, [this, ...targets], err) + } + } -const assert = __nccwpck_require__(4589) -const net = __nccwpck_require__(7030) -const http = __nccwpck_require__(7067) -const util = __nccwpck_require__(983) -const { ClientStats } = __nccwpck_require__(7755) -const { channels } = __nccwpck_require__(6591) -const Request = __nccwpck_require__(8990) -const DispatcherBase = __nccwpck_require__(6612) -const { - InvalidArgumentError, - InformationalError, - ClientDestroyedError -} = __nccwpck_require__(4928) -const buildConnector = __nccwpck_require__(978) -const { - kUrl, - kServerName, - kClient, - kBusy, - kConnect, - kResuming, - kRunning, - kPending, - kSize, - kQueue, - kConnected, - kConnecting, - kNeedDrain, - kKeepAliveDefaultTimeout, - kHostHeader, - kPendingIdx, - kRunningIdx, - kError, - kPipelining, - kKeepAliveTimeoutValue, - kMaxHeadersSize, - kKeepAliveMaxTimeout, - kKeepAliveTimeoutThreshold, - kHeadersTimeout, - kBodyTimeout, - kStrictContentLength, - kConnector, - kMaxRequests, - kCounter, - kClose, - kDestroy, - kDispatch, - kLocalAddress, - kMaxResponseSize, - kOnError, - kHTTPContext, - kMaxConcurrentStreams, - kHTTP2InitialWindowSize, - kHTTP2ConnectionWindowSize, - kResume -} = __nccwpck_require__(9562) -const connectH1 = __nccwpck_require__(1300) -const connectH2 = __nccwpck_require__(9181) - -const kClosedResolve = Symbol('kClosedResolve') + get [kRunning] () { + let ret = 0 + for (const { dispatcher } of this[kClients].values()) { + ret += dispatcher[kRunning] + } + return ret + } -const getDefaultNodeMaxHeaderSize = http && - http.maxHeaderSize && - Number.isInteger(http.maxHeaderSize) && - http.maxHeaderSize > 0 - ? () => http.maxHeaderSize - : () => { throw new InvalidArgumentError('http module not available or http.maxHeaderSize invalid') } + [kDispatch] (opts, handler) { + let key + if (opts.origin && (typeof opts.origin === 'string' || opts.origin instanceof URL)) { + key = String(opts.origin) + } else { + throw new InvalidArgumentError('opts.origin must be a non-empty string or URL.') + } -const noop = () => {} + if (this[kOrigins].size >= this[kOptions].maxOrigins && !this[kOrigins].has(key)) { + throw new MaxOriginsReachedError() + } -function getPipelining (client) { - return client[kPipelining] ?? client[kHTTPContext]?.defaultPipelining ?? 1 -} + const result = this[kClients].get(key) + let dispatcher = result && result.dispatcher + if (!dispatcher) { + const closeClientIfUnused = (connected) => { + const result = this[kClients].get(key) + if (result) { + if (connected) result.count -= 1 + if (result.count <= 0) { + this[kClients].delete(key) + result.dispatcher.close() + } + this[kOrigins].delete(key) + } + } + dispatcher = this[kFactory](opts.origin, this[kOptions]) + .on('drain', this[kOnDrain]) + .on('connect', (origin, targets) => { + const result = this[kClients].get(key) + if (result) { + result.count += 1 + } + this[kOnConnect](origin, targets) + }) + .on('disconnect', (origin, targets, err) => { + closeClientIfUnused(true) + this[kOnDisconnect](origin, targets, err) + }) + .on('connectionError', (origin, targets, err) => { + closeClientIfUnused(false) + this[kOnConnectionError](origin, targets, err) + }) -/** - * @type {import('../../types/client.js').default} - */ -class Client extends DispatcherBase { - /** - * - * @param {string|URL} url - * @param {import('../../types/client.js').Client.Options} options - */ - constructor (url, { - maxHeaderSize, - headersTimeout, - socketTimeout, - requestTimeout, - connectTimeout, - bodyTimeout, - idleTimeout, - keepAlive, - keepAliveTimeout, - maxKeepAliveTimeout, - keepAliveMaxTimeout, - keepAliveTimeoutThreshold, - socketPath, - pipelining, - tls, - strictContentLength, - maxCachedSessions, - connect, - maxRequestsPerClient, - localAddress, - maxResponseSize, - autoSelectFamily, - autoSelectFamilyAttemptTimeout, - // h2 - maxConcurrentStreams, - allowH2, - useH2c, - initialWindowSize, - connectionWindowSize - } = {}) { - if (keepAlive !== undefined) { - throw new InvalidArgumentError('unsupported keepAlive, use pipelining=0 instead') + this[kClients].set(key, { count: 0, dispatcher }) + this[kOrigins].add(key) } - if (socketTimeout !== undefined) { - throw new InvalidArgumentError('unsupported socketTimeout, use headersTimeout & bodyTimeout instead') - } + return dispatcher.dispatch(opts, handler) + } - if (requestTimeout !== undefined) { - throw new InvalidArgumentError('unsupported requestTimeout, use headersTimeout & bodyTimeout instead') + [kClose] () { + const closePromises = [] + for (const { dispatcher } of this[kClients].values()) { + closePromises.push(dispatcher.close()) } + this[kClients].clear() - if (idleTimeout !== undefined) { - throw new InvalidArgumentError('unsupported idleTimeout, use keepAliveTimeout instead') - } + return Promise.all(closePromises) + } - if (maxKeepAliveTimeout !== undefined) { - throw new InvalidArgumentError('unsupported maxKeepAliveTimeout, use keepAliveMaxTimeout instead') + [kDestroy] (err) { + const destroyPromises = [] + for (const { dispatcher } of this[kClients].values()) { + destroyPromises.push(dispatcher.destroy(err)) } + this[kClients].clear() - if (maxHeaderSize != null) { - if (!Number.isInteger(maxHeaderSize) || maxHeaderSize < 1) { - throw new InvalidArgumentError('invalid maxHeaderSize') + return Promise.all(destroyPromises) + } + + get stats () { + const allClientStats = {} + for (const { dispatcher } of this[kClients].values()) { + if (dispatcher.stats) { + allClientStats[dispatcher[kUrl].origin] = dispatcher.stats } - } else { - // If maxHeaderSize is not provided, use the default value from the http module - // or if that is not available, throw an error. - maxHeaderSize = getDefaultNodeMaxHeaderSize() } + return allClientStats + } +} - if (socketPath != null && typeof socketPath !== 'string') { - throw new InvalidArgumentError('invalid socketPath') - } +module.exports = Agent - if (connectTimeout != null && (!Number.isFinite(connectTimeout) || connectTimeout < 0)) { - throw new InvalidArgumentError('invalid connectTimeout') - } - if (keepAliveTimeout != null && (!Number.isFinite(keepAliveTimeout) || keepAliveTimeout <= 0)) { - throw new InvalidArgumentError('invalid keepAliveTimeout') - } +/***/ }), - if (keepAliveMaxTimeout != null && (!Number.isFinite(keepAliveMaxTimeout) || keepAliveMaxTimeout <= 0)) { - throw new InvalidArgumentError('invalid keepAliveMaxTimeout') - } +/***/ 1083: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - if (keepAliveTimeoutThreshold != null && !Number.isFinite(keepAliveTimeoutThreshold)) { - throw new InvalidArgumentError('invalid keepAliveTimeoutThreshold') - } - if (headersTimeout != null && (!Number.isInteger(headersTimeout) || headersTimeout < 0)) { - throw new InvalidArgumentError('headersTimeout must be a positive integer or zero') - } - if (bodyTimeout != null && (!Number.isInteger(bodyTimeout) || bodyTimeout < 0)) { - throw new InvalidArgumentError('bodyTimeout must be a positive integer or zero') - } +const { + BalancedPoolMissingUpstreamError, + InvalidArgumentError +} = __nccwpck_require__(5093) +const { + PoolBase, + kClients, + kNeedDrain, + kAddClient, + kRemoveClient, + kGetDispatcher +} = __nccwpck_require__(7978) +const Pool = __nccwpck_require__(8034) +const { kUrl } = __nccwpck_require__(8261) +const { parseOrigin } = __nccwpck_require__(2550) +const kFactory = Symbol('factory') - if (connect != null && typeof connect !== 'function' && typeof connect !== 'object') { - throw new InvalidArgumentError('connect must be a function or an object') - } +const kOptions = Symbol('options') +const kGreatestCommonDivisor = Symbol('kGreatestCommonDivisor') +const kCurrentWeight = Symbol('kCurrentWeight') +const kIndex = Symbol('kIndex') +const kWeight = Symbol('kWeight') +const kMaxWeightPerServer = Symbol('kMaxWeightPerServer') +const kErrorPenalty = Symbol('kErrorPenalty') - if (maxRequestsPerClient != null && (!Number.isInteger(maxRequestsPerClient) || maxRequestsPerClient < 0)) { - throw new InvalidArgumentError('maxRequestsPerClient must be a positive number') - } +/** + * Calculate the greatest common divisor of two numbers by + * using the Euclidean algorithm. + * + * @param {number} a + * @param {number} b + * @returns {number} + */ +function getGreatestCommonDivisor (a, b) { + if (a === 0) return b - if (localAddress != null && (typeof localAddress !== 'string' || net.isIP(localAddress) === 0)) { - throw new InvalidArgumentError('localAddress must be valid string IP address') - } + while (b !== 0) { + const t = b + b = a % b + a = t + } + return a +} - if (maxResponseSize != null && (!Number.isInteger(maxResponseSize) || maxResponseSize < -1)) { - throw new InvalidArgumentError('maxResponseSize must be a positive number') - } +function defaultFactory (origin, opts) { + return new Pool(origin, opts) +} - if ( - autoSelectFamilyAttemptTimeout != null && - (!Number.isInteger(autoSelectFamilyAttemptTimeout) || autoSelectFamilyAttemptTimeout < -1) - ) { - throw new InvalidArgumentError('autoSelectFamilyAttemptTimeout must be a positive number') +class BalancedPool extends PoolBase { + constructor (upstreams = [], { factory = defaultFactory, ...opts } = {}) { + if (typeof factory !== 'function') { + throw new InvalidArgumentError('factory must be a function.') } - // h2 - if (allowH2 != null && typeof allowH2 !== 'boolean') { - throw new InvalidArgumentError('allowH2 must be a valid boolean value') - } + super() - if (maxConcurrentStreams != null && (typeof maxConcurrentStreams !== 'number' || maxConcurrentStreams < 1)) { - throw new InvalidArgumentError('maxConcurrentStreams must be a positive integer, greater than 0') - } + this[kOptions] = opts + this[kIndex] = -1 + this[kCurrentWeight] = 0 - if (useH2c != null && typeof useH2c !== 'boolean') { - throw new InvalidArgumentError('useH2c must be a valid boolean value') - } + this[kMaxWeightPerServer] = this[kOptions].maxWeightPerServer || 100 + this[kErrorPenalty] = this[kOptions].errorPenalty || 15 - if (initialWindowSize != null && (!Number.isInteger(initialWindowSize) || initialWindowSize < 1)) { - throw new InvalidArgumentError('initialWindowSize must be a positive integer, greater than 0') + if (!Array.isArray(upstreams)) { + upstreams = [upstreams] } - if (connectionWindowSize != null && (!Number.isInteger(connectionWindowSize) || connectionWindowSize < 1)) { - throw new InvalidArgumentError('connectionWindowSize must be a positive integer, greater than 0') + this[kFactory] = factory + + for (const upstream of upstreams) { + this.addUpstream(upstream) } + this._updateBalancedPoolStats() + } - super() + addUpstream (upstream) { + const upstreamOrigin = parseOrigin(upstream).origin - if (typeof connect !== 'function') { - connect = buildConnector({ - ...tls, - maxCachedSessions, - allowH2, - useH2c, - socketPath, - timeout: connectTimeout, - ...(typeof autoSelectFamily === 'boolean' ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : undefined), - ...connect - }) + if (this[kClients].find((pool) => ( + pool[kUrl].origin === upstreamOrigin && + pool.closed !== true && + pool.destroyed !== true + ))) { + return this } + const pool = this[kFactory](upstreamOrigin, Object.assign({}, this[kOptions])) - this[kUrl] = util.parseOrigin(url) - this[kConnector] = connect - this[kPipelining] = pipelining != null ? pipelining : 1 - this[kMaxHeadersSize] = maxHeaderSize - this[kKeepAliveDefaultTimeout] = keepAliveTimeout == null ? 4e3 : keepAliveTimeout - this[kKeepAliveMaxTimeout] = keepAliveMaxTimeout == null ? 600e3 : keepAliveMaxTimeout - this[kKeepAliveTimeoutThreshold] = keepAliveTimeoutThreshold == null ? 2e3 : keepAliveTimeoutThreshold - this[kKeepAliveTimeoutValue] = this[kKeepAliveDefaultTimeout] - this[kServerName] = null - this[kLocalAddress] = localAddress != null ? localAddress : null - this[kResuming] = 0 // 0, idle, 1, scheduled, 2 resuming - this[kNeedDrain] = 0 // 0, idle, 1, scheduled, 2 resuming - this[kHostHeader] = `host: ${this[kUrl].hostname}${this[kUrl].port ? `:${this[kUrl].port}` : ''}\r\n` - this[kBodyTimeout] = bodyTimeout != null ? bodyTimeout : 300e3 - this[kHeadersTimeout] = headersTimeout != null ? headersTimeout : 300e3 - this[kStrictContentLength] = strictContentLength == null ? true : strictContentLength - this[kMaxRequests] = maxRequestsPerClient - this[kClosedResolve] = null - this[kMaxResponseSize] = maxResponseSize > -1 ? maxResponseSize : -1 - this[kMaxConcurrentStreams] = maxConcurrentStreams != null ? maxConcurrentStreams : 100 // Max peerConcurrentStreams for a Node h2 server - // HTTP/2 window sizes are set to higher defaults than Node.js core for better performance: - // - initialWindowSize: 262144 (256KB) vs Node.js default 65535 (64KB - 1) - // Allows more data to be sent before requiring acknowledgment, improving throughput - // especially on high-latency networks. This matches common production HTTP/2 servers. - // - connectionWindowSize: 524288 (512KB) vs Node.js default (none set) - // Provides better flow control for the entire connection across multiple streams. - this[kHTTP2InitialWindowSize] = initialWindowSize != null ? initialWindowSize : 262144 - this[kHTTP2ConnectionWindowSize] = connectionWindowSize != null ? connectionWindowSize : 524288 - this[kHTTPContext] = null + this[kAddClient](pool) + pool.on('connect', () => { + pool[kWeight] = Math.min(this[kMaxWeightPerServer], pool[kWeight] + this[kErrorPenalty]) + }) - // kQueue is built up of 3 sections separated by - // the kRunningIdx and kPendingIdx indices. - // | complete | running | pending | - // ^ kRunningIdx ^ kPendingIdx ^ kQueue.length - // kRunningIdx points to the first running element. - // kPendingIdx points to the first pending element. - // This implements a fast queue with an amortized - // time of O(1). + pool.on('connectionError', () => { + pool[kWeight] = Math.max(1, pool[kWeight] - this[kErrorPenalty]) + this._updateBalancedPoolStats() + }) - this[kQueue] = [] - this[kRunningIdx] = 0 - this[kPendingIdx] = 0 + pool.on('disconnect', (...args) => { + const err = args[2] + if (err && err.code === 'UND_ERR_SOCKET') { + // decrease the weight of the pool. + pool[kWeight] = Math.max(1, pool[kWeight] - this[kErrorPenalty]) + this._updateBalancedPoolStats() + } + }) - this[kResume] = (sync) => resume(this, sync) - this[kOnError] = (err) => onError(this, err) - } + for (const client of this[kClients]) { + client[kWeight] = this[kMaxWeightPerServer] + } - get pipelining () { - return this[kPipelining] - } + this._updateBalancedPoolStats() - set pipelining (value) { - this[kPipelining] = value - this[kResume](true) + return this } - get stats () { - return new ClientStats(this) - } + _updateBalancedPoolStats () { + let result = 0 + for (let i = 0; i < this[kClients].length; i++) { + result = getGreatestCommonDivisor(this[kClients][i][kWeight], result) + } - get [kPending] () { - return this[kQueue].length - this[kPendingIdx] + this[kGreatestCommonDivisor] = result } - get [kRunning] () { - return this[kPendingIdx] - this[kRunningIdx] - } + removeUpstream (upstream) { + const upstreamOrigin = parseOrigin(upstream).origin - get [kSize] () { - return this[kQueue].length - this[kRunningIdx] - } + const pool = this[kClients].find((pool) => ( + pool[kUrl].origin === upstreamOrigin && + pool.closed !== true && + pool.destroyed !== true + )) - get [kConnected] () { - return !!this[kHTTPContext] && !this[kConnecting] && !this[kHTTPContext].destroyed + if (pool) { + this[kRemoveClient](pool) + } + + return this } - get [kBusy] () { - return Boolean( - this[kHTTPContext]?.busy(null) || - (this[kSize] >= (getPipelining(this) || 1)) || - this[kPending] > 0 - ) + getUpstream (upstream) { + const upstreamOrigin = parseOrigin(upstream).origin + + return this[kClients].find((pool) => ( + pool[kUrl].origin === upstreamOrigin && + pool.closed !== true && + pool.destroyed !== true + )) } - [kConnect] (cb) { - connect(this) - this.once('connect', cb) + get upstreams () { + return this[kClients] + .filter(dispatcher => dispatcher.closed !== true && dispatcher.destroyed !== true) + .map((p) => p[kUrl].origin) } - [kDispatch] (opts, handler) { - const request = new Request(this[kUrl].origin, opts, handler) + [kGetDispatcher] () { + // We validate that pools is greater than 0, + // otherwise we would have to wait until an upstream + // is added, which might never happen. + if (this[kClients].length === 0) { + throw new BalancedPoolMissingUpstreamError() + } - this[kQueue].push(request) - if (this[kResuming]) { - // Do nothing. - } else if (util.bodyLength(request.body) == null && util.isIterable(request.body)) { - // Wait a tick in case stream/iterator is ended in the same tick. - this[kResuming] = 1 - queueMicrotask(() => resume(this)) - } else { - this[kResume](true) + const dispatcher = this[kClients].find(dispatcher => ( + !dispatcher[kNeedDrain] && + dispatcher.closed !== true && + dispatcher.destroyed !== true + )) + + if (!dispatcher) { + return } - if (this[kResuming] && this[kNeedDrain] !== 2 && this[kBusy]) { - this[kNeedDrain] = 2 + const allClientsBusy = this[kClients].map(pool => pool[kNeedDrain]).reduce((a, b) => a && b, true) + + if (allClientsBusy) { + return } - return this[kNeedDrain] < 2 - } + let counter = 0 - [kClose] () { - // TODO: for H2 we need to gracefully flush the remaining enqueued - // request and close each stream. - return new Promise((resolve) => { - if (this[kSize]) { - this[kClosedResolve] = resolve - } else { - resolve(null) - } - }) - } + let maxWeightIndex = this[kClients].findIndex(pool => !pool[kNeedDrain]) - [kDestroy] (err) { - return new Promise((resolve) => { - const requests = this[kQueue].splice(this[kPendingIdx]) - for (let i = 0; i < requests.length; i++) { - const request = requests[i] - util.errorRequest(this, request, err) - } + while (counter++ < this[kClients].length) { + this[kIndex] = (this[kIndex] + 1) % this[kClients].length + const pool = this[kClients][this[kIndex]] - const callback = () => { - if (this[kClosedResolve]) { - // TODO (fix): Should we error here with ClientDestroyedError? - this[kClosedResolve]() - this[kClosedResolve] = null - } - resolve(null) + // find pool index with the largest weight + if (pool[kWeight] > this[kClients][maxWeightIndex][kWeight] && !pool[kNeedDrain]) { + maxWeightIndex = this[kIndex] } - if (this[kHTTPContext]) { - this[kHTTPContext].destroy(err, callback) - this[kHTTPContext] = null - } else { - queueMicrotask(callback) + // decrease the current weight every `this[kClients].length`. + if (this[kIndex] === 0) { + // Set the current weight to the next lower weight. + this[kCurrentWeight] = this[kCurrentWeight] - this[kGreatestCommonDivisor] + + if (this[kCurrentWeight] <= 0) { + this[kCurrentWeight] = this[kMaxWeightPerServer] + } + } + if (pool[kWeight] >= this[kCurrentWeight] && (!pool[kNeedDrain])) { + return pool } + } - this[kResume]() - }) + this[kCurrentWeight] = this[kClients][maxWeightIndex][kWeight] + this[kIndex] = maxWeightIndex + return this[kClients][maxWeightIndex] } } -function onError (client, err) { - if ( - client[kRunning] === 0 && - err.code !== 'UND_ERR_INFO' && - err.code !== 'UND_ERR_SOCKET' - ) { - // Error is not caused by running request and not a recoverable - // socket error. - - assert(client[kPendingIdx] === client[kRunningIdx]) +module.exports = BalancedPool - const requests = client[kQueue].splice(client[kRunningIdx]) - for (let i = 0; i < requests.length; i++) { - const request = requests[i] - util.errorRequest(client, request, err) - } - assert(client[kSize] === 0) - } -} +/***/ }), -/** - * @param {Client} client - * @returns {void} - */ -function connect (client) { - assert(!client[kConnecting]) - assert(!client[kHTTPContext]) +/***/ 8823: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - let { host, hostname, protocol, port } = client[kUrl] - // Resolve ipv6 - if (hostname[0] === '[') { - const idx = hostname.indexOf(']') - assert(idx !== -1) - const ip = hostname.substring(1, idx) +/* global WebAssembly */ - assert(net.isIPv6(ip)) - hostname = ip - } +const assert = __nccwpck_require__(4589) +const util = __nccwpck_require__(2550) +const { channels } = __nccwpck_require__(2248) +const timers = __nccwpck_require__(8621) +const { + RequestContentLengthMismatchError, + ResponseContentLengthMismatchError, + RequestAbortedError, + HeadersTimeoutError, + HeadersOverflowError, + SocketError, + InformationalError, + BodyTimeoutError, + HTTPParserError, + ResponseExceededMaxSizeError +} = __nccwpck_require__(5093) +const { + kUrl, + kReset, + kClient, + kParser, + kBlocking, + kRunning, + kPending, + kSize, + kWriting, + kQueue, + kNoRef, + kKeepAliveDefaultTimeout, + kHostHeader, + kPendingIdx, + kRunningIdx, + kError, + kPipelining, + kSocket, + kKeepAliveTimeoutValue, + kMaxHeadersSize, + kKeepAliveMaxTimeout, + kKeepAliveTimeoutThreshold, + kHeadersTimeout, + kBodyTimeout, + kStrictContentLength, + kMaxRequests, + kCounter, + kMaxResponseSize, + kOnError, + kResume, + kHTTPContext, + kClosed +} = __nccwpck_require__(8261) - client[kConnecting] = true +const constants = __nccwpck_require__(1478) +const EMPTY_BUF = Buffer.alloc(0) +const FastBuffer = Buffer[Symbol.species] +const removeAllListeners = util.removeAllListeners - if (channels.beforeConnect.hasSubscribers) { - channels.beforeConnect.publish({ - connectParams: { - host, - hostname, - protocol, - port, - version: client[kHTTPContext]?.version, - servername: client[kServerName], - localAddress: client[kLocalAddress] - }, - connector: client[kConnector] - }) - } +let extractBody - client[kConnector]({ - host, - hostname, - protocol, - port, - servername: client[kServerName], - localAddress: client[kLocalAddress] - }, (err, socket) => { - if (err) { - handleConnectError(client, err, { host, hostname, protocol, port }) - client[kResume]() - return - } +function lazyllhttp () { + const llhttpWasmData = process.env.JEST_WORKER_ID ? __nccwpck_require__(1020) : undefined - if (client.destroyed) { - util.destroy(socket.on('error', noop), new ClientDestroyedError()) - client[kResume]() - return - } + let mod - assert(socket) + // We disable wasm SIMD on ppc64 as it seems to be broken on Power 9 architectures. + let useWasmSIMD = process.arch !== 'ppc64' + // The Env Variable UNDICI_NO_WASM_SIMD allows explicitly overriding the default behavior + if (process.env.UNDICI_NO_WASM_SIMD === '1') { + useWasmSIMD = true + } else if (process.env.UNDICI_NO_WASM_SIMD === '0') { + useWasmSIMD = false + } + if (useWasmSIMD) { try { - client[kHTTPContext] = socket.alpnProtocol === 'h2' - ? connectH2(client, socket) - : connectH1(client, socket) - } catch (err) { - socket.destroy().on('error', noop) - handleConnectError(client, err, { host, hostname, protocol, port }) - client[kResume]() - return + mod = new WebAssembly.Module(__nccwpck_require__(820)) + } catch { } + } - client[kConnecting] = false + if (!mod) { + // We could check if the error was caused by the simd option not + // being enabled, but the occurring of this other error + // * https://github.com/emscripten-core/emscripten/issues/11495 + // got me to remove that check to avoid breaking Node 12. + mod = new WebAssembly.Module(llhttpWasmData || __nccwpck_require__(1020)) + } - socket[kCounter] = 0 - socket[kMaxRequests] = client[kMaxRequests] - socket[kClient] = client - socket[kError] = null + return new WebAssembly.Instance(mod, { + env: { + /** + * @param {number} p + * @param {number} at + * @param {number} len + * @returns {number} + */ + wasm_on_url: (p, at, len) => { + return 0 + }, + /** + * @param {number} p + * @param {number} at + * @param {number} len + * @returns {number} + */ + wasm_on_status: (p, at, len) => { + assert(currentParser.ptr === p) + const start = at - currentBufferPtr + currentBufferRef.byteOffset + return currentParser.onStatus(new FastBuffer(currentBufferRef.buffer, start, len)) + }, + /** + * @param {number} p + * @returns {number} + */ + wasm_on_message_begin: (p) => { + assert(currentParser.ptr === p) + return currentParser.onMessageBegin() + }, + /** + * @param {number} p + * @param {number} at + * @param {number} len + * @returns {number} + */ + wasm_on_header_field: (p, at, len) => { + assert(currentParser.ptr === p) + const start = at - currentBufferPtr + currentBufferRef.byteOffset + return currentParser.onHeaderField(new FastBuffer(currentBufferRef.buffer, start, len)) + }, + /** + * @param {number} p + * @param {number} at + * @param {number} len + * @returns {number} + */ + wasm_on_header_value: (p, at, len) => { + assert(currentParser.ptr === p) + const start = at - currentBufferPtr + currentBufferRef.byteOffset + return currentParser.onHeaderValue(new FastBuffer(currentBufferRef.buffer, start, len)) + }, + /** + * @param {number} p + * @param {number} statusCode + * @param {0|1} upgrade + * @param {0|1} shouldKeepAlive + * @returns {number} + */ + wasm_on_headers_complete: (p, statusCode, upgrade, shouldKeepAlive) => { + assert(currentParser.ptr === p) + return currentParser.onHeadersComplete(statusCode, upgrade === 1, shouldKeepAlive === 1) + }, + /** + * @param {number} p + * @param {number} at + * @param {number} len + * @returns {number} + */ + wasm_on_body: (p, at, len) => { + assert(currentParser.ptr === p) + const start = at - currentBufferPtr + currentBufferRef.byteOffset + return currentParser.onBody(new FastBuffer(currentBufferRef.buffer, start, len)) + }, + /** + * @param {number} p + * @returns {number} + */ + wasm_on_message_complete: (p) => { + assert(currentParser.ptr === p) + return currentParser.onMessageComplete() + } - if (channels.connected.hasSubscribers) { - channels.connected.publish({ - connectParams: { - host, - hostname, - protocol, - port, - version: client[kHTTPContext]?.version, - servername: client[kServerName], - localAddress: client[kLocalAddress] - }, - connector: client[kConnector], - socket - }) } - - client.emit('connect', client[kUrl], [client]) - client[kResume]() }) } -function handleConnectError (client, err, { host, hostname, protocol, port }) { - if (client.destroyed) { - return - } - - client[kConnecting] = false - - if (channels.connectError.hasSubscribers) { - channels.connectError.publish({ - connectParams: { - host, - hostname, - protocol, - port, - version: client[kHTTPContext]?.version, - servername: client[kServerName], - localAddress: client[kLocalAddress] - }, - connector: client[kConnector], - error: err - }) - } +let llhttpInstance = null - if (err.code === 'ERR_TLS_CERT_ALTNAME_INVALID') { - assert(client[kRunning] === 0) - while (client[kPending] > 0 && client[kQueue][client[kPendingIdx]].servername === client[kServerName]) { - const request = client[kQueue][client[kPendingIdx]++] - util.errorRequest(client, request, err) - } - } else { - onError(client, err) - } +/** + * @type {Parser|null} + */ +let currentParser = null +let currentBufferRef = null +/** + * @type {number} + */ +let currentBufferSize = 0 +let currentBufferPtr = null - client.emit('connectionError', client[kUrl], [client], err) -} +const USE_NATIVE_TIMER = 0 +const USE_FAST_TIMER = 1 -function emitDrain (client) { - client[kNeedDrain] = 0 - client.emit('drain', client[kUrl], [client]) -} +// Use fast timers for headers and body to take eventual event loop +// latency into account. +const TIMEOUT_HEADERS = 2 | USE_FAST_TIMER +const TIMEOUT_BODY = 4 | USE_FAST_TIMER -function resume (client, sync) { - if (client[kResuming] === 2) { - return - } +// Use native timers to ignore event loop latency for keep-alive +// handling. +const TIMEOUT_KEEP_ALIVE = 8 | USE_NATIVE_TIMER - client[kResuming] = 2 +class Parser { + /** + * @param {import('./client.js')} client + * @param {import('net').Socket} socket + * @param {*} llhttp + */ + constructor (client, socket, { exports }) { + this.llhttp = exports + this.ptr = this.llhttp.llhttp_alloc(constants.TYPE.RESPONSE) + this.client = client + /** + * @type {import('net').Socket} + */ + this.socket = socket + this.timeout = null + this.timeoutValue = null + this.timeoutType = null + this.statusCode = 0 + this.statusText = '' + this.upgrade = false + this.headers = [] + this.headersSize = 0 + this.headersMaxSize = client[kMaxHeadersSize] + this.shouldKeepAlive = false + this.paused = false + this.resume = this.resume.bind(this) - _resume(client, sync) - client[kResuming] = 0 + this.bytesRead = 0 - if (client[kRunningIdx] > 256) { - client[kQueue].splice(0, client[kRunningIdx]) - client[kPendingIdx] -= client[kRunningIdx] - client[kRunningIdx] = 0 + this.keepAlive = '' + this.contentLength = '' + this.connection = '' + this.maxResponseSize = client[kMaxResponseSize] } -} - -function _resume (client, sync) { - while (true) { - if (client.destroyed) { - assert(client[kPending] === 0) - return - } - if (client[kClosedResolve] && !client[kSize]) { - client[kClosedResolve]() - client[kClosedResolve] = null - return - } + setTimeout (delay, type) { + // If the existing timer and the new timer are of different timer type + // (fast or native) or have different delay, we need to clear the existing + // timer and set a new one. + if ( + delay !== this.timeoutValue || + (type & USE_FAST_TIMER) ^ (this.timeoutType & USE_FAST_TIMER) + ) { + // If a timeout is already set, clear it with clearTimeout of the fast + // timer implementation, as it can clear fast and native timers. + if (this.timeout) { + timers.clearTimeout(this.timeout) + this.timeout = null + } - if (client[kHTTPContext]) { - client[kHTTPContext].resume() - } + if (delay) { + if (type & USE_FAST_TIMER) { + this.timeout = timers.setFastTimeout(onParserTimeout, delay, new WeakRef(this)) + } else { + this.timeout = setTimeout(onParserTimeout, delay, new WeakRef(this)) + this.timeout?.unref() + } + } - if (client[kBusy]) { - client[kNeedDrain] = 2 - } else if (client[kNeedDrain] === 2) { - if (sync) { - client[kNeedDrain] = 1 - queueMicrotask(() => emitDrain(client)) - } else { - emitDrain(client) + this.timeoutValue = delay + } else if (this.timeout) { + if (this.timeout.refresh) { + this.timeout.refresh() } - continue } - if (client[kPending] === 0) { - return - } + this.timeoutType = type + } - if (client[kRunning] >= (getPipelining(client) || 1)) { + resume () { + if (this.socket.destroyed || !this.paused) { return } - const request = client[kQueue][client[kPendingIdx]] - - if (client[kUrl].protocol === 'https:' && client[kServerName] !== request.servername) { - if (client[kRunning] > 0) { - return - } - - client[kServerName] = request.servername - client[kHTTPContext]?.destroy(new InformationalError('servername changed'), () => { - client[kHTTPContext] = null - resume(client) - }) - } - - if (client[kConnecting]) { - return - } + assert(this.ptr != null) + assert(currentParser === null) - if (!client[kHTTPContext]) { - connect(client) - return - } + this.llhttp.llhttp_resume(this.ptr) - if (client[kHTTPContext].destroyed) { - return + assert(this.timeoutType === TIMEOUT_BODY) + if (this.timeout) { + if (this.timeout.refresh) { + this.timeout.refresh() + } } - if (client[kHTTPContext].busy(request)) { - return - } + this.paused = false + this.execute(this.socket.read() || EMPTY_BUF) // Flush parser. + this.readMore() + } - if (!request.aborted && client[kHTTPContext].write(request)) { - client[kPendingIdx]++ - } else { - client[kQueue].splice(client[kPendingIdx], 1) + readMore () { + while (!this.paused && this.ptr) { + const chunk = this.socket.read() + if (chunk === null) { + break + } + this.execute(chunk) } } -} - -module.exports = Client + /** + * @param {Buffer} chunk + */ + execute (chunk) { + assert(currentParser === null) + assert(this.ptr != null) + assert(!this.paused) -/***/ }), + const { socket, llhttp } = this -/***/ 6612: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // Allocate a new buffer if the current buffer is too small. + if (chunk.length > currentBufferSize) { + if (currentBufferPtr) { + llhttp.free(currentBufferPtr) + } + // Allocate a buffer that is a multiple of 4096 bytes. + currentBufferSize = Math.ceil(chunk.length / 4096) * 4096 + currentBufferPtr = llhttp.malloc(currentBufferSize) + } -"use strict"; + new Uint8Array(llhttp.memory.buffer, currentBufferPtr, currentBufferSize).set(chunk) + // Call `execute` on the wasm parser. + // We pass the `llhttp_parser` pointer address, the pointer address of buffer view data, + // and finally the length of bytes to parse. + // The return value is an error code or `constants.ERROR.OK`. + try { + let ret -const Dispatcher = __nccwpck_require__(2096) -const UnwrapHandler = __nccwpck_require__(220) -const { - ClientDestroyedError, - ClientClosedError, - InvalidArgumentError -} = __nccwpck_require__(4928) -const { kDestroy, kClose, kClosed, kDestroyed, kDispatch } = __nccwpck_require__(9562) + try { + currentBufferRef = chunk + currentParser = this + ret = llhttp.llhttp_execute(this.ptr, currentBufferPtr, chunk.length) + } finally { + currentParser = null + currentBufferRef = null + } -const kOnDestroyed = Symbol('onDestroyed') -const kOnClosed = Symbol('onClosed') + if (ret !== constants.ERROR.OK) { + const data = chunk.subarray(llhttp.llhttp_get_error_pos(this.ptr) - currentBufferPtr) -class DispatcherBase extends Dispatcher { - /** @type {boolean} */ - [kDestroyed] = false; + if (ret === constants.ERROR.PAUSED_UPGRADE) { + this.onUpgrade(data) + } else if (ret === constants.ERROR.PAUSED) { + this.paused = true + socket.unshift(data) + } else { + const ptr = llhttp.llhttp_get_error_reason(this.ptr) + let message = '' + if (ptr) { + const len = new Uint8Array(llhttp.memory.buffer, ptr).indexOf(0) + message = + 'Response does not match the HTTP/1.1 protocol (' + + Buffer.from(llhttp.memory.buffer, ptr, len).toString() + + ')' + } + throw new HTTPParserError(message, constants.ERROR[ret], data) + } + } + } catch (err) { + util.destroy(socket, err) + } + } - /** @type {Array|null} */ - [kOnClosed] = null + this.timeout && timers.clearTimeout(this.timeout) + this.timeout = null + this.timeoutValue = null + this.timeoutType = null - /** @returns {boolean} */ - get destroyed () { - return this[kDestroyed] + this.paused = false } - /** @returns {boolean} */ - get closed () { - return this[kClosed] + /** + * @param {Buffer} buf + * @returns {0} + */ + onStatus (buf) { + this.statusText = buf.toString() + return 0 } - close (callback) { - if (callback === undefined) { - return new Promise((resolve, reject) => { - this.close((err, data) => { - return err ? reject(err) : resolve(data) - }) - }) - } + /** + * @returns {0|-1} + */ + onMessageBegin () { + const { socket, client } = this - if (typeof callback !== 'function') { - throw new InvalidArgumentError('invalid callback') + if (socket.destroyed) { + return -1 } - if (this[kDestroyed]) { - const err = new ClientDestroyedError() - queueMicrotask(() => callback(err, null)) - return + const request = client[kQueue][client[kRunningIdx]] + if (!request) { + return -1 } + request.onResponseStarted() - if (this[kClosed]) { - if (this[kOnClosed]) { - this[kOnClosed].push(callback) - } else { - queueMicrotask(() => callback(null, null)) - } - return - } + return 0 + } - this[kClosed] = true - this[kOnClosed] ??= [] - this[kOnClosed].push(callback) + /** + * @param {Buffer} buf + * @returns {number} + */ + onHeaderField (buf) { + const len = this.headers.length - const onClosed = () => { - const callbacks = this[kOnClosed] - this[kOnClosed] = null - for (let i = 0; i < callbacks.length; i++) { - callbacks[i](null, null) - } + if ((len & 1) === 0) { + this.headers.push(buf) + } else { + this.headers[len - 1] = Buffer.concat([this.headers[len - 1], buf]) } - // Should not error. - this[kClose]() - .then(() => this.destroy()) - .then(() => queueMicrotask(onClosed)) - } + this.trackHeader(buf.length) - destroy (err, callback) { - if (typeof err === 'function') { - callback = err - err = null - } + return 0 + } - if (callback === undefined) { - return new Promise((resolve, reject) => { - this.destroy(err, (err, data) => { - return err ? reject(err) : resolve(data) - }) - }) - } + /** + * @param {Buffer} buf + * @returns {number} + */ + onHeaderValue (buf) { + let len = this.headers.length - if (typeof callback !== 'function') { - throw new InvalidArgumentError('invalid callback') + if ((len & 1) === 1) { + this.headers.push(buf) + len += 1 + } else { + this.headers[len - 1] = Buffer.concat([this.headers[len - 1], buf]) } - if (this[kDestroyed]) { - if (this[kOnDestroyed]) { - this[kOnDestroyed].push(callback) - } else { - queueMicrotask(() => callback(null, null)) + const key = this.headers[len - 2] + if (key.length === 10) { + const headerName = util.bufferToLowerCasedHeaderName(key) + if (headerName === 'keep-alive') { + this.keepAlive += buf.toString() + } else if (headerName === 'connection') { + this.connection += buf.toString() } - return + } else if (key.length === 14 && util.bufferToLowerCasedHeaderName(key) === 'content-length') { + this.contentLength += buf.toString() } - if (!err) { - err = new ClientDestroyedError() - } + this.trackHeader(buf.length) - this[kDestroyed] = true - this[kOnDestroyed] ??= [] - this[kOnDestroyed].push(callback) + return 0 + } - const onDestroyed = () => { - const callbacks = this[kOnDestroyed] - this[kOnDestroyed] = null - for (let i = 0; i < callbacks.length; i++) { - callbacks[i](null, null) - } + /** + * @param {number} len + */ + trackHeader (len) { + this.headersSize += len + if (this.headersSize >= this.headersMaxSize) { + util.destroy(this.socket, new HeadersOverflowError()) } - - // Should not error. - this[kDestroy](err) - .then(() => queueMicrotask(onDestroyed)) } - dispatch (opts, handler) { - if (!handler || typeof handler !== 'object') { - throw new InvalidArgumentError('handler must be an object') - } + /** + * @param {Buffer} head + */ + onUpgrade (head) { + const { upgrade, client, socket, headers, statusCode } = this - handler = UnwrapHandler.unwrap(handler) + assert(upgrade) + assert(client[kSocket] === socket) + assert(!socket.destroyed) + assert(!this.paused) + assert((headers.length & 1) === 0) - try { - if (!opts || typeof opts !== 'object') { - throw new InvalidArgumentError('opts must be an object.') - } + const request = client[kQueue][client[kRunningIdx]] + assert(request) + assert(request.upgrade || request.method === 'CONNECT') - if (this[kDestroyed] || this[kOnDestroyed]) { - throw new ClientDestroyedError() - } + this.statusCode = 0 + this.statusText = '' + this.shouldKeepAlive = false - if (this[kClosed]) { - throw new ClientClosedError() - } + this.headers = [] + this.headersSize = 0 - return this[kDispatch](opts, handler) - } catch (err) { - if (typeof handler.onError !== 'function') { - throw err - } + socket.unshift(head) - handler.onError(err) + socket[kParser].destroy() + socket[kParser] = null - return false + socket[kClient] = null + socket[kError] = null + + removeAllListeners(socket) + + client[kSocket] = null + client[kHTTPContext] = null // TODO (fix): This is hacky... + client[kQueue][client[kRunningIdx]++] = null + client.emit('disconnect', client[kUrl], [client], new InformationalError('upgrade')) + + try { + request.onUpgrade(statusCode, headers, socket) + } catch (err) { + util.destroy(socket, err) } + + client[kResume]() } -} -module.exports = DispatcherBase + /** + * @param {number} statusCode + * @param {boolean} upgrade + * @param {boolean} shouldKeepAlive + * @returns {number} + */ + onHeadersComplete (statusCode, upgrade, shouldKeepAlive) { + const { client, socket, headers, statusText } = this + if (socket.destroyed) { + return -1 + } -/***/ }), + const request = client[kQueue][client[kRunningIdx]] -/***/ 2096: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + if (!request) { + return -1 + } -"use strict"; + assert(!this.upgrade) + assert(this.statusCode < 200) -const EventEmitter = __nccwpck_require__(8474) -const WrapHandler = __nccwpck_require__(3195) + if (statusCode === 100) { + util.destroy(socket, new SocketError('bad response', util.getSocketInfo(socket))) + return -1 + } -const wrapInterceptor = (dispatch) => (opts, handler) => dispatch(opts, WrapHandler.wrap(handler)) + /* this can only happen if server is misbehaving */ + if (upgrade && !request.upgrade) { + util.destroy(socket, new SocketError('bad upgrade', util.getSocketInfo(socket))) + return -1 + } -class Dispatcher extends EventEmitter { - dispatch () { - throw new Error('not implemented') - } + assert(this.timeoutType === TIMEOUT_HEADERS) - close () { - throw new Error('not implemented') - } + this.statusCode = statusCode + this.shouldKeepAlive = ( + shouldKeepAlive || + // Override llhttp value which does not allow keepAlive for HEAD. + (request.method === 'HEAD' && !socket[kReset] && this.connection.toLowerCase() === 'keep-alive') + ) - destroy () { - throw new Error('not implemented') - } + if (this.statusCode >= 200) { + const bodyTimeout = request.bodyTimeout != null + ? request.bodyTimeout + : client[kBodyTimeout] + this.setTimeout(bodyTimeout, TIMEOUT_BODY) + } else if (this.timeout) { + if (this.timeout.refresh) { + this.timeout.refresh() + } + } - compose (...args) { - // So we handle [interceptor1, interceptor2] or interceptor1, interceptor2, ... - const interceptors = Array.isArray(args[0]) ? args[0] : args - let dispatch = this.dispatch.bind(this) + if (request.method === 'CONNECT') { + assert(client[kRunning] === 1) + this.upgrade = true + return 2 + } - for (const interceptor of interceptors) { - if (interceptor == null) { - continue - } + if (upgrade) { + assert(client[kRunning] === 1) + this.upgrade = true + return 2 + } - if (typeof interceptor !== 'function') { - throw new TypeError(`invalid interceptor, expected function received ${typeof interceptor}`) - } + assert((this.headers.length & 1) === 0) + this.headers = [] + this.headersSize = 0 - dispatch = interceptor(dispatch) - dispatch = wrapInterceptor(dispatch) + if (this.shouldKeepAlive && client[kPipelining]) { + const keepAliveTimeout = this.keepAlive ? util.parseKeepAliveTimeout(this.keepAlive) : null - if (dispatch == null || typeof dispatch !== 'function' || dispatch.length !== 2) { - throw new TypeError('invalid interceptor') + if (keepAliveTimeout != null) { + const timeout = Math.min( + keepAliveTimeout - client[kKeepAliveTimeoutThreshold], + client[kKeepAliveMaxTimeout] + ) + if (timeout <= 0) { + socket[kReset] = true + } else { + client[kKeepAliveTimeoutValue] = timeout + } + } else { + client[kKeepAliveTimeoutValue] = client[kKeepAliveDefaultTimeout] } + } else { + // Stop more requests from being dispatched. + socket[kReset] = true } - return new Proxy(this, { - get: (target, key) => key === 'dispatch' ? dispatch : target[key] - }) - } -} + const pause = request.onHeaders(statusCode, headers, this.resume, statusText) === false -module.exports = Dispatcher + if (request.aborted) { + return -1 + } + if (request.method === 'HEAD') { + return 1 + } -/***/ }), + if (statusCode < 200) { + return 1 + } -/***/ 4646: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + if (socket[kBlocking]) { + socket[kBlocking] = false + client[kResume]() + } -"use strict"; + return pause ? constants.ERROR.PAUSED : 0 + } + /** + * @param {Buffer} buf + * @returns {number} + */ + onBody (buf) { + const { client, socket, statusCode, maxResponseSize } = this -const DispatcherBase = __nccwpck_require__(6612) -const { kClose, kDestroy, kClosed, kDestroyed, kDispatch, kNoProxyAgent, kHttpProxyAgent, kHttpsProxyAgent } = __nccwpck_require__(9562) -const ProxyAgent = __nccwpck_require__(7621) -const Agent = __nccwpck_require__(2004) + if (socket.destroyed) { + return -1 + } -const DEFAULT_PORTS = { - 'http:': 80, - 'https:': 443 -} + const request = client[kQueue][client[kRunningIdx]] + assert(request) -class EnvHttpProxyAgent extends DispatcherBase { - #noProxyValue = null - #noProxyEntries = null - #opts = null + assert(this.timeoutType === TIMEOUT_BODY) + if (this.timeout) { + if (this.timeout.refresh) { + this.timeout.refresh() + } + } - constructor (opts = {}) { - super() - this.#opts = opts + assert(statusCode >= 200) - const { httpProxy, httpsProxy, noProxy, ...agentOpts } = opts + if (maxResponseSize > -1 && this.bytesRead + buf.length > maxResponseSize) { + util.destroy(socket, new ResponseExceededMaxSizeError()) + return -1 + } - this[kNoProxyAgent] = new Agent(agentOpts) + this.bytesRead += buf.length - const HTTP_PROXY = httpProxy ?? process.env.http_proxy ?? process.env.HTTP_PROXY - if (HTTP_PROXY) { - this[kHttpProxyAgent] = new ProxyAgent({ ...agentOpts, uri: HTTP_PROXY }) - } else { - this[kHttpProxyAgent] = this[kNoProxyAgent] + if (request.onData(buf) === false) { + return constants.ERROR.PAUSED } - const HTTPS_PROXY = httpsProxy ?? process.env.https_proxy ?? process.env.HTTPS_PROXY - if (HTTPS_PROXY) { - this[kHttpsProxyAgent] = new ProxyAgent({ ...agentOpts, uri: HTTPS_PROXY }) - } else { - this[kHttpsProxyAgent] = this[kHttpProxyAgent] + return 0 + } + + /** + * @returns {number} + */ + onMessageComplete () { + const { client, socket, statusCode, upgrade, headers, contentLength, bytesRead, shouldKeepAlive } = this + + if (socket.destroyed && (!statusCode || shouldKeepAlive)) { + return -1 } - this.#parseNoProxy() - } + if (upgrade) { + return 0 + } - [kDispatch] (opts, handler) { - const url = new URL(opts.origin) - const agent = this.#getProxyAgentForUrl(url) - return agent.dispatch(opts, handler) - } + assert(statusCode >= 100) + assert((this.headers.length & 1) === 0) - [kClose] () { - return Promise.all([ - this[kNoProxyAgent].close(), - !this[kHttpProxyAgent][kClosed] && this[kHttpProxyAgent].close(), - !this[kHttpsProxyAgent][kClosed] && this[kHttpsProxyAgent].close() - ]) - } + const request = client[kQueue][client[kRunningIdx]] + assert(request) - [kDestroy] (err) { - return Promise.all([ - this[kNoProxyAgent].destroy(err), - !this[kHttpProxyAgent][kDestroyed] && this[kHttpProxyAgent].destroy(err), - !this[kHttpsProxyAgent][kDestroyed] && this[kHttpsProxyAgent].destroy(err) - ]) - } + this.statusCode = 0 + this.statusText = '' + this.bytesRead = 0 + this.contentLength = '' + this.keepAlive = '' + this.connection = '' - #getProxyAgentForUrl (url) { - let { protocol, host: hostname, port } = url + this.headers = [] + this.headersSize = 0 - // Stripping ports in this way instead of using parsedUrl.hostname to make - // sure that the brackets around IPv6 addresses are kept. - hostname = hostname.replace(/:\d*$/, '').toLowerCase() - port = Number.parseInt(port, 10) || DEFAULT_PORTS[protocol] || 0 - if (!this.#shouldProxy(hostname, port)) { - return this[kNoProxyAgent] - } - if (protocol === 'https:') { - return this[kHttpsProxyAgent] + if (statusCode < 200) { + return 0 } - return this[kHttpProxyAgent] - } - #shouldProxy (hostname, port) { - if (this.#noProxyChanged) { - this.#parseNoProxy() + if (request.method !== 'HEAD' && contentLength && bytesRead !== parseInt(contentLength, 10)) { + util.destroy(socket, new ResponseContentLengthMismatchError()) + return -1 } - if (this.#noProxyEntries.length === 0) { - return true // Always proxy if NO_PROXY is not set or empty. - } - if (this.#noProxyValue === '*') { - return false // Never proxy if wildcard is set. - } + request.onComplete(headers) - for (let i = 0; i < this.#noProxyEntries.length; i++) { - const entry = this.#noProxyEntries[i] - if (entry.port && entry.port !== port) { - continue // Skip if ports don't match. - } - if (!/^[.*]/.test(entry.hostname)) { - // No wildcards, so don't proxy only if there is not an exact match. - if (hostname === entry.hostname) { - return false - } - } else { - // Don't proxy if the hostname ends with the no_proxy host. - if (hostname.endsWith(entry.hostname.replace(/^\*/, ''))) { - return false - } - } - } - - return true - } - - #parseNoProxy () { - const noProxyValue = this.#opts.noProxy ?? this.#noProxyEnv - const noProxySplit = noProxyValue.split(/[,\s]/) - const noProxyEntries = [] + client[kQueue][client[kRunningIdx]++] = null - for (let i = 0; i < noProxySplit.length; i++) { - const entry = noProxySplit[i] - if (!entry) { - continue - } - const parsed = entry.match(/^(.+):(\d+)$/) - noProxyEntries.push({ - hostname: (parsed ? parsed[1] : entry).toLowerCase(), - port: parsed ? Number.parseInt(parsed[2], 10) : 0 - }) + if (socket[kWriting]) { + assert(client[kRunning] === 0) + // Response completed before request. + util.destroy(socket, new InformationalError('reset')) + return constants.ERROR.PAUSED + } else if (!shouldKeepAlive) { + util.destroy(socket, new InformationalError('reset')) + return constants.ERROR.PAUSED + } else if (socket[kReset] && client[kRunning] === 0) { + // Destroy socket once all requests have completed. + // The request at the tail of the pipeline is the one + // that requested reset and no further requests should + // have been queued since then. + util.destroy(socket, new InformationalError('reset')) + return constants.ERROR.PAUSED + } else if (client[kPipelining] == null || client[kPipelining] === 1) { + // We must wait a full event loop cycle to reuse this socket to make sure + // that non-spec compliant servers are not closing the connection even if they + // said they won't. + setImmediate(client[kResume]) + } else { + client[kResume]() } - this.#noProxyValue = noProxyValue - this.#noProxyEntries = noProxyEntries + return 0 } +} - get #noProxyChanged () { - if (this.#opts.noProxy !== undefined) { - return false - } - return this.#noProxyValue !== this.#noProxyEnv +function onParserTimeout (parserWeakRef) { + const parser = parserWeakRef.deref() + if (!parser) { + return } - get #noProxyEnv () { - return process.env.no_proxy ?? process.env.NO_PROXY ?? '' + const { socket, timeoutType, client, paused } = parser + + if (timeoutType === TIMEOUT_HEADERS) { + if (!socket[kWriting] || socket.writableNeedDrain || client[kRunning] > 1) { + assert(!paused, 'cannot be paused while waiting for headers') + util.destroy(socket, new HeadersTimeoutError()) + } + } else if (timeoutType === TIMEOUT_BODY) { + if (!paused) { + util.destroy(socket, new BodyTimeoutError()) + } + } else if (timeoutType === TIMEOUT_KEEP_ALIVE) { + assert(client[kRunning] === 0 && client[kKeepAliveTimeoutValue]) + util.destroy(socket, new InformationalError('socket idle timeout')) } } -module.exports = EnvHttpProxyAgent - +/** + * @param {import ('./client.js')} client + * @param {import('net').Socket} socket + * @returns + */ +function connectH1 (client, socket) { + client[kSocket] = socket -/***/ }), + if (!llhttpInstance) { + llhttpInstance = lazyllhttp() + } -/***/ 6677: -/***/ ((module) => { + if (socket.errored) { + throw socket.errored + } -"use strict"; + if (socket.destroyed) { + throw new SocketError('destroyed') + } + socket[kNoRef] = false + socket[kWriting] = false + socket[kReset] = false + socket[kBlocking] = false + socket[kParser] = new Parser(client, socket, llhttpInstance) -// Extracted from node/lib/internal/fixed_queue.js + util.addListener(socket, 'error', onHttpSocketError) + util.addListener(socket, 'readable', onHttpSocketReadable) + util.addListener(socket, 'end', onHttpSocketEnd) + util.addListener(socket, 'close', onHttpSocketClose) -// Currently optimal queue size, tested on V8 6.0 - 6.6. Must be power of two. -const kSize = 2048 -const kMask = kSize - 1 + socket[kClosed] = false + socket.on('close', onSocketClose) -// The FixedQueue is implemented as a singly-linked list of fixed-size -// circular buffers. It looks something like this: -// -// head tail -// | | -// v v -// +-----------+ <-----\ +-----------+ <------\ +-----------+ -// | [null] | \----- | next | \------- | next | -// +-----------+ +-----------+ +-----------+ -// | item | <-- bottom | item | <-- bottom | undefined | -// | item | | item | | undefined | -// | item | | item | | undefined | -// | item | | item | | undefined | -// | item | | item | bottom --> | item | -// | item | | item | | item | -// | ... | | ... | | ... | -// | item | | item | | item | -// | item | | item | | item | -// | undefined | <-- top | item | | item | -// | undefined | | item | | item | -// | undefined | | undefined | <-- top top --> | undefined | -// +-----------+ +-----------+ +-----------+ -// -// Or, if there is only one circular buffer, it looks something -// like either of these: -// -// head tail head tail -// | | | | -// v v v v -// +-----------+ +-----------+ -// | [null] | | [null] | -// +-----------+ +-----------+ -// | undefined | | item | -// | undefined | | item | -// | item | <-- bottom top --> | undefined | -// | item | | undefined | -// | undefined | <-- top bottom --> | item | -// | undefined | | item | -// +-----------+ +-----------+ -// -// Adding a value means moving `top` forward by one, removing means -// moving `bottom` forward by one. After reaching the end, the queue -// wraps around. -// -// When `top === bottom` the current queue is empty and when -// `top + 1 === bottom` it's full. This wastes a single space of storage -// but allows much quicker checks. + return { + version: 'h1', + defaultPipelining: 1, + write (request) { + return writeH1(client, request) + }, + resume () { + resumeH1(client) + }, + /** + * @param {Error|undefined} err + * @param {() => void} callback + */ + destroy (err, callback) { + if (socket[kClosed]) { + queueMicrotask(callback) + } else { + socket.on('close', callback) + socket.destroy(err) + } + }, + /** + * @returns {boolean} + */ + get destroyed () { + return socket.destroyed + }, + /** + * @param {import('../core/request.js')} request + * @returns {boolean} + */ + busy (request) { + if (socket[kWriting] || socket[kReset] || socket[kBlocking]) { + return true + } -/** - * @type {FixedCircularBuffer} - * @template T - */ -class FixedCircularBuffer { - /** @type {number} */ - bottom = 0 - /** @type {number} */ - top = 0 - /** @type {Array} */ - list = new Array(kSize).fill(undefined) - /** @type {T|null} */ - next = null + if (request) { + if (client[kRunning] > 0 && !request.idempotent) { + // Non-idempotent request cannot be retried. + // Ensure that no other requests are inflight and + // could cause failure. + return true + } - /** @returns {boolean} */ - isEmpty () { - return this.top === this.bottom - } + if (client[kRunning] > 0 && (request.upgrade || request.method === 'CONNECT')) { + // Don't dispatch an upgrade until all preceding requests have completed. + // A misbehaving server might upgrade the connection before all pipelined + // request has completed. + return true + } - /** @returns {boolean} */ - isFull () { - return ((this.top + 1) & kMask) === this.bottom - } + if (client[kRunning] > 0 && util.bodyLength(request.body) !== 0 && + (util.isStream(request.body) || util.isAsyncIterable(request.body) || util.isFormDataLike(request.body))) { + // Request with stream or iterator body can error while other requests + // are inflight and indirectly error those as well. + // Ensure this doesn't happen by waiting for inflight + // to complete before dispatching. - /** - * @param {T} data - * @returns {void} - */ - push (data) { - this.list[this.top] = data - this.top = (this.top + 1) & kMask - } + // Request with stream or iterator body cannot be retried. + // Ensure that no other requests are inflight and + // could cause failure. + return true + } + } - /** @returns {T|null} */ - shift () { - const nextItem = this.list[this.bottom] - if (nextItem === undefined) { return null } - this.list[this.bottom] = undefined - this.bottom = (this.bottom + 1) & kMask - return nextItem + return false + } } } -/** - * @template T - */ -module.exports = class FixedQueue { - constructor () { - /** @type {FixedCircularBuffer} */ - this.head = this.tail = new FixedCircularBuffer() - } +function onHttpSocketError (err) { + assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID') - /** @returns {boolean} */ - isEmpty () { - return this.head.isEmpty() - } + const parser = this[kParser] - /** @param {T} data */ - push (data) { - if (this.head.isFull()) { - // Head is full: Creates a new queue, sets the old queue's `.next` to it, - // and sets it as the new main queue. - this.head = this.head.next = new FixedCircularBuffer() - } - this.head.push(data) + // On Mac OS, we get an ECONNRESET even if there is a full body to be forwarded + // to the user. + if (err.code === 'ECONNRESET' && parser.statusCode && !parser.shouldKeepAlive) { + // We treat all incoming data so for as a valid response. + parser.onMessageComplete() + return } - /** @returns {T|null} */ - shift () { - const tail = this.tail - const next = tail.shift() - if (tail.isEmpty() && tail.next !== null) { - // If there is another queue, it forms the new tail. - this.tail = tail.next - tail.next = null - } - return next - } -} + this[kError] = err + this[kClient][kOnError](err) +} -/***/ }), +function onHttpSocketReadable () { + this[kParser]?.readMore() +} -/***/ 8036: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +function onHttpSocketEnd () { + const parser = this[kParser] -"use strict"; + if (parser.statusCode && !parser.shouldKeepAlive) { + // We treat all incoming data so far as a valid response. + parser.onMessageComplete() + return + } + util.destroy(this, new SocketError('other side closed', util.getSocketInfo(this))) +} -const { InvalidArgumentError } = __nccwpck_require__(4928) -const Client = __nccwpck_require__(226) +function onHttpSocketClose () { + const parser = this[kParser] -class H2CClient extends Client { - constructor (origin, clientOpts) { - if (typeof origin === 'string') { - origin = new URL(origin) + if (parser) { + if (!this[kError] && parser.statusCode && !parser.shouldKeepAlive) { + // We treat all incoming data so far as a valid response. + parser.onMessageComplete() } - if (origin.protocol !== 'http:') { - throw new InvalidArgumentError( - 'h2c-client: Only h2c protocol is supported' - ) - } + this[kParser].destroy() + this[kParser] = null + } - const { connect, maxConcurrentStreams, pipelining, ...opts } = - clientOpts ?? {} - let defaultMaxConcurrentStreams = 100 - let defaultPipelining = 100 + const err = this[kError] || new SocketError('closed', util.getSocketInfo(this)) - if ( - maxConcurrentStreams != null && - Number.isInteger(maxConcurrentStreams) && - maxConcurrentStreams > 0 - ) { - defaultMaxConcurrentStreams = maxConcurrentStreams - } + const client = this[kClient] - if (pipelining != null && Number.isInteger(pipelining) && pipelining > 0) { - defaultPipelining = pipelining - } + client[kSocket] = null + client[kHTTPContext] = null // TODO (fix): This is hacky... - if (defaultPipelining > defaultMaxConcurrentStreams) { - throw new InvalidArgumentError( - 'h2c-client: pipelining cannot be greater than maxConcurrentStreams' - ) + if (client.destroyed) { + assert(client[kPending] === 0) + + // Fail entire queue. + const requests = client[kQueue].splice(client[kRunningIdx]) + for (let i = 0; i < requests.length; i++) { + const request = requests[i] + util.errorRequest(client, request, err) } + } else if (client[kRunning] > 0 && err.code !== 'UND_ERR_INFO') { + // Fail head of pipeline. + const request = client[kQueue][client[kRunningIdx]] + client[kQueue][client[kRunningIdx]++] = null - super(origin, { - ...opts, - maxConcurrentStreams: defaultMaxConcurrentStreams, - pipelining: defaultPipelining, - allowH2: true, - useH2c: true - }) + util.errorRequest(client, request, err) } -} -module.exports = H2CClient - - -/***/ }), + client[kPendingIdx] = client[kRunningIdx] -/***/ 6469: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + assert(client[kRunning] === 0) -"use strict"; + client.emit('disconnect', client[kUrl], [client], err) + client[kResume]() +} -const { PoolStats } = __nccwpck_require__(7755) -const DispatcherBase = __nccwpck_require__(6612) -const FixedQueue = __nccwpck_require__(6677) -const { kConnected, kSize, kRunning, kPending, kQueued, kBusy, kFree, kUrl, kClose, kDestroy, kDispatch } = __nccwpck_require__(9562) +function onSocketClose () { + this[kClosed] = true +} -const kClients = Symbol('clients') -const kNeedDrain = Symbol('needDrain') -const kQueue = Symbol('queue') -const kClosedResolve = Symbol('closed resolve') -const kOnDrain = Symbol('onDrain') -const kOnConnect = Symbol('onConnect') -const kOnDisconnect = Symbol('onDisconnect') -const kOnConnectionError = Symbol('onConnectionError') -const kGetDispatcher = Symbol('get dispatcher') -const kAddClient = Symbol('add client') -const kRemoveClient = Symbol('remove client') +/** + * @param {import('./client.js')} client + */ +function resumeH1 (client) { + const socket = client[kSocket] -class PoolBase extends DispatcherBase { - [kQueue] = new FixedQueue(); + if (socket && !socket.destroyed) { + if (client[kSize] === 0) { + if (!socket[kNoRef] && socket.unref) { + socket.unref() + socket[kNoRef] = true + } + } else if (socket[kNoRef] && socket.ref) { + socket.ref() + socket[kNoRef] = false + } - [kQueued] = 0; + if (client[kSize] === 0) { + if (socket[kParser].timeoutType !== TIMEOUT_KEEP_ALIVE) { + socket[kParser].setTimeout(client[kKeepAliveTimeoutValue], TIMEOUT_KEEP_ALIVE) + } + } else if (client[kRunning] > 0 && socket[kParser].statusCode < 200) { + if (socket[kParser].timeoutType !== TIMEOUT_HEADERS) { + const request = client[kQueue][client[kRunningIdx]] + const headersTimeout = request.headersTimeout != null + ? request.headersTimeout + : client[kHeadersTimeout] + socket[kParser].setTimeout(headersTimeout, TIMEOUT_HEADERS) + } + } + } +} - [kClients] = []; +// https://www.rfc-editor.org/rfc/rfc7230#section-3.3.2 +function shouldSendContentLength (method) { + return method !== 'GET' && method !== 'HEAD' && method !== 'OPTIONS' && method !== 'TRACE' && method !== 'CONNECT' +} - [kNeedDrain] = false; +/** + * @param {import('./client.js')} client + * @param {import('../core/request.js')} request + * @returns + */ +function writeH1 (client, request) { + const { method, path, host, upgrade, blocking, reset } = request - [kOnDrain] (client, origin, targets) { - const queue = this[kQueue] + let { body, headers, contentLength } = request - let needDrain = false + // https://tools.ietf.org/html/rfc7231#section-4.3.1 + // https://tools.ietf.org/html/rfc7231#section-4.3.2 + // https://tools.ietf.org/html/rfc7231#section-4.3.5 - while (!needDrain) { - const item = queue.shift() - if (!item) { - break - } - this[kQueued]-- - needDrain = !client.dispatch(item.opts, item.handler) - } + // Sending a payload body on a request that does not + // expect it can cause undefined behavior on some + // servers and corrupt connection state. Do not + // re-use the connection for further requests. - client[kNeedDrain] = needDrain + const expectsPayload = ( + method === 'PUT' || + method === 'POST' || + method === 'PATCH' || + method === 'QUERY' || + method === 'PROPFIND' || + method === 'PROPPATCH' + ) - if (!needDrain && this[kNeedDrain]) { - this[kNeedDrain] = false - this.emit('drain', origin, [this, ...targets]) + if (util.isFormDataLike(body)) { + if (!extractBody) { + extractBody = (__nccwpck_require__(9742).extractBody) } - if (this[kClosedResolve] && queue.isEmpty()) { - const closeAll = new Array(this[kClients].length) - for (let i = 0; i < this[kClients].length; i++) { - closeAll[i] = this[kClients][i].close() - } - return Promise.all(closeAll) - .then(this[kClosedResolve]) + const [bodyStream, contentType] = extractBody(body) + if (request.contentType == null) { + headers.push('content-type', contentType) } + body = bodyStream.stream + contentLength = bodyStream.length + } else if (util.isBlobLike(body) && request.contentType == null && body.type) { + headers.push('content-type', body.type) } - [kOnConnect] = (origin, targets) => { - this.emit('connect', origin, [this, ...targets]) - }; + if (body && typeof body.read === 'function') { + // Try to read EOF in order to get length. + body.read(0) + } - [kOnDisconnect] = (origin, targets, err) => { - this.emit('disconnect', origin, [this, ...targets], err) - }; + const bodyLength = util.bodyLength(body) - [kOnConnectionError] = (origin, targets, err) => { - this.emit('connectionError', origin, [this, ...targets], err) - } + contentLength = bodyLength ?? contentLength - get [kBusy] () { - return this[kNeedDrain] + if (contentLength === null) { + contentLength = request.contentLength } - get [kConnected] () { - let ret = 0 - for (const { [kConnected]: connected } of this[kClients]) { - ret += connected - } - return ret + if (contentLength === 0 && !expectsPayload) { + // https://tools.ietf.org/html/rfc7230#section-3.3.2 + // A user agent SHOULD NOT send a Content-Length header field when + // the request message does not contain a payload body and the method + // semantics do not anticipate such a body. + + contentLength = null } - get [kFree] () { - let ret = 0 - for (const { [kConnected]: connected, [kNeedDrain]: needDrain } of this[kClients]) { - ret += connected && !needDrain + // https://github.com/nodejs/undici/issues/2046 + // A user agent may send a Content-Length header with 0 value, this should be allowed. + if (shouldSendContentLength(method) && contentLength > 0 && request.contentLength !== null && request.contentLength !== contentLength) { + if (client[kStrictContentLength]) { + util.errorRequest(client, request, new RequestContentLengthMismatchError()) + return false } - return ret + + process.emitWarning(new RequestContentLengthMismatchError()) } - get [kPending] () { - let ret = this[kQueued] - for (const { [kPending]: pending } of this[kClients]) { - ret += pending + const socket = client[kSocket] + + /** + * @param {Error} [err] + * @returns {void} + */ + const abort = (err) => { + if (request.aborted || request.completed) { + return } - return ret + + util.errorRequest(client, request, err || new RequestAbortedError()) + + util.destroy(body) + util.destroy(socket, new InformationalError('aborted')) } - get [kRunning] () { - let ret = 0 - for (const { [kRunning]: running } of this[kClients]) { - ret += running - } - return ret + try { + request.onConnect(abort) + } catch (err) { + util.errorRequest(client, request, err) } - get [kSize] () { - let ret = this[kQueued] - for (const { [kSize]: size } of this[kClients]) { - ret += size - } - return ret + if (request.aborted) { + return false } - get stats () { - return new PoolStats(this) + if (method === 'HEAD') { + // https://github.com/mcollina/undici/issues/258 + // Close after a HEAD request to interop with misbehaving servers + // that may send a body in the response. + + socket[kReset] = true } - [kClose] () { - if (this[kQueue].isEmpty()) { - const closeAll = new Array(this[kClients].length) - for (let i = 0; i < this[kClients].length; i++) { - closeAll[i] = this[kClients][i].close() - } - return Promise.all(closeAll) - } else { - return new Promise((resolve) => { - this[kClosedResolve] = resolve - }) - } + if (upgrade || method === 'CONNECT') { + // On CONNECT or upgrade, block pipeline from dispatching further + // requests on this connection. + + socket[kReset] = true } - [kDestroy] (err) { - while (true) { - const item = this[kQueue].shift() - if (!item) { - break - } - item.handler.onError(err) - } + if (reset != null) { + socket[kReset] = reset + } - const destroyAll = new Array(this[kClients].length) - for (let i = 0; i < this[kClients].length; i++) { - destroyAll[i] = this[kClients][i].destroy(err) - } - return Promise.all(destroyAll) + if (client[kMaxRequests] && socket[kCounter]++ >= client[kMaxRequests]) { + socket[kReset] = true } - [kDispatch] (opts, handler) { - const dispatcher = this[kGetDispatcher]() + if (blocking) { + socket[kBlocking] = true + } - if (!dispatcher) { - this[kNeedDrain] = true - this[kQueue].push({ opts, handler }) - this[kQueued]++ - } else if (!dispatcher.dispatch(opts, handler)) { - dispatcher[kNeedDrain] = true - this[kNeedDrain] = !this[kGetDispatcher]() - } + let header = `${method} ${path} HTTP/1.1\r\n` - return !this[kNeedDrain] + if (typeof host === 'string') { + header += `host: ${host}\r\n` + } else { + header += client[kHostHeader] } - [kAddClient] (client) { - client - .on('drain', this[kOnDrain].bind(this, client)) - .on('connect', this[kOnConnect]) - .on('disconnect', this[kOnDisconnect]) - .on('connectionError', this[kOnConnectionError]) + if (upgrade) { + header += `connection: upgrade\r\nupgrade: ${upgrade}\r\n` + } else if (client[kPipelining] && !socket[kReset]) { + header += 'connection: keep-alive\r\n' + } else { + header += 'connection: close\r\n' + } - this[kClients].push(client) + if (Array.isArray(headers)) { + for (let n = 0; n < headers.length; n += 2) { + const key = headers[n + 0] + const val = headers[n + 1] - if (this[kNeedDrain]) { - queueMicrotask(() => { - if (this[kNeedDrain]) { - this[kOnDrain](client, client[kUrl], [client, this]) + if (Array.isArray(val)) { + for (let i = 0; i < val.length; i++) { + header += `${key}: ${val[i]}\r\n` } - }) + } else { + header += `${key}: ${val}\r\n` + } } - - return this } - [kRemoveClient] (client) { - client.close(() => { - const idx = this[kClients].indexOf(client) - if (idx !== -1) { - this[kClients].splice(idx, 1) - } - }) + if (channels.sendHeaders.hasSubscribers) { + channels.sendHeaders.publish({ request, headers: header, socket }) + } - this[kNeedDrain] = this[kClients].some(dispatcher => ( - !dispatcher[kNeedDrain] && - dispatcher.closed !== true && - dispatcher.destroyed !== true - )) + if (!body || bodyLength === 0) { + writeBuffer(abort, null, client, request, socket, contentLength, header, expectsPayload) + } else if (util.isBuffer(body)) { + writeBuffer(abort, body, client, request, socket, contentLength, header, expectsPayload) + } else if (util.isBlobLike(body)) { + if (typeof body.stream === 'function') { + writeIterable(abort, body.stream(), client, request, socket, contentLength, header, expectsPayload) + } else { + writeBlob(abort, body, client, request, socket, contentLength, header, expectsPayload) + } + } else if (util.isStream(body)) { + writeStream(abort, body, client, request, socket, contentLength, header, expectsPayload) + } else if (util.isIterable(body)) { + writeIterable(abort, body, client, request, socket, contentLength, header, expectsPayload) + } else { + assert(false) } -} -module.exports = { - PoolBase, - kClients, - kNeedDrain, - kAddClient, - kRemoveClient, - kGetDispatcher + return true } +/** + * @param {AbortCallback} abort + * @param {import('stream').Stream} body + * @param {import('./client.js')} client + * @param {import('../core/request.js')} request + * @param {import('net').Socket} socket + * @param {number} contentLength + * @param {string} header + * @param {boolean} expectsPayload + */ +function writeStream (abort, body, client, request, socket, contentLength, header, expectsPayload) { + assert(contentLength !== 0 || client[kRunning] === 0, 'stream body cannot be pipelined') -/***/ }), - -/***/ 8767: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -"use strict"; - - -const { - PoolBase, - kClients, - kNeedDrain, - kAddClient, - kGetDispatcher, - kRemoveClient -} = __nccwpck_require__(6469) -const Client = __nccwpck_require__(226) -const { - InvalidArgumentError -} = __nccwpck_require__(4928) -const util = __nccwpck_require__(983) -const { kUrl } = __nccwpck_require__(9562) -const buildConnector = __nccwpck_require__(978) - -const kOptions = Symbol('options') -const kConnections = Symbol('connections') -const kFactory = Symbol('factory') + let finished = false -function defaultFactory (origin, opts) { - return new Client(origin, opts) -} + const writer = new AsyncWriter({ abort, socket, request, contentLength, client, expectsPayload, header }) -class Pool extends PoolBase { - constructor (origin, { - connections, - factory = defaultFactory, - connect, - connectTimeout, - tls, - maxCachedSessions, - socketPath, - autoSelectFamily, - autoSelectFamilyAttemptTimeout, - allowH2, - clientTtl, - ...options - } = {}) { - if (connections != null && (!Number.isFinite(connections) || connections < 0)) { - throw new InvalidArgumentError('invalid connections') + /** + * @param {Buffer} chunk + * @returns {void} + */ + const onData = function (chunk) { + if (finished) { + return } - if (typeof factory !== 'function') { - throw new InvalidArgumentError('factory must be a function.') + try { + if (!writer.write(chunk) && this.pause) { + this.pause() + } + } catch (err) { + util.destroy(this, err) } + } - if (connect != null && typeof connect !== 'function' && typeof connect !== 'object') { - throw new InvalidArgumentError('connect must be a function or an object') + /** + * @returns {void} + */ + const onDrain = function () { + if (finished) { + return } - if (typeof connect !== 'function') { - connect = buildConnector({ - ...tls, - maxCachedSessions, - allowH2, - socketPath, - timeout: connectTimeout, - ...(typeof autoSelectFamily === 'boolean' ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : undefined), - ...connect - }) + if (body.resume) { + body.resume() } + } - super() - - this[kConnections] = connections || null - this[kUrl] = util.parseOrigin(origin) - this[kOptions] = { ...util.deepClone(options), connect, allowH2, clientTtl } - this[kOptions].interceptors = options.interceptors - ? { ...options.interceptors } - : undefined - this[kFactory] = factory - - this.on('connect', (origin, targets) => { - if (clientTtl != null && clientTtl > 0) { - for (const target of targets) { - Object.assign(target, { ttl: Date.now() }) - } - } - }) - - this.on('connectionError', (origin, targets, error) => { - // If a connection error occurs, we remove the client from the pool, - // and emit a connectionError event. They will not be re-used. - // Fixes https://github.com/nodejs/undici/issues/3895 - for (const target of targets) { - // Do not use kRemoveClient here, as it will close the client, - // but the client cannot be closed in this state. - const idx = this[kClients].indexOf(target) - if (idx !== -1) { - this[kClients].splice(idx, 1) - } - } + /** + * @returns {void} + */ + const onClose = function () { + // 'close' might be emitted *before* 'error' for + // broken streams. Wait a tick to avoid this case. + queueMicrotask(() => { + // It's only safe to remove 'error' listener after + // 'close'. + body.removeListener('error', onFinished) }) - } - [kGetDispatcher] () { - const clientTtlOption = this[kOptions].clientTtl - for (const client of this[kClients]) { - // check ttl of client and if it's stale, remove it from the pool - if (clientTtlOption != null && clientTtlOption > 0 && client.ttl && ((Date.now() - client.ttl) > clientTtlOption)) { - this[kRemoveClient](client) - } else if (!client[kNeedDrain]) { - return client - } + if (!finished) { + const err = new RequestAbortedError() + queueMicrotask(() => onFinished(err)) } + } - if (!this[kConnections] || this[kClients].length < this[kConnections]) { - const dispatcher = this[kFactory](this[kUrl], this[kOptions]) - this[kAddClient](dispatcher) - return dispatcher + /** + * @param {Error} [err] + * @returns + */ + const onFinished = function (err) { + if (finished) { + return } - } -} -module.exports = Pool + finished = true + assert(socket.destroyed || (socket[kWriting] && client[kRunning] <= 1)) -/***/ }), + socket + .off('drain', onDrain) + .off('error', onFinished) -/***/ 7621: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + body + .removeListener('data', onData) + .removeListener('end', onFinished) + .removeListener('close', onClose) -"use strict"; + if (!err) { + try { + writer.end() + } catch (er) { + err = er + } + } + writer.destroy(err) -const { kProxy, kClose, kDestroy, kDispatch } = __nccwpck_require__(9562) -const Agent = __nccwpck_require__(2004) -const Pool = __nccwpck_require__(8767) -const DispatcherBase = __nccwpck_require__(6612) -const { InvalidArgumentError, RequestAbortedError, SecureProxyConnectionError } = __nccwpck_require__(4928) -const buildConnector = __nccwpck_require__(978) -const Client = __nccwpck_require__(226) -const { channels } = __nccwpck_require__(6591) + if (err && (err.code !== 'UND_ERR_INFO' || err.message !== 'reset')) { + util.destroy(body, err) + } else { + util.destroy(body) + } + } -const kAgent = Symbol('proxy agent') -const kClient = Symbol('proxy client') -const kProxyHeaders = Symbol('proxy headers') -const kRequestTls = Symbol('request tls settings') -const kProxyTls = Symbol('proxy tls settings') -const kConnectEndpoint = Symbol('connect endpoint function') -const kTunnelProxy = Symbol('tunnel proxy') + body + .on('data', onData) + .on('end', onFinished) + .on('error', onFinished) + .on('close', onClose) -function defaultProtocolPort (protocol) { - return protocol === 'https:' ? 443 : 80 -} + if (body.resume) { + body.resume() + } -function defaultFactory (origin, opts) { - return new Pool(origin, opts) -} + socket + .on('drain', onDrain) + .on('error', onFinished) -const noop = () => {} + if (body.errorEmitted ?? body.errored) { + setImmediate(onFinished, body.errored) + } else if (body.endEmitted ?? body.readableEnded) { + setImmediate(onFinished, null) + } -function defaultAgentFactory (origin, opts) { - if (opts.connections === 1) { - return new Client(origin, opts) + if (body.closeEmitted ?? body.closed) { + setImmediate(onClose) } - return new Pool(origin, opts) } -class Http1ProxyWrapper extends DispatcherBase { - #client - - constructor (proxyUrl, { headers = {}, connect, factory }) { - if (!proxyUrl) { - throw new InvalidArgumentError('Proxy URL is mandatory') - } +/** + * @typedef AbortCallback + * @type {Function} + * @param {Error} [err] + * @returns {void} + */ - super() +/** + * @param {AbortCallback} abort + * @param {Uint8Array|null} body + * @param {import('./client.js')} client + * @param {import('../core/request.js')} request + * @param {import('net').Socket} socket + * @param {number} contentLength + * @param {string} header + * @param {boolean} expectsPayload + * @returns {void} + */ +function writeBuffer (abort, body, client, request, socket, contentLength, header, expectsPayload) { + try { + if (!body) { + if (contentLength === 0) { + socket.write(`${header}content-length: 0\r\n\r\n`, 'latin1') + } else { + assert(contentLength === null, 'no body must not have content length') + socket.write(`${header}\r\n`, 'latin1') + } + } else if (util.isBuffer(body)) { + assert(contentLength === body.byteLength, 'buffer body must have content length') - this[kProxyHeaders] = headers - if (factory) { - this.#client = factory(proxyUrl, { connect }) - } else { - this.#client = new Client(proxyUrl, { connect }) - } - } + socket.cork() + socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'latin1') + socket.write(body) + socket.uncork() + request.onBodySent(body) - [kDispatch] (opts, handler) { - const onHeaders = handler.onHeaders - handler.onHeaders = function (statusCode, data, resume) { - if (statusCode === 407) { - if (typeof handler.onError === 'function') { - handler.onError(new InvalidArgumentError('Proxy Authentication Required (407)')) - } - return + if (!expectsPayload && request.reset !== false) { + socket[kReset] = true } - if (onHeaders) onHeaders.call(this, statusCode, data, resume) } + request.onRequestSent() - // Rewrite request as an HTTP1 Proxy request, without tunneling. - const { - origin, - path = '/', - headers = {} - } = opts + client[kResume]() + } catch (err) { + abort(err) + } +} - opts.path = origin + path +/** + * @param {AbortCallback} abort + * @param {Blob} body + * @param {import('./client.js')} client + * @param {import('../core/request.js')} request + * @param {import('net').Socket} socket + * @param {number} contentLength + * @param {string} header + * @param {boolean} expectsPayload + * @returns {Promise} + */ +async function writeBlob (abort, body, client, request, socket, contentLength, header, expectsPayload) { + assert(contentLength === body.size, 'blob body must have content length') - if (!('host' in headers) && !('Host' in headers)) { - const { host } = new URL(origin) - headers.host = host + try { + if (contentLength != null && contentLength !== body.size) { + throw new RequestContentLengthMismatchError() } - opts.headers = { ...this[kProxyHeaders], ...headers } - return this.#client[kDispatch](opts, handler) - } + const buffer = Buffer.from(await body.arrayBuffer()) - [kClose] () { - return this.#client.close() - } - - [kDestroy] (err) { - return this.#client.destroy(err) - } -} + socket.cork() + socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'latin1') + socket.write(buffer) + socket.uncork() -class ProxyAgent extends DispatcherBase { - constructor (opts) { - if (!opts || (typeof opts === 'object' && !(opts instanceof URL) && !opts.uri)) { - throw new InvalidArgumentError('Proxy uri is mandatory') - } + request.onBodySent(buffer) + request.onRequestSent() - const { clientFactory = defaultFactory } = opts - if (typeof clientFactory !== 'function') { - throw new InvalidArgumentError('Proxy opts.clientFactory must be a function.') + if (!expectsPayload && request.reset !== false) { + socket[kReset] = true } - const { proxyTunnel = true } = opts - - super() - - const url = this.#getUrl(opts) - const { href, origin, port, protocol, username, password, hostname: proxyHostname } = url + client[kResume]() + } catch (err) { + abort(err) + } +} - this[kProxy] = { uri: href, protocol } - this[kRequestTls] = opts.requestTls - this[kProxyTls] = opts.proxyTls - this[kProxyHeaders] = opts.headers || {} - this[kTunnelProxy] = proxyTunnel +/** + * @param {AbortCallback} abort + * @param {Iterable} body + * @param {import('./client.js')} client + * @param {import('../core/request.js')} request + * @param {import('net').Socket} socket + * @param {number} contentLength + * @param {string} header + * @param {boolean} expectsPayload + * @returns {Promise} + */ +async function writeIterable (abort, body, client, request, socket, contentLength, header, expectsPayload) { + assert(contentLength !== 0 || client[kRunning] === 0, 'iterator body cannot be pipelined') - if (opts.auth && opts.token) { - throw new InvalidArgumentError('opts.auth cannot be used in combination with opts.token') - } else if (opts.auth) { - /* @deprecated in favour of opts.token */ - this[kProxyHeaders]['proxy-authorization'] = `Basic ${opts.auth}` - } else if (opts.token) { - this[kProxyHeaders]['proxy-authorization'] = opts.token - } else if (username && password) { - this[kProxyHeaders]['proxy-authorization'] = `Basic ${Buffer.from(`${decodeURIComponent(username)}:${decodeURIComponent(password)}`).toString('base64')}` + let callback = null + function onDrain () { + if (callback) { + const cb = callback + callback = null + cb() } + } - const connect = buildConnector({ ...opts.proxyTls }) - this[kConnectEndpoint] = buildConnector({ ...opts.requestTls }) + const waitForDrain = () => new Promise((resolve, reject) => { + assert(callback === null) - const agentFactory = opts.factory || defaultAgentFactory - const factory = (origin, options) => { - const { protocol } = new URL(origin) - if (!this[kTunnelProxy] && protocol === 'http:' && this[kProxy].protocol === 'http:') { - return new Http1ProxyWrapper(this[kProxy].uri, { - headers: this[kProxyHeaders], - connect, - factory: agentFactory - }) - } - return agentFactory(origin, options) + if (socket[kError]) { + reject(socket[kError]) + } else { + callback = resolve } - this[kClient] = clientFactory(url, { connect }) - this[kAgent] = new Agent({ - ...opts, - factory, - connect: async (opts, callback) => { - let requestedPath = opts.host - if (!opts.port) { - requestedPath += `:${defaultProtocolPort(opts.protocol)}` - } - try { - const connectParams = { - origin, - port, - path: requestedPath, - signal: opts.signal, - headers: { - ...this[kProxyHeaders], - host: opts.host, - ...(opts.connections == null || opts.connections > 0 ? { 'proxy-connection': 'keep-alive' } : {}) - }, - servername: this[kProxyTls]?.servername || proxyHostname - } - const { socket, statusCode } = await this[kClient].connect(connectParams) - if (statusCode !== 200) { - socket.on('error', noop).destroy() - callback(new RequestAbortedError(`Proxy response (${statusCode}) !== 200 when HTTP Tunneling`)) - return - } + }) - if (channels.proxyConnected.hasSubscribers) { - channels.proxyConnected.publish({ - socket, - connectParams - }) - } + socket + .on('close', onDrain) + .on('drain', onDrain) - if (opts.protocol !== 'https:') { - callback(null, socket) - return - } - let servername - if (this[kRequestTls]) { - servername = this[kRequestTls].servername - } else { - servername = opts.servername - } - this[kConnectEndpoint]({ ...opts, servername, httpSocket: socket }, callback) - } catch (err) { - if (err.code === 'ERR_TLS_CERT_ALTNAME_INVALID') { - // Throw a custom error to avoid loop in client.js#connect - callback(new SecureProxyConnectionError(err)) - } else { - callback(err) - } - } + const writer = new AsyncWriter({ abort, socket, request, contentLength, client, expectsPayload, header }) + try { + // It's up to the user to somehow abort the async iterable. + for await (const chunk of body) { + if (socket[kError]) { + throw socket[kError] } - }) - } - - dispatch (opts, handler) { - const headers = buildHeaders(opts.headers) - throwIfProxyAuthIsSent(headers) - if (headers && !('host' in headers) && !('Host' in headers)) { - const { host } = new URL(opts.origin) - headers.host = host + if (!writer.write(chunk)) { + await waitForDrain() + } } - return this[kAgent].dispatch( - { - ...opts, - headers - }, - handler - ) + writer.end() + } catch (err) { + writer.destroy(err) + } finally { + socket + .off('close', onDrain) + .off('drain', onDrain) } +} +class AsyncWriter { /** - * @param {import('../../types/proxy-agent').ProxyAgent.Options | string | URL} opts - * @returns {URL} + * + * @param {object} arg + * @param {AbortCallback} arg.abort + * @param {import('net').Socket} arg.socket + * @param {import('../core/request.js')} arg.request + * @param {number} arg.contentLength + * @param {import('./client.js')} arg.client + * @param {boolean} arg.expectsPayload + * @param {string} arg.header */ - #getUrl (opts) { - if (typeof opts === 'string') { - return new URL(opts) - } else if (opts instanceof URL) { - return opts - } else { - return new URL(opts.uri) - } - } - - [kClose] () { - return Promise.all([ - this[kAgent].close(), - this[kClient].close() - ]) - } + constructor ({ abort, socket, request, contentLength, client, expectsPayload, header }) { + this.socket = socket + this.request = request + this.contentLength = contentLength + this.client = client + this.bytesWritten = 0 + this.expectsPayload = expectsPayload + this.header = header + this.abort = abort - [kDestroy] () { - return Promise.all([ - this[kAgent].destroy(), - this[kClient].destroy() - ]) + socket[kWriting] = true } -} -/** - * @param {string[] | Record} headers - * @returns {Record} - */ -function buildHeaders (headers) { - // When using undici.fetch, the headers list is stored - // as an array. - if (Array.isArray(headers)) { - /** @type {Record} */ - const headersPair = {} + /** + * @param {Buffer} chunk + * @returns + */ + write (chunk) { + const { socket, request, contentLength, client, bytesWritten, expectsPayload, header } = this - for (let i = 0; i < headers.length; i += 2) { - headersPair[headers[i]] = headers[i + 1] + if (socket[kError]) { + throw socket[kError] } - return headersPair - } + if (socket.destroyed) { + return false + } - return headers -} + const len = Buffer.byteLength(chunk) + if (!len) { + return true + } -/** - * @param {Record} headers - * - * Previous versions of ProxyAgent suggests the Proxy-Authorization in request headers - * Nevertheless, it was changed and to avoid a security vulnerability by end users - * this check was created. - * It should be removed in the next major version for performance reasons - */ -function throwIfProxyAuthIsSent (headers) { - const existProxyAuth = headers && Object.keys(headers) - .find((key) => key.toLowerCase() === 'proxy-authorization') - if (existProxyAuth) { - throw new InvalidArgumentError('Proxy-Authorization should be sent in ProxyAgent constructor') - } -} + // We should defer writing chunks. + if (contentLength !== null && bytesWritten + len > contentLength) { + if (client[kStrictContentLength]) { + throw new RequestContentLengthMismatchError() + } -module.exports = ProxyAgent + process.emitWarning(new RequestContentLengthMismatchError()) + } + socket.cork() -/***/ }), + if (bytesWritten === 0) { + if (!expectsPayload && request.reset !== false) { + socket[kReset] = true + } -/***/ 139: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + if (contentLength === null) { + socket.write(`${header}transfer-encoding: chunked\r\n`, 'latin1') + } else { + socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'latin1') + } + } -"use strict"; + if (contentLength === null) { + socket.write(`\r\n${len.toString(16)}\r\n`, 'latin1') + } + this.bytesWritten += len -const Dispatcher = __nccwpck_require__(2096) -const RetryHandler = __nccwpck_require__(4943) + const ret = socket.write(chunk) -class RetryAgent extends Dispatcher { - #agent = null - #options = null - constructor (agent, options = {}) { - super(options) - this.#agent = agent - this.#options = options - } + socket.uncork() - dispatch (opts, handler) { - const retry = new RetryHandler({ - ...opts, - retryOptions: this.#options - }, { - dispatch: this.#agent.dispatch.bind(this.#agent), - handler - }) - return this.#agent.dispatch(opts, retry) - } + request.onBodySent(chunk) - close () { - return this.#agent.close() - } + if (!ret) { + if (socket[kParser].timeout && socket[kParser].timeoutType === TIMEOUT_HEADERS) { + if (socket[kParser].timeout.refresh) { + socket[kParser].timeout.refresh() + } + } + } - destroy () { - return this.#agent.destroy() + return ret } -} - -module.exports = RetryAgent - - -/***/ }), - -/***/ 3079: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -"use strict"; - - -const { - PoolBase, - kClients, - kNeedDrain, - kAddClient, - kGetDispatcher, - kRemoveClient -} = __nccwpck_require__(6469) -const Client = __nccwpck_require__(226) -const { - InvalidArgumentError -} = __nccwpck_require__(4928) -const util = __nccwpck_require__(983) -const { kUrl } = __nccwpck_require__(9562) -const buildConnector = __nccwpck_require__(978) -const kOptions = Symbol('options') -const kConnections = Symbol('connections') -const kFactory = Symbol('factory') -const kIndex = Symbol('index') + /** + * @returns {void} + */ + end () { + const { socket, contentLength, client, bytesWritten, expectsPayload, header, request } = this + request.onRequestSent() -function defaultFactory (origin, opts) { - return new Client(origin, opts) -} + socket[kWriting] = false -class RoundRobinPool extends PoolBase { - constructor (origin, { - connections, - factory = defaultFactory, - connect, - connectTimeout, - tls, - maxCachedSessions, - socketPath, - autoSelectFamily, - autoSelectFamilyAttemptTimeout, - allowH2, - clientTtl, - ...options - } = {}) { - if (connections != null && (!Number.isFinite(connections) || connections < 0)) { - throw new InvalidArgumentError('invalid connections') + if (socket[kError]) { + throw socket[kError] } - if (typeof factory !== 'function') { - throw new InvalidArgumentError('factory must be a function.') + if (socket.destroyed) { + return } - if (connect != null && typeof connect !== 'function' && typeof connect !== 'object') { - throw new InvalidArgumentError('connect must be a function or an object') - } + if (bytesWritten === 0) { + if (expectsPayload) { + // https://tools.ietf.org/html/rfc7230#section-3.3.2 + // A user agent SHOULD send a Content-Length in a request message when + // no Transfer-Encoding is sent and the request method defines a meaning + // for an enclosed payload body. - if (typeof connect !== 'function') { - connect = buildConnector({ - ...tls, - maxCachedSessions, - allowH2, - socketPath, - timeout: connectTimeout, - ...(typeof autoSelectFamily === 'boolean' ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : undefined), - ...connect - }) + socket.write(`${header}content-length: 0\r\n\r\n`, 'latin1') + } else { + socket.write(`${header}\r\n`, 'latin1') + } + } else if (contentLength === null) { + socket.write('\r\n0\r\n\r\n', 'latin1') } - super() - - this[kConnections] = connections || null - this[kUrl] = util.parseOrigin(origin) - this[kOptions] = { ...util.deepClone(options), connect, allowH2, clientTtl } - this[kOptions].interceptors = options.interceptors - ? { ...options.interceptors } - : undefined - this[kFactory] = factory - this[kIndex] = -1 - - this.on('connect', (origin, targets) => { - if (clientTtl != null && clientTtl > 0) { - for (const target of targets) { - Object.assign(target, { ttl: Date.now() }) - } + if (contentLength !== null && bytesWritten !== contentLength) { + if (client[kStrictContentLength]) { + throw new RequestContentLengthMismatchError() + } else { + process.emitWarning(new RequestContentLengthMismatchError()) } - }) + } - this.on('connectionError', (origin, targets, error) => { - for (const target of targets) { - const idx = this[kClients].indexOf(target) - if (idx !== -1) { - this[kClients].splice(idx, 1) - } + if (socket[kParser].timeout && socket[kParser].timeoutType === TIMEOUT_HEADERS) { + if (socket[kParser].timeout.refresh) { + socket[kParser].timeout.refresh() } - }) - } - - [kGetDispatcher] () { - const clientTtlOption = this[kOptions].clientTtl - const clientsLength = this[kClients].length - - // If we have no clients yet, create one - if (clientsLength === 0) { - const dispatcher = this[kFactory](this[kUrl], this[kOptions]) - this[kAddClient](dispatcher) - return dispatcher } - // Round-robin through existing clients - let checked = 0 - while (checked < clientsLength) { - this[kIndex] = (this[kIndex] + 1) % clientsLength - const client = this[kClients][this[kIndex]] - - // Check if client is stale (TTL expired) - if (clientTtlOption != null && clientTtlOption > 0 && client.ttl && ((Date.now() - client.ttl) > clientTtlOption)) { - this[kRemoveClient](client) - checked++ - continue - } + client[kResume]() + } - // Return client if it's not draining - if (!client[kNeedDrain]) { - return client - } + /** + * @param {Error} [err] + * @returns {void} + */ + destroy (err) { + const { socket, client, abort } = this - checked++ - } + socket[kWriting] = false - // All clients are busy, create a new one if we haven't reached the limit - if (!this[kConnections] || clientsLength < this[kConnections]) { - const dispatcher = this[kFactory](this[kUrl], this[kOptions]) - this[kAddClient](dispatcher) - return dispatcher + if (err) { + assert(client[kRunning] <= 1, 'pipeline should only contain this request') + abort(err) } } } -module.exports = RoundRobinPool +module.exports = connectH1 /***/ }), -/***/ 9825: -/***/ ((module) => { - -"use strict"; - - -const textDecoder = new TextDecoder() - -/** - * @see https://encoding.spec.whatwg.org/#utf-8-decode - * @param {Uint8Array} buffer - */ -function utf8DecodeBytes (buffer) { - if (buffer.length === 0) { - return '' - } +/***/ 6250: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - // 1. Let buffer be the result of peeking three bytes from - // ioQueue, converted to a byte sequence. - // 2. If buffer is 0xEF 0xBB 0xBF, then read three - // bytes from ioQueue. (Do nothing with those bytes.) - if (buffer[0] === 0xEF && buffer[1] === 0xBB && buffer[2] === 0xBF) { - buffer = buffer.subarray(3) - } - // 3. Process a queue with an instance of UTF-8’s - // decoder, ioQueue, output, and "replacement". - const output = textDecoder.decode(buffer) +const assert = __nccwpck_require__(4589) +const { pipeline } = __nccwpck_require__(7075) +const util = __nccwpck_require__(2550) +const { + RequestContentLengthMismatchError, + RequestAbortedError, + SocketError, + InformationalError, + InvalidArgumentError +} = __nccwpck_require__(5093) +const { + kUrl, + kReset, + kClient, + kRunning, + kPending, + kQueue, + kPendingIdx, + kRunningIdx, + kError, + kSocket, + kStrictContentLength, + kOnError, + kMaxConcurrentStreams, + kHTTP2Session, + kHTTP2InitialWindowSize, + kHTTP2ConnectionWindowSize, + kResume, + kSize, + kHTTPContext, + kClosed, + kBodyTimeout, + kEnableConnectProtocol, + kRemoteSettings, + kHTTP2Stream +} = __nccwpck_require__(8261) +const { channels } = __nccwpck_require__(2248) - // 4. Return output. - return output +const kOpenStreams = Symbol('open streams') + +let extractBody + +/** @type {import('http2')} */ +let http2 +try { + http2 = __nccwpck_require__(2467) +} catch { + // @ts-ignore + http2 = { constants: {} } } -module.exports = { - utf8DecodeBytes +const { + constants: { + HTTP2_HEADER_AUTHORITY, + HTTP2_HEADER_METHOD, + HTTP2_HEADER_PATH, + HTTP2_HEADER_SCHEME, + HTTP2_HEADER_CONTENT_LENGTH, + HTTP2_HEADER_EXPECT, + HTTP2_HEADER_STATUS, + HTTP2_HEADER_PROTOCOL, + NGHTTP2_REFUSED_STREAM, + NGHTTP2_CANCEL + } +} = http2 + +function parseH2Headers (headers) { + const result = [] + + for (const [name, value] of Object.entries(headers)) { + // h2 may concat the header value by array + // e.g. Set-Cookie + if (Array.isArray(value)) { + for (const subvalue of value) { + // we need to provide each header value of header name + // because the headers handler expect name-value pair + result.push(Buffer.from(name), Buffer.from(subvalue)) + } + } else { + result.push(Buffer.from(name), Buffer.from(value)) + } + } + + return result } +function connectH2 (client, socket) { + client[kSocket] = socket -/***/ }), + const http2InitialWindowSize = client[kHTTP2InitialWindowSize] + const http2ConnectionWindowSize = client[kHTTP2ConnectionWindowSize] -/***/ 4456: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + const session = http2.connect(client[kUrl], { + createConnection: () => socket, + peerMaxConcurrentStreams: client[kMaxConcurrentStreams], + settings: { + // TODO(metcoder95): add support for PUSH + enablePush: false, + ...(http2InitialWindowSize != null ? { initialWindowSize: http2InitialWindowSize } : null) + } + }) -"use strict"; + session[kOpenStreams] = 0 + session[kClient] = client + session[kSocket] = socket + session[kHTTP2Session] = null + // We set it to true by default in a best-effort; however once connected to an H2 server + // we will check if extended CONNECT protocol is supported or not + // and set this value accordingly. + session[kEnableConnectProtocol] = false + // States whether or not we have received the remote settings from the server + session[kRemoteSettings] = false + // Apply connection-level flow control once connected (if supported). + if (http2ConnectionWindowSize) { + util.addListener(session, 'connect', applyConnectionWindowSize.bind(session, http2ConnectionWindowSize)) + } -// We include a version number for the Dispatcher API. In case of breaking changes, -// this version number must be increased to avoid conflicts. -const globalDispatcher = Symbol.for('undici.globalDispatcher.1') -const { InvalidArgumentError } = __nccwpck_require__(4928) -const Agent = __nccwpck_require__(2004) + util.addListener(session, 'error', onHttp2SessionError) + util.addListener(session, 'frameError', onHttp2FrameError) + util.addListener(session, 'end', onHttp2SessionEnd) + util.addListener(session, 'goaway', onHttp2SessionGoAway) + util.addListener(session, 'close', onHttp2SessionClose) + util.addListener(session, 'remoteSettings', onHttp2RemoteSettings) + // TODO (@metcoder95): implement SETTINGS support + // util.addListener(session, 'localSettings', onHttp2RemoteSettings) -if (getGlobalDispatcher() === undefined) { - setGlobalDispatcher(new Agent()) + session.unref() + + client[kHTTP2Session] = session + socket[kHTTP2Session] = session + + util.addListener(socket, 'error', onHttp2SocketError) + util.addListener(socket, 'end', onHttp2SocketEnd) + util.addListener(socket, 'close', onHttp2SocketClose) + + socket[kClosed] = false + socket.on('close', onSocketClose) + + return { + version: 'h2', + defaultPipelining: Infinity, + /** + * @param {import('../core/request.js')} request + * @returns {boolean} + */ + write (request) { + return writeH2(client, request) + }, + /** + * @returns {void} + */ + resume () { + resumeH2(client) + }, + /** + * @param {Error | null} err + * @param {() => void} callback + */ + destroy (err, callback) { + if (socket[kClosed]) { + queueMicrotask(callback) + } else { + socket.destroy(err).on('close', callback) + } + }, + /** + * @type {boolean} + */ + get destroyed () { + return socket.destroyed + }, + /** + * @param {import('../core/request.js')} request + * @returns {boolean} + */ + busy (request) { + if (request != null) { + if (client[kRunning] > 0) { + // We are already processing requests + + // Non-idempotent request cannot be retried. + // Ensure that no other requests are inflight and + // could cause failure. + if (request.idempotent === false) return true + // Don't dispatch an upgrade until all preceding requests have completed. + // Possibly, we do not have remote settings confirmed yet. + if ((request.upgrade === 'websocket' || request.method === 'CONNECT') && session[kRemoteSettings] === false) return true + // Request with stream or iterator body can error while other requests + // are inflight and indirectly error those as well. + // Ensure this doesn't happen by waiting for inflight + // to complete before dispatching. + + // Request with stream or iterator body cannot be retried. + // Ensure that no other requests are inflight and + // could cause failure. + if (util.bodyLength(request.body) !== 0 && + (util.isStream(request.body) || util.isAsyncIterable(request.body) || util.isFormDataLike(request.body))) return true + } else { + return (request.upgrade === 'websocket' || request.method === 'CONNECT') && session[kRemoteSettings] === false + } + } + + return false + } + } } -function setGlobalDispatcher (agent) { - if (!agent || typeof agent.dispatch !== 'function') { - throw new InvalidArgumentError('Argument agent must implement Agent') +function resumeH2 (client) { + const socket = client[kSocket] + + if (socket?.destroyed === false) { + if (client[kSize] === 0 || client[kMaxConcurrentStreams] === 0) { + socket.unref() + client[kHTTP2Session].unref() + } else { + socket.ref() + client[kHTTP2Session].ref() + } } - Object.defineProperty(globalThis, globalDispatcher, { - value: agent, - writable: true, - enumerable: false, - configurable: false - }) } -function getGlobalDispatcher () { - return globalThis[globalDispatcher] +function applyConnectionWindowSize (connectionWindowSize) { + try { + if (typeof this.setLocalWindowSize === 'function') { + this.setLocalWindowSize(connectionWindowSize) + } + } catch { + // Best-effort only. + } } -// These are the globals that can be installed by undici.install(). -// Not exported by index.js to avoid use outside of this module. -const installedExports = /** @type {const} */ ( - [ - 'fetch', - 'Headers', - 'Response', - 'Request', - 'FormData', - 'WebSocket', - 'CloseEvent', - 'ErrorEvent', - 'MessageEvent', - 'EventSource' - ] -) +function onHttp2RemoteSettings (settings) { + // Fallbacks are a safe bet, remote setting will always override + this[kClient][kMaxConcurrentStreams] = settings.maxConcurrentStreams ?? this[kClient][kMaxConcurrentStreams] + /** + * From RFC-8441 + * A sender MUST NOT send a SETTINGS_ENABLE_CONNECT_PROTOCOL parameter + * with the value of 0 after previously sending a value of 1. + */ + // Note: Cannot be tested in Node, it does not supports disabling the extended CONNECT protocol once enabled + if (this[kRemoteSettings] === true && this[kEnableConnectProtocol] === true && settings.enableConnectProtocol === false) { + const err = new InformationalError('HTTP/2: Server disabled extended CONNECT protocol against RFC-8441') + this[kSocket][kError] = err + this[kClient][kOnError](err) + return + } -module.exports = { - setGlobalDispatcher, - getGlobalDispatcher, - installedExports + this[kEnableConnectProtocol] = settings.enableConnectProtocol ?? this[kEnableConnectProtocol] + this[kRemoteSettings] = true + this[kClient][kResume]() } +function onHttp2SessionError (err) { + assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID') -/***/ }), + this[kSocket][kError] = err + this[kClient][kOnError](err) +} -/***/ 2387: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +function onHttp2FrameError (type, code, id) { + if (id === 0) { + const err = new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`) + this[kSocket][kError] = err + this[kClient][kOnError](err) + } +} -"use strict"; +function onHttp2SessionEnd () { + const err = new SocketError('other side closed', util.getSocketInfo(this[kSocket])) + this.destroy(err) + util.destroy(this[kSocket], err) +} +/** + * This is the root cause of #3011 + * We need to handle GOAWAY frames properly, and trigger the session close + * along with the socket right away + * + * @this {import('http2').ClientHttp2Session} + * @param {number} errorCode + */ +function onHttp2SessionGoAway (errorCode) { + // TODO(mcollina): Verify if GOAWAY implements the spec correctly: + // https://datatracker.ietf.org/doc/html/rfc7540#section-6.8 + // Specifically, we do not verify the "valid" stream id. -const util = __nccwpck_require__(983) -const { - parseCacheControlHeader, - parseVaryHeader, - isEtagUsable -} = __nccwpck_require__(630) -const { parseHttpDate } = __nccwpck_require__(6810) + const err = this[kError] || new SocketError(`HTTP/2: "GOAWAY" frame received with code ${errorCode}`, util.getSocketInfo(this[kSocket])) + const client = this[kClient] -function noop () {} + client[kSocket] = null + client[kHTTPContext] = null -// Status codes that we can use some heuristics on to cache -const HEURISTICALLY_CACHEABLE_STATUS_CODES = [ - 200, 203, 204, 206, 300, 301, 308, 404, 405, 410, 414, 501 -] + // this is an HTTP2 session + this.close() + this[kHTTP2Session] = null -// Status codes which semantic is not handled by the cache -// https://datatracker.ietf.org/doc/html/rfc9111#section-3 -// This list should not grow beyond 206 unless the RFC is updated -// by a newer one including more. Please introduce another list if -// implementing caching of responses with the 'must-understand' directive. -const NOT_UNDERSTOOD_STATUS_CODES = [ - 206 -] + util.destroy(this[kSocket], err) -const MAX_RESPONSE_AGE = 2147483647000 + // Fail head of pipeline. + if (client[kRunningIdx] < client[kQueue].length) { + const request = client[kQueue][client[kRunningIdx]] + client[kQueue][client[kRunningIdx]++] = null + util.errorRequest(client, request, err) + client[kPendingIdx] = client[kRunningIdx] + } -/** - * @typedef {import('../../types/dispatcher.d.ts').default.DispatchHandler} DispatchHandler - * - * @implements {DispatchHandler} - */ -class CacheHandler { - /** - * @type {import('../../types/cache-interceptor.d.ts').default.CacheKey} - */ - #cacheKey + assert(client[kRunning] === 0) - /** - * @type {import('../../types/cache-interceptor.d.ts').default.CacheHandlerOptions['type']} - */ - #cacheType + client.emit('disconnect', client[kUrl], [client], err) + client.emit('connectionError', client[kUrl], [client], err) - /** - * @type {number | undefined} - */ - #cacheByDefault + client[kResume]() +} - /** - * @type {import('../../types/cache-interceptor.d.ts').default.CacheStore} - */ - #store +function onHttp2SessionClose () { + const { [kClient]: client } = this + const { [kSocket]: socket } = client - /** - * @type {import('../../types/dispatcher.d.ts').default.DispatchHandler} - */ - #handler + const err = this[kSocket][kError] || this[kError] || new SocketError('closed', util.getSocketInfo(socket)) - /** - * @type {import('node:stream').Writable | undefined} - */ - #writeStream + client[kSocket] = null + client[kHTTPContext] = null - /** - * @param {import('../../types/cache-interceptor.d.ts').default.CacheHandlerOptions} opts - * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} cacheKey - * @param {import('../../types/dispatcher.d.ts').default.DispatchHandler} handler - */ - constructor ({ store, type, cacheByDefault }, cacheKey, handler) { - this.#store = store - this.#cacheType = type - this.#cacheByDefault = cacheByDefault - this.#cacheKey = cacheKey - this.#handler = handler - } + if (client.destroyed) { + assert(client[kPending] === 0) - onRequestStart (controller, context) { - this.#writeStream?.destroy() - this.#writeStream = undefined - this.#handler.onRequestStart?.(controller, context) + // Fail entire queue. + const requests = client[kQueue].splice(client[kRunningIdx]) + for (let i = 0; i < requests.length; i++) { + const request = requests[i] + util.errorRequest(client, request, err) + } } +} - onRequestUpgrade (controller, statusCode, headers, socket) { - this.#handler.onRequestUpgrade?.(controller, statusCode, headers, socket) - } +function onHttp2SocketClose () { + const err = this[kError] || new SocketError('closed', util.getSocketInfo(this)) - /** - * @param {import('../../types/dispatcher.d.ts').default.DispatchController} controller - * @param {number} statusCode - * @param {import('../../types/header.d.ts').IncomingHttpHeaders} resHeaders - * @param {string} statusMessage - */ - onResponseStart ( - controller, - statusCode, - resHeaders, - statusMessage - ) { - const downstreamOnHeaders = () => - this.#handler.onResponseStart?.( - controller, - statusCode, - resHeaders, - statusMessage - ) - const handler = this + const client = this[kHTTP2Session][kClient] - if ( - !util.safeHTTPMethods.includes(this.#cacheKey.method) && - statusCode >= 200 && - statusCode <= 399 - ) { - // Successful response to an unsafe method, delete it from cache - // https://www.rfc-editor.org/rfc/rfc9111.html#name-invalidating-stored-response - try { - this.#store.delete(this.#cacheKey)?.catch?.(noop) - } catch { - // Fail silently - } - return downstreamOnHeaders() - } + client[kSocket] = null + client[kHTTPContext] = null - const cacheControlHeader = resHeaders['cache-control'] - const heuristicallyCacheable = resHeaders['last-modified'] && HEURISTICALLY_CACHEABLE_STATUS_CODES.includes(statusCode) - if ( - !cacheControlHeader && - !resHeaders['expires'] && - !heuristicallyCacheable && - !this.#cacheByDefault - ) { - // Don't have anything to tell us this response is cachable and we're not - // caching by default - return downstreamOnHeaders() - } + if (this[kHTTP2Session] !== null) { + this[kHTTP2Session].destroy(err) + } - const cacheControlDirectives = cacheControlHeader ? parseCacheControlHeader(cacheControlHeader) : {} - if (!canCacheResponse(this.#cacheType, statusCode, resHeaders, cacheControlDirectives)) { - return downstreamOnHeaders() - } + client[kPendingIdx] = client[kRunningIdx] - const now = Date.now() - const resAge = resHeaders.age ? getAge(resHeaders.age) : undefined - if (resAge && resAge >= MAX_RESPONSE_AGE) { - // Response considered stale - return downstreamOnHeaders() - } + assert(client[kRunning] === 0) - const resDate = typeof resHeaders.date === 'string' - ? parseHttpDate(resHeaders.date) - : undefined + client.emit('disconnect', client[kUrl], [client], err) - const staleAt = - determineStaleAt(this.#cacheType, now, resAge, resHeaders, resDate, cacheControlDirectives) ?? - this.#cacheByDefault - if (staleAt === undefined || (resAge && resAge > staleAt)) { - return downstreamOnHeaders() - } + client[kResume]() +} - const baseTime = resDate ? resDate.getTime() : now - const absoluteStaleAt = staleAt + baseTime - if (now >= absoluteStaleAt) { - // Response is already stale - return downstreamOnHeaders() - } +function onHttp2SocketError (err) { + assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID') - let varyDirectives - if (this.#cacheKey.headers && resHeaders.vary) { - varyDirectives = parseVaryHeader(resHeaders.vary, this.#cacheKey.headers) - if (!varyDirectives) { - // Parse error - return downstreamOnHeaders() - } - } + this[kError] = err - const deleteAt = determineDeleteAt(baseTime, cacheControlDirectives, absoluteStaleAt) - const strippedHeaders = stripNecessaryHeaders(resHeaders, cacheControlDirectives) + this[kClient][kOnError](err) +} - /** - * @type {import('../../types/cache-interceptor.d.ts').default.CacheValue} - */ - const value = { - statusCode, - statusMessage, - headers: strippedHeaders, - vary: varyDirectives, - cacheControlDirectives, - cachedAt: resAge ? now - resAge : now, - staleAt: absoluteStaleAt, - deleteAt - } +function onHttp2SocketEnd () { + util.destroy(this, new SocketError('other side closed', util.getSocketInfo(this))) +} - // Not modified, re-use the cached value - // https://www.rfc-editor.org/rfc/rfc9111.html#name-handling-304-not-modified - if (statusCode === 304) { - /** - * @type {import('../../types/cache-interceptor.d.ts').default.CacheValue} - */ - const cachedValue = this.#store.get(this.#cacheKey) - if (!cachedValue) { - // Do not create a new cache entry, as a 304 won't have a body - so cannot be cached. - return downstreamOnHeaders() - } +function onSocketClose () { + this[kClosed] = true +} - // Re-use the cached value: statuscode, statusmessage, headers and body - value.statusCode = cachedValue.statusCode - value.statusMessage = cachedValue.statusMessage - value.etag = cachedValue.etag - value.headers = { ...cachedValue.headers, ...strippedHeaders } +// https://www.rfc-editor.org/rfc/rfc7230#section-3.3.2 +function shouldSendContentLength (method) { + return method !== 'GET' && method !== 'HEAD' && method !== 'OPTIONS' && method !== 'TRACE' && method !== 'CONNECT' +} - downstreamOnHeaders() +function writeH2 (client, request) { + const requestTimeout = request.bodyTimeout ?? client[kBodyTimeout] + const session = client[kHTTP2Session] + const { method, path, host, upgrade, expectContinue, signal, protocol, headers: reqHeaders } = request + let { body } = request - this.#writeStream = this.#store.createWriteStream(this.#cacheKey, value) + if (upgrade != null && upgrade !== 'websocket') { + util.errorRequest(client, request, new InvalidArgumentError(`Custom upgrade "${upgrade}" not supported over HTTP/2`)) + return false + } - if (!this.#writeStream || !cachedValue?.body) { - return + const headers = {} + for (let n = 0; n < reqHeaders.length; n += 2) { + const key = reqHeaders[n + 0] + const val = reqHeaders[n + 1] + + if (key === 'cookie') { + if (headers[key] != null) { + headers[key] = Array.isArray(headers[key]) ? (headers[key].push(val), headers[key]) : [headers[key], val] + } else { + headers[key] = val } - const bodyIterator = cachedValue.body.values() + continue + } - const streamCachedBody = () => { - for (const chunk of bodyIterator) { - const full = this.#writeStream.write(chunk) === false - this.#handler.onResponseData?.(controller, chunk) - // when stream is full stop writing until we get a 'drain' event - if (full) { - break - } + if (Array.isArray(val)) { + for (let i = 0; i < val.length; i++) { + if (headers[key]) { + headers[key] += `, ${val[i]}` + } else { + headers[key] = val[i] } } + } else if (headers[key]) { + headers[key] += `, ${val}` + } else { + headers[key] = val + } + } - this.#writeStream - .on('error', function () { - handler.#writeStream = undefined - handler.#store.delete(handler.#cacheKey) - }) - .on('drain', () => { - streamCachedBody() - }) - .on('close', function () { - if (handler.#writeStream === this) { - handler.#writeStream = undefined - } - }) + /** @type {import('node:http2').ClientHttp2Stream} */ + let stream = null - streamCachedBody() - } else { - if (typeof resHeaders.etag === 'string' && isEtagUsable(resHeaders.etag)) { - value.etag = resHeaders.etag - } + const { hostname, port } = client[kUrl] - this.#writeStream = this.#store.createWriteStream(this.#cacheKey, value) + headers[HTTP2_HEADER_AUTHORITY] = host || `${hostname}${port ? `:${port}` : ''}` + headers[HTTP2_HEADER_METHOD] = method - if (!this.#writeStream) { - return downstreamOnHeaders() - } + const abort = (err) => { + if (request.aborted || request.completed) { + return + } - this.#writeStream - .on('drain', () => controller.resume()) - .on('error', function () { - // TODO (fix): Make error somehow observable? - handler.#writeStream = undefined + err = err || new RequestAbortedError() - // Delete the value in case the cache store is holding onto state from - // the call to createWriteStream - handler.#store.delete(handler.#cacheKey) - }) - .on('close', function () { - if (handler.#writeStream === this) { - handler.#writeStream = undefined - } + util.errorRequest(client, request, err) - // TODO (fix): Should we resume even if was paused downstream? - controller.resume() - }) + if (stream != null) { + // Some chunks might still come after abort, + // let's ignore them + stream.removeAllListeners('data') - downstreamOnHeaders() - } - } + // On Abort, we close the stream to send RST_STREAM frame + stream.close() - onResponseData (controller, chunk) { - if (this.#writeStream?.write(chunk) === false) { - controller.pause() + // We move the running index to the next request + client[kOnError](err) + client[kResume]() } - this.#handler.onResponseData?.(controller, chunk) - } - - onResponseEnd (controller, trailers) { - this.#writeStream?.end() - this.#handler.onResponseEnd?.(controller, trailers) + // We do not destroy the socket as we can continue using the session + // the stream gets destroyed and the session remains to create new streams + util.destroy(body, err) } - onResponseError (controller, err) { - this.#writeStream?.destroy(err) - this.#writeStream = undefined - this.#handler.onResponseError?.(controller, err) + try { + // We are already connected, streams are pending. + // We can call on connect, and wait for abort + request.onConnect(abort) + } catch (err) { + util.errorRequest(client, request, err) } -} -/** - * @see https://www.rfc-editor.org/rfc/rfc9111.html#name-storing-responses-to-authen - * - * @param {import('../../types/cache-interceptor.d.ts').default.CacheOptions['type']} cacheType - * @param {number} statusCode - * @param {import('../../types/header.d.ts').IncomingHttpHeaders} resHeaders - * @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives} cacheControlDirectives - */ -function canCacheResponse (cacheType, statusCode, resHeaders, cacheControlDirectives) { - // Status code must be final and understood. - if (statusCode < 200 || NOT_UNDERSTOOD_STATUS_CODES.includes(statusCode)) { - return false - } - // Responses with neither status codes that are heuristically cacheable, nor "explicit enough" caching - // directives, are not cacheable. "Explicit enough": see https://www.rfc-editor.org/rfc/rfc9111.html#section-3 - if (!HEURISTICALLY_CACHEABLE_STATUS_CODES.includes(statusCode) && !resHeaders['expires'] && - !cacheControlDirectives.public && - cacheControlDirectives['max-age'] === undefined && - // RFC 9111: a private response directive, if the cache is not shared - !(cacheControlDirectives.private && cacheType === 'private') && - !(cacheControlDirectives['s-maxage'] !== undefined && cacheType === 'shared') - ) { + if (request.aborted) { return false } - if (cacheControlDirectives['no-store']) { - return false - } + if (upgrade || method === 'CONNECT') { + session.ref() - if (cacheType === 'shared' && cacheControlDirectives.private === true) { - return false - } + if (upgrade === 'websocket') { + // We cannot upgrade to websocket if extended CONNECT protocol is not supported + if (session[kEnableConnectProtocol] === false) { + util.errorRequest(client, request, new InformationalError('HTTP/2: Extended CONNECT protocol not supported by server')) + session.unref() + return false + } - // https://www.rfc-editor.org/rfc/rfc9111.html#section-4.1-5 - if (resHeaders.vary?.includes('*')) { - return false - } + // We force the method to CONNECT + // as per RFC-8441 + // https://datatracker.ietf.org/doc/html/rfc8441#section-4 + headers[HTTP2_HEADER_METHOD] = 'CONNECT' + headers[HTTP2_HEADER_PROTOCOL] = 'websocket' + // :path and :scheme headers must be omitted when sending CONNECT but set if extended-CONNECT + headers[HTTP2_HEADER_PATH] = path - // https://www.rfc-editor.org/rfc/rfc9111.html#name-storing-responses-to-authen - if (resHeaders.authorization) { - if (!cacheControlDirectives.public || typeof resHeaders.authorization !== 'string') { - return false - } + if (protocol === 'ws:' || protocol === 'wss:') { + headers[HTTP2_HEADER_SCHEME] = protocol === 'ws:' ? 'http' : 'https' + } else { + headers[HTTP2_HEADER_SCHEME] = protocol === 'http:' ? 'http' : 'https' + } - if ( - Array.isArray(cacheControlDirectives['no-cache']) && - cacheControlDirectives['no-cache'].includes('authorization') - ) { - return false - } + stream = session.request(headers, { endStream: false, signal }) + stream[kHTTP2Stream] = true - if ( - Array.isArray(cacheControlDirectives['private']) && - cacheControlDirectives['private'].includes('authorization') - ) { - return false - } - } + stream.once('response', (headers, _flags) => { + const { [HTTP2_HEADER_STATUS]: statusCode, ...realHeaders } = headers - return true -} + request.onUpgrade(statusCode, parseH2Headers(realHeaders), stream) -/** - * @param {string | string[]} ageHeader - * @returns {number | undefined} - */ -function getAge (ageHeader) { - const age = parseInt(Array.isArray(ageHeader) ? ageHeader[0] : ageHeader) + ++session[kOpenStreams] + client[kQueue][client[kRunningIdx]++] = null + }) - return isNaN(age) ? undefined : age * 1000 -} + stream.on('error', () => { + if (stream.rstCode === NGHTTP2_REFUSED_STREAM || stream.rstCode === NGHTTP2_CANCEL) { + // NGHTTP2_REFUSED_STREAM (7) or NGHTTP2_CANCEL (8) + // We do not treat those as errors as the server might + // not support websockets and refuse the stream + abort(new InformationalError(`HTTP/2: "stream error" received - code ${stream.rstCode}`)) + } + }) -/** - * @param {import('../../types/cache-interceptor.d.ts').default.CacheOptions['type']} cacheType - * @param {number} now - * @param {number | undefined} age - * @param {import('../../types/header.d.ts').IncomingHttpHeaders} resHeaders - * @param {Date | undefined} responseDate - * @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives} cacheControlDirectives - * - * @returns {number | undefined} time that the value is stale at in seconds or undefined if it shouldn't be cached - */ -function determineStaleAt (cacheType, now, age, resHeaders, responseDate, cacheControlDirectives) { - if (cacheType === 'shared') { - // Prioritize s-maxage since we're a shared cache - // s-maxage > max-age > Expire - // https://www.rfc-editor.org/rfc/rfc9111.html#section-5.2.2.10-3 - const sMaxAge = cacheControlDirectives['s-maxage'] - if (sMaxAge !== undefined) { - return sMaxAge > 0 ? sMaxAge * 1000 : undefined + stream.once('close', () => { + session[kOpenStreams] -= 1 + if (session[kOpenStreams] === 0) session.unref() + }) + + stream.setTimeout(requestTimeout) + return true } - } - const maxAge = cacheControlDirectives['max-age'] - if (maxAge !== undefined) { - return maxAge > 0 ? maxAge * 1000 : undefined - } + // TODO: consolidate once we support CONNECT properly + // NOTE: We are already connected, streams are pending, first request + // will create a new stream. We trigger a request to create the stream and wait until + // `ready` event is triggered + // We disabled endStream to allow the user to write to the stream + stream = session.request(headers, { endStream: false, signal }) + stream[kHTTP2Stream] = true + stream.on('response', headers => { + const { [HTTP2_HEADER_STATUS]: statusCode, ...realHeaders } = headers - if (typeof resHeaders.expires === 'string') { - // https://www.rfc-editor.org/rfc/rfc9111.html#section-5.3 - const expiresDate = parseHttpDate(resHeaders.expires) - if (expiresDate) { - if (now >= expiresDate.getTime()) { - return undefined - } + request.onUpgrade(statusCode, parseH2Headers(realHeaders), stream) + ++session[kOpenStreams] + client[kQueue][client[kRunningIdx]++] = null + }) + stream.once('close', () => { + session[kOpenStreams] -= 1 + if (session[kOpenStreams] === 0) session.unref() + }) + stream.setTimeout(requestTimeout) - if (responseDate) { - if (responseDate >= expiresDate) { - return undefined - } + return true + } - if (age !== undefined && age > (expiresDate - responseDate)) { - return undefined - } - } + // https://tools.ietf.org/html/rfc7540#section-8.3 + // :path and :scheme headers must be omitted when sending CONNECT + headers[HTTP2_HEADER_PATH] = path + headers[HTTP2_HEADER_SCHEME] = protocol === 'http:' ? 'http' : 'https' - return expiresDate.getTime() - now - } - } + // https://tools.ietf.org/html/rfc7231#section-4.3.1 + // https://tools.ietf.org/html/rfc7231#section-4.3.2 + // https://tools.ietf.org/html/rfc7231#section-4.3.5 - if (typeof resHeaders['last-modified'] === 'string') { - // https://www.rfc-editor.org/rfc/rfc9111.html#name-calculating-heuristic-fresh - const lastModified = new Date(resHeaders['last-modified']) - if (isValidDate(lastModified)) { - if (lastModified.getTime() >= now) { - return undefined - } + // Sending a payload body on a request that does not + // expect it can cause undefined behavior on some + // servers and corrupt connection state. Do not + // re-use the connection for further requests. - const responseAge = now - lastModified.getTime() + const expectsPayload = ( + method === 'PUT' || + method === 'POST' || + method === 'PATCH' + ) - return responseAge * 0.1 - } + if (body && typeof body.read === 'function') { + // Try to read EOF in order to get length. + body.read(0) } - if (cacheControlDirectives.immutable) { - // https://www.rfc-editor.org/rfc/rfc8246.html#section-2.2 - return 31536000 - } + let contentLength = util.bodyLength(body) - return undefined -} + if (util.isFormDataLike(body)) { + extractBody ??= (__nccwpck_require__(9742).extractBody) -/** - * @param {number} now - * @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives} cacheControlDirectives - * @param {number} staleAt - */ -function determineDeleteAt (now, cacheControlDirectives, staleAt) { - let staleWhileRevalidate = -Infinity - let staleIfError = -Infinity - let immutable = -Infinity + const [bodyStream, contentType] = extractBody(body) + headers['content-type'] = contentType - if (cacheControlDirectives['stale-while-revalidate']) { - staleWhileRevalidate = staleAt + (cacheControlDirectives['stale-while-revalidate'] * 1000) + body = bodyStream.stream + contentLength = bodyStream.length } - if (cacheControlDirectives['stale-if-error']) { - staleIfError = staleAt + (cacheControlDirectives['stale-if-error'] * 1000) + if (contentLength == null) { + contentLength = request.contentLength } - if (staleWhileRevalidate === -Infinity && staleIfError === -Infinity) { - immutable = now + 31536000000 + if (!expectsPayload) { + // https://tools.ietf.org/html/rfc7230#section-3.3.2 + // A user agent SHOULD NOT send a Content-Length header field when + // the request message does not contain a payload body and the method + // semantics do not anticipate such a body. + // And for methods that don't expect a payload, omit Content-Length. + contentLength = null } - return Math.max(staleAt, staleWhileRevalidate, staleIfError, immutable) -} - -/** - * Strips headers required to be removed in cached responses - * @param {import('../../types/header.d.ts').IncomingHttpHeaders} resHeaders - * @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives} cacheControlDirectives - * @returns {Record} - */ -function stripNecessaryHeaders (resHeaders, cacheControlDirectives) { - const headersToRemove = [ - 'connection', - 'proxy-authenticate', - 'proxy-authentication-info', - 'proxy-authorization', - 'proxy-connection', - 'te', - 'transfer-encoding', - 'upgrade', - // We'll add age back when serving it - 'age' - ] - - if (resHeaders['connection']) { - if (Array.isArray(resHeaders['connection'])) { - // connection: a - // connection: b - headersToRemove.push(...resHeaders['connection'].map(header => header.trim())) - } else { - // connection: a, b - headersToRemove.push(...resHeaders['connection'].split(',').map(header => header.trim())) + // https://github.com/nodejs/undici/issues/2046 + // A user agent may send a Content-Length header with 0 value, this should be allowed. + if (shouldSendContentLength(method) && contentLength > 0 && request.contentLength != null && request.contentLength !== contentLength) { + if (client[kStrictContentLength]) { + util.errorRequest(client, request, new RequestContentLengthMismatchError()) + return false } - } - if (Array.isArray(cacheControlDirectives['no-cache'])) { - headersToRemove.push(...cacheControlDirectives['no-cache']) + process.emitWarning(new RequestContentLengthMismatchError()) } - if (Array.isArray(cacheControlDirectives['private'])) { - headersToRemove.push(...cacheControlDirectives['private']) + if (contentLength != null) { + assert(body || contentLength === 0, 'no body must not have content length') + headers[HTTP2_HEADER_CONTENT_LENGTH] = `${contentLength}` } - let strippedHeaders - for (const headerName of headersToRemove) { - if (resHeaders[headerName]) { - strippedHeaders ??= { ...resHeaders } - delete strippedHeaders[headerName] + session.ref() + + if (channels.sendHeaders.hasSubscribers) { + let header = '' + for (const key in headers) { + header += `${key}: ${headers[key]}\r\n` } + channels.sendHeaders.publish({ request, headers: header, socket: session[kSocket] }) } - return strippedHeaders ?? resHeaders -} + // TODO(metcoder95): add support for sending trailers + const shouldEndStream = method === 'GET' || method === 'HEAD' || body === null + if (expectContinue) { + headers[HTTP2_HEADER_EXPECT] = '100-continue' + stream = session.request(headers, { endStream: shouldEndStream, signal }) + stream[kHTTP2Stream] = true -/** - * @param {Date} date - * @returns {boolean} - */ -function isValidDate (date) { - return date instanceof Date && Number.isFinite(date.valueOf()) -} + stream.once('continue', writeBodyH2) + } else { + stream = session.request(headers, { + endStream: shouldEndStream, + signal + }) + stream[kHTTP2Stream] = true -module.exports = CacheHandler + writeBodyH2() + } + // Increment counter as we have new streams open + ++session[kOpenStreams] + stream.setTimeout(requestTimeout) -/***/ }), + // Track whether we received a response (headers) + let responseReceived = false -/***/ 7524: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + stream.once('response', headers => { + const { [HTTP2_HEADER_STATUS]: statusCode, ...realHeaders } = headers + request.onResponseStarted() + responseReceived = true -"use strict"; + // Due to the stream nature, it is possible we face a race condition + // where the stream has been assigned, but the request has been aborted + // the request remains in-flight and headers hasn't been received yet + // for those scenarios, best effort is to destroy the stream immediately + // as there's no value to keep it open. + if (request.aborted) { + stream.removeAllListeners('data') + return + } + if (request.onHeaders(Number(statusCode), parseH2Headers(realHeaders), stream.resume.bind(stream), '') === false) { + stream.pause() + } + }) -const assert = __nccwpck_require__(4589) + stream.on('data', (chunk) => { + if (request.onData(chunk) === false) { + stream.pause() + } + }) -/** - * This takes care of revalidation requests we send to the origin. If we get - * a response indicating that what we have is cached (via a HTTP 304), we can - * continue using the cached value. Otherwise, we'll receive the new response - * here, which we then just pass on to the next handler (most likely a - * CacheHandler). Note that this assumes the proper headers were already - * included in the request to tell the origin that we want to revalidate the - * response (i.e. if-modified-since or if-none-match). - * - * @see https://www.rfc-editor.org/rfc/rfc9111.html#name-validation - * - * @implements {import('../../types/dispatcher.d.ts').default.DispatchHandler} - */ -class CacheRevalidationHandler { - #successful = false - - /** - * @type {((boolean, any) => void) | null} - */ - #callback - - /** - * @type {(import('../../types/dispatcher.d.ts').default.DispatchHandler)} - */ - #handler - - #context - - /** - * @type {boolean} - */ - #allowErrorStatusCodes + stream.once('end', () => { + stream.removeAllListeners('data') + // If we received a response, this is a normal completion + if (responseReceived) { + if (!request.aborted && !request.completed) { + request.onComplete({}) + } - /** - * @param {(boolean) => void} callback Function to call if the cached value is valid - * @param {import('../../types/dispatcher.d.ts').default.DispatchHandlers} handler - * @param {boolean} allowErrorStatusCodes - */ - constructor (callback, handler, allowErrorStatusCodes) { - if (typeof callback !== 'function') { - throw new TypeError('callback must be a function') + client[kQueue][client[kRunningIdx]++] = null + client[kResume]() + } else { + // Stream ended without receiving a response - this is an error + // (e.g., server destroyed the stream before sending headers) + abort(new InformationalError('HTTP/2: stream half-closed (remote)')) + client[kQueue][client[kRunningIdx]++] = null + client[kPendingIdx] = client[kRunningIdx] + client[kResume]() } + }) - this.#callback = callback - this.#handler = handler - this.#allowErrorStatusCodes = allowErrorStatusCodes - } + stream.once('close', () => { + stream.removeAllListeners('data') + session[kOpenStreams] -= 1 + if (session[kOpenStreams] === 0) { + session.unref() + } + }) - onRequestStart (_, context) { - this.#successful = false - this.#context = context - } + stream.once('error', function (err) { + stream.removeAllListeners('data') + abort(err) + }) - onRequestUpgrade (controller, statusCode, headers, socket) { - this.#handler.onRequestUpgrade?.(controller, statusCode, headers, socket) - } + stream.once('frameError', (type, code) => { + stream.removeAllListeners('data') + abort(new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`)) + }) - onResponseStart ( - controller, - statusCode, - headers, - statusMessage - ) { - assert(this.#callback != null) + stream.on('aborted', () => { + stream.removeAllListeners('data') + }) - // https://www.rfc-editor.org/rfc/rfc9111.html#name-handling-a-validation-respo - // https://datatracker.ietf.org/doc/html/rfc5861#section-4 - this.#successful = statusCode === 304 || - (this.#allowErrorStatusCodes && statusCode >= 500 && statusCode <= 504) - this.#callback(this.#successful, this.#context) - this.#callback = null + stream.on('timeout', () => { + const err = new InformationalError(`HTTP/2: "stream timeout after ${requestTimeout}"`) + stream.removeAllListeners('data') + session[kOpenStreams] -= 1 - if (this.#successful) { - return true + if (session[kOpenStreams] === 0) { + session.unref() } - this.#handler.onRequestStart?.(controller, this.#context) - this.#handler.onResponseStart?.( - controller, - statusCode, - headers, - statusMessage - ) - } + abort(err) + }) - onResponseData (controller, chunk) { - if (this.#successful) { + stream.once('trailers', trailers => { + if (request.aborted || request.completed) { return } - return this.#handler.onResponseData?.(controller, chunk) - } + request.onComplete(trailers) + }) - onResponseEnd (controller, trailers) { - if (this.#successful) { - return - } + return true - this.#handler.onResponseEnd?.(controller, trailers) + function writeBodyH2 () { + if (!body || contentLength === 0) { + writeBuffer( + abort, + stream, + null, + client, + request, + client[kSocket], + contentLength, + expectsPayload + ) + } else if (util.isBuffer(body)) { + writeBuffer( + abort, + stream, + body, + client, + request, + client[kSocket], + contentLength, + expectsPayload + ) + } else if (util.isBlobLike(body)) { + if (typeof body.stream === 'function') { + writeIterable( + abort, + stream, + body.stream(), + client, + request, + client[kSocket], + contentLength, + expectsPayload + ) + } else { + writeBlob( + abort, + stream, + body, + client, + request, + client[kSocket], + contentLength, + expectsPayload + ) + } + } else if (util.isStream(body)) { + writeStream( + abort, + client[kSocket], + expectsPayload, + stream, + body, + client, + request, + contentLength + ) + } else if (util.isIterable(body)) { + writeIterable( + abort, + stream, + body, + client, + request, + client[kSocket], + contentLength, + expectsPayload + ) + } else { + assert(false) + } } +} - onResponseError (controller, err) { - if (this.#successful) { - return - } +function writeBuffer (abort, h2stream, body, client, request, socket, contentLength, expectsPayload) { + try { + if (body != null && util.isBuffer(body)) { + assert(contentLength === body.byteLength, 'buffer body must have content length') + h2stream.cork() + h2stream.write(body) + h2stream.uncork() + h2stream.end() - if (this.#callback) { - this.#callback(false) - this.#callback = null + request.onBodySent(body) } - if (typeof this.#handler.onResponseError === 'function') { - this.#handler.onResponseError(controller, err) - } else { - throw err + if (!expectsPayload) { + socket[kReset] = true } + + request.onRequestSent() + client[kResume]() + } catch (error) { + abort(error) } } -module.exports = CacheRevalidationHandler +function writeStream (abort, socket, expectsPayload, h2stream, body, client, request, contentLength) { + assert(contentLength !== 0 || client[kRunning] === 0, 'stream body cannot be pipelined') + // For HTTP/2, is enough to pipe the stream + const pipe = pipeline( + body, + h2stream, + (err) => { + if (err) { + util.destroy(pipe, err) + abort(err) + } else { + util.removeAllListeners(pipe) + request.onRequestSent() -/***/ }), + if (!expectsPayload) { + socket[kReset] = true + } -/***/ 5156: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + client[kResume]() + } + } + ) -"use strict"; + util.addListener(pipe, 'data', onPipeData) + function onPipeData (chunk) { + request.onBodySent(chunk) + } +} -const assert = __nccwpck_require__(4589) -const WrapHandler = __nccwpck_require__(3195) +async function writeBlob (abort, h2stream, body, client, request, socket, contentLength, expectsPayload) { + assert(contentLength === body.size, 'blob body must have content length') -/** - * @deprecated - */ -module.exports = class DecoratorHandler { - #handler - #onCompleteCalled = false - #onErrorCalled = false - #onResponseStartCalled = false + try { + if (contentLength != null && contentLength !== body.size) { + throw new RequestContentLengthMismatchError() + } - constructor (handler) { - if (typeof handler !== 'object' || handler === null) { - throw new TypeError('handler must be an object') + const buffer = Buffer.from(await body.arrayBuffer()) + + h2stream.cork() + h2stream.write(buffer) + h2stream.uncork() + h2stream.end() + + request.onBodySent(buffer) + request.onRequestSent() + + if (!expectsPayload) { + socket[kReset] = true } - this.#handler = WrapHandler.wrap(handler) - } - onRequestStart (...args) { - this.#handler.onRequestStart?.(...args) + client[kResume]() + } catch (err) { + abort(err) } +} - onRequestUpgrade (...args) { - assert(!this.#onCompleteCalled) - assert(!this.#onErrorCalled) +async function writeIterable (abort, h2stream, body, client, request, socket, contentLength, expectsPayload) { + assert(contentLength !== 0 || client[kRunning] === 0, 'iterator body cannot be pipelined') - return this.#handler.onRequestUpgrade?.(...args) + let callback = null + function onDrain () { + if (callback) { + const cb = callback + callback = null + cb() + } } - onResponseStart (...args) { - assert(!this.#onCompleteCalled) - assert(!this.#onErrorCalled) - assert(!this.#onResponseStartCalled) + const waitForDrain = () => new Promise((resolve, reject) => { + assert(callback === null) - this.#onResponseStartCalled = true + if (socket[kError]) { + reject(socket[kError]) + } else { + callback = resolve + } + }) - return this.#handler.onResponseStart?.(...args) - } + h2stream + .on('close', onDrain) + .on('drain', onDrain) - onResponseData (...args) { - assert(!this.#onCompleteCalled) - assert(!this.#onErrorCalled) + try { + // It's up to the user to somehow abort the async iterable. + for await (const chunk of body) { + if (socket[kError]) { + throw socket[kError] + } - return this.#handler.onResponseData?.(...args) - } + const res = h2stream.write(chunk) + request.onBodySent(chunk) + if (!res) { + await waitForDrain() + } + } - onResponseEnd (...args) { - assert(!this.#onCompleteCalled) - assert(!this.#onErrorCalled) + h2stream.end() - this.#onCompleteCalled = true - return this.#handler.onResponseEnd?.(...args) - } + request.onRequestSent() - onResponseError (...args) { - this.#onErrorCalled = true - return this.#handler.onResponseError?.(...args) - } + if (!expectsPayload) { + socket[kReset] = true + } - /** - * @deprecated - */ - onBodySent () {} + client[kResume]() + } catch (err) { + abort(err) + } finally { + h2stream + .off('close', onDrain) + .off('drain', onDrain) + } } +module.exports = connectH2 + /***/ }), -/***/ 2064: -/***/ ((module) => { +/***/ 1115: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -/** - * @typedef {import('../../types/dispatcher.d.ts').default.DispatchHandler} DispatchHandler - */ +const assert = __nccwpck_require__(4589) +const net = __nccwpck_require__(7030) +const http = __nccwpck_require__(7067) +const util = __nccwpck_require__(2550) +const { ClientStats } = __nccwpck_require__(7044) +const { channels } = __nccwpck_require__(2248) +const Request = __nccwpck_require__(5881) +const DispatcherBase = __nccwpck_require__(6223) +const { + InvalidArgumentError, + InformationalError, + ClientDestroyedError +} = __nccwpck_require__(5093) +const buildConnector = __nccwpck_require__(1430) +const { + kUrl, + kServerName, + kClient, + kBusy, + kConnect, + kResuming, + kRunning, + kPending, + kSize, + kQueue, + kConnected, + kConnecting, + kNeedDrain, + kKeepAliveDefaultTimeout, + kHostHeader, + kPendingIdx, + kRunningIdx, + kError, + kPipelining, + kKeepAliveTimeoutValue, + kMaxHeadersSize, + kKeepAliveMaxTimeout, + kKeepAliveTimeoutThreshold, + kHeadersTimeout, + kBodyTimeout, + kStrictContentLength, + kConnector, + kMaxRequests, + kCounter, + kClose, + kDestroy, + kDispatch, + kLocalAddress, + kMaxResponseSize, + kOnError, + kHTTPContext, + kMaxConcurrentStreams, + kHTTP2InitialWindowSize, + kHTTP2ConnectionWindowSize, + kResume +} = __nccwpck_require__(8261) +const connectH1 = __nccwpck_require__(8823) +const connectH2 = __nccwpck_require__(6250) -/** - * Handler that buffers response data and notifies multiple waiting handlers. - * Used for request deduplication. - * - * @implements {DispatchHandler} - */ -class DeduplicationHandler { - /** - * @type {DispatchHandler} - */ - #primaryHandler +const kClosedResolve = Symbol('kClosedResolve') - /** - * @type {DispatchHandler[]} - */ - #waitingHandlers = [] +const getDefaultNodeMaxHeaderSize = http && + http.maxHeaderSize && + Number.isInteger(http.maxHeaderSize) && + http.maxHeaderSize > 0 + ? () => http.maxHeaderSize + : () => { throw new InvalidArgumentError('http module not available or http.maxHeaderSize invalid') } - /** - * @type {Buffer[]} - */ - #chunks = [] +const noop = () => {} - /** - * @type {number} - */ - #statusCode = 0 +function getPipelining (client) { + return client[kPipelining] ?? client[kHTTPContext]?.defaultPipelining ?? 1 +} +/** + * @type {import('../../types/client.js').default} + */ +class Client extends DispatcherBase { /** - * @type {Record} + * + * @param {string|URL} url + * @param {import('../../types/client.js').Client.Options} options */ - #headers = {} + constructor (url, { + maxHeaderSize, + headersTimeout, + socketTimeout, + requestTimeout, + connectTimeout, + bodyTimeout, + idleTimeout, + keepAlive, + keepAliveTimeout, + maxKeepAliveTimeout, + keepAliveMaxTimeout, + keepAliveTimeoutThreshold, + socketPath, + pipelining, + tls, + strictContentLength, + maxCachedSessions, + connect, + maxRequestsPerClient, + localAddress, + maxResponseSize, + autoSelectFamily, + autoSelectFamilyAttemptTimeout, + // h2 + maxConcurrentStreams, + allowH2, + useH2c, + initialWindowSize, + connectionWindowSize + } = {}) { + if (keepAlive !== undefined) { + throw new InvalidArgumentError('unsupported keepAlive, use pipelining=0 instead') + } - /** - * @type {string} - */ - #statusMessage = '' + if (socketTimeout !== undefined) { + throw new InvalidArgumentError('unsupported socketTimeout, use headersTimeout & bodyTimeout instead') + } - /** - * @type {boolean} - */ - #aborted = false + if (requestTimeout !== undefined) { + throw new InvalidArgumentError('unsupported requestTimeout, use headersTimeout & bodyTimeout instead') + } - /** - * @type {import('../../types/dispatcher.d.ts').default.DispatchController | null} - */ - #controller = null + if (idleTimeout !== undefined) { + throw new InvalidArgumentError('unsupported idleTimeout, use keepAliveTimeout instead') + } - /** - * @type {(() => void) | null} - */ - #onComplete = null - - /** - * @param {DispatchHandler} primaryHandler The primary handler - * @param {() => void} onComplete Callback when request completes - */ - constructor (primaryHandler, onComplete) { - this.#primaryHandler = primaryHandler - this.#onComplete = onComplete - } - - /** - * Add a waiting handler that will receive the buffered response - * @param {DispatchHandler} handler - */ - addWaitingHandler (handler) { - this.#waitingHandlers.push(handler) - } + if (maxKeepAliveTimeout !== undefined) { + throw new InvalidArgumentError('unsupported maxKeepAliveTimeout, use keepAliveMaxTimeout instead') + } - /** - * @param {() => void} abort - * @param {any} context - */ - onRequestStart (controller, context) { - this.#controller = controller - this.#primaryHandler.onRequestStart?.(controller, context) - } + if (maxHeaderSize != null) { + if (!Number.isInteger(maxHeaderSize) || maxHeaderSize < 1) { + throw new InvalidArgumentError('invalid maxHeaderSize') + } + } else { + // If maxHeaderSize is not provided, use the default value from the http module + // or if that is not available, throw an error. + maxHeaderSize = getDefaultNodeMaxHeaderSize() + } - /** - * @param {import('../../types/dispatcher.d.ts').default.DispatchController} controller - * @param {number} statusCode - * @param {import('../../types/header.d.ts').IncomingHttpHeaders} headers - * @param {Socket} socket - */ - onRequestUpgrade (controller, statusCode, headers, socket) { - this.#primaryHandler.onRequestUpgrade?.(controller, statusCode, headers, socket) - } + if (socketPath != null && typeof socketPath !== 'string') { + throw new InvalidArgumentError('invalid socketPath') + } - /** - * @param {import('../../types/dispatcher.d.ts').default.DispatchController} controller - * @param {number} statusCode - * @param {Record} headers - * @param {string} statusMessage - */ - onResponseStart (controller, statusCode, headers, statusMessage) { - this.#statusCode = statusCode - this.#headers = headers - this.#statusMessage = statusMessage - this.#primaryHandler.onResponseStart?.(controller, statusCode, headers, statusMessage) - } + if (connectTimeout != null && (!Number.isFinite(connectTimeout) || connectTimeout < 0)) { + throw new InvalidArgumentError('invalid connectTimeout') + } - /** - * @param {import('../../types/dispatcher.d.ts').default.DispatchController} controller - * @param {Buffer} chunk - */ - onResponseData (controller, chunk) { - // Buffer the chunk for waiting handlers - this.#chunks.push(Buffer.from(chunk)) - this.#primaryHandler.onResponseData?.(controller, chunk) - } + if (keepAliveTimeout != null && (!Number.isFinite(keepAliveTimeout) || keepAliveTimeout <= 0)) { + throw new InvalidArgumentError('invalid keepAliveTimeout') + } - /** - * @param {import('../../types/dispatcher.d.ts').default.DispatchController} controller - * @param {object} trailers - */ - onResponseEnd (controller, trailers) { - this.#primaryHandler.onResponseEnd?.(controller, trailers) - this.#notifyWaitingHandlers() - this.#onComplete?.() - } + if (keepAliveMaxTimeout != null && (!Number.isFinite(keepAliveMaxTimeout) || keepAliveMaxTimeout <= 0)) { + throw new InvalidArgumentError('invalid keepAliveMaxTimeout') + } - /** - * @param {import('../../types/dispatcher.d.ts').default.DispatchController} controller - * @param {Error} err - */ - onResponseError (controller, err) { - this.#aborted = true - this.#primaryHandler.onResponseError?.(controller, err) - this.#notifyWaitingHandlersError(err) - this.#onComplete?.() - } + if (keepAliveTimeoutThreshold != null && !Number.isFinite(keepAliveTimeoutThreshold)) { + throw new InvalidArgumentError('invalid keepAliveTimeoutThreshold') + } - /** - * Notify all waiting handlers with the buffered response - */ - #notifyWaitingHandlers () { - const body = Buffer.concat(this.#chunks) + if (headersTimeout != null && (!Number.isInteger(headersTimeout) || headersTimeout < 0)) { + throw new InvalidArgumentError('headersTimeout must be a positive integer or zero') + } - for (const handler of this.#waitingHandlers) { - // Create a simple controller for each waiting handler - const waitingController = { - resume () {}, - pause () {}, - get paused () { return false }, - get aborted () { return false }, - get reason () { return null }, - abort () {} - } + if (bodyTimeout != null && (!Number.isInteger(bodyTimeout) || bodyTimeout < 0)) { + throw new InvalidArgumentError('bodyTimeout must be a positive integer or zero') + } - try { - handler.onRequestStart?.(waitingController, null) + if (connect != null && typeof connect !== 'function' && typeof connect !== 'object') { + throw new InvalidArgumentError('connect must be a function or an object') + } - if (waitingController.aborted) { - continue - } + if (maxRequestsPerClient != null && (!Number.isInteger(maxRequestsPerClient) || maxRequestsPerClient < 0)) { + throw new InvalidArgumentError('maxRequestsPerClient must be a positive number') + } - handler.onResponseStart?.( - waitingController, - this.#statusCode, - this.#headers, - this.#statusMessage - ) + if (localAddress != null && (typeof localAddress !== 'string' || net.isIP(localAddress) === 0)) { + throw new InvalidArgumentError('localAddress must be valid string IP address') + } - if (waitingController.aborted) { - continue - } + if (maxResponseSize != null && (!Number.isInteger(maxResponseSize) || maxResponseSize < -1)) { + throw new InvalidArgumentError('maxResponseSize must be a positive number') + } - if (body.length > 0) { - handler.onResponseData?.(waitingController, body) - } + if ( + autoSelectFamilyAttemptTimeout != null && + (!Number.isInteger(autoSelectFamilyAttemptTimeout) || autoSelectFamilyAttemptTimeout < -1) + ) { + throw new InvalidArgumentError('autoSelectFamilyAttemptTimeout must be a positive number') + } - handler.onResponseEnd?.(waitingController, {}) - } catch { - // Ignore errors from waiting handlers - } + // h2 + if (allowH2 != null && typeof allowH2 !== 'boolean') { + throw new InvalidArgumentError('allowH2 must be a valid boolean value') } - this.#waitingHandlers = [] - this.#chunks = [] - } + if (maxConcurrentStreams != null && (typeof maxConcurrentStreams !== 'number' || maxConcurrentStreams < 1)) { + throw new InvalidArgumentError('maxConcurrentStreams must be a positive integer, greater than 0') + } - /** - * Notify all waiting handlers of an error - * @param {Error} err - */ - #notifyWaitingHandlersError (err) { - for (const handler of this.#waitingHandlers) { - const waitingController = { - resume () {}, - pause () {}, - get paused () { return false }, - get aborted () { return true }, - get reason () { return err }, - abort () {} - } + if (useH2c != null && typeof useH2c !== 'boolean') { + throw new InvalidArgumentError('useH2c must be a valid boolean value') + } - try { - handler.onRequestStart?.(waitingController, null) - handler.onResponseError?.(waitingController, err) - } catch { - // Ignore errors from waiting handlers - } + if (initialWindowSize != null && (!Number.isInteger(initialWindowSize) || initialWindowSize < 1)) { + throw new InvalidArgumentError('initialWindowSize must be a positive integer, greater than 0') } - this.#waitingHandlers = [] - this.#chunks = [] - } -} + if (connectionWindowSize != null && (!Number.isInteger(connectionWindowSize) || connectionWindowSize < 1)) { + throw new InvalidArgumentError('connectionWindowSize must be a positive integer, greater than 0') + } -module.exports = DeduplicationHandler + super() + if (typeof connect !== 'function') { + connect = buildConnector({ + ...tls, + maxCachedSessions, + allowH2, + useH2c, + socketPath, + timeout: connectTimeout, + ...(typeof autoSelectFamily === 'boolean' ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : undefined), + ...connect + }) + } -/***/ }), + this[kUrl] = util.parseOrigin(url) + this[kConnector] = connect + this[kPipelining] = pipelining != null ? pipelining : 1 + this[kMaxHeadersSize] = maxHeaderSize + this[kKeepAliveDefaultTimeout] = keepAliveTimeout == null ? 4e3 : keepAliveTimeout + this[kKeepAliveMaxTimeout] = keepAliveMaxTimeout == null ? 600e3 : keepAliveMaxTimeout + this[kKeepAliveTimeoutThreshold] = keepAliveTimeoutThreshold == null ? 2e3 : keepAliveTimeoutThreshold + this[kKeepAliveTimeoutValue] = this[kKeepAliveDefaultTimeout] + this[kServerName] = null + this[kLocalAddress] = localAddress != null ? localAddress : null + this[kResuming] = 0 // 0, idle, 1, scheduled, 2 resuming + this[kNeedDrain] = 0 // 0, idle, 1, scheduled, 2 resuming + this[kHostHeader] = `host: ${this[kUrl].hostname}${this[kUrl].port ? `:${this[kUrl].port}` : ''}\r\n` + this[kBodyTimeout] = bodyTimeout != null ? bodyTimeout : 300e3 + this[kHeadersTimeout] = headersTimeout != null ? headersTimeout : 300e3 + this[kStrictContentLength] = strictContentLength == null ? true : strictContentLength + this[kMaxRequests] = maxRequestsPerClient + this[kClosedResolve] = null + this[kMaxResponseSize] = maxResponseSize > -1 ? maxResponseSize : -1 + this[kMaxConcurrentStreams] = maxConcurrentStreams != null ? maxConcurrentStreams : 100 // Max peerConcurrentStreams for a Node h2 server + // HTTP/2 window sizes are set to higher defaults than Node.js core for better performance: + // - initialWindowSize: 262144 (256KB) vs Node.js default 65535 (64KB - 1) + // Allows more data to be sent before requiring acknowledgment, improving throughput + // especially on high-latency networks. This matches common production HTTP/2 servers. + // - connectionWindowSize: 524288 (512KB) vs Node.js default (none set) + // Provides better flow control for the entire connection across multiple streams. + this[kHTTP2InitialWindowSize] = initialWindowSize != null ? initialWindowSize : 262144 + this[kHTTP2ConnectionWindowSize] = connectionWindowSize != null ? connectionWindowSize : 524288 + this[kHTTPContext] = null -/***/ 415: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // kQueue is built up of 3 sections separated by + // the kRunningIdx and kPendingIdx indices. + // | complete | running | pending | + // ^ kRunningIdx ^ kPendingIdx ^ kQueue.length + // kRunningIdx points to the first running element. + // kPendingIdx points to the first pending element. + // This implements a fast queue with an amortized + // time of O(1). -"use strict"; + this[kQueue] = [] + this[kRunningIdx] = 0 + this[kPendingIdx] = 0 + this[kResume] = (sync) => resume(this, sync) + this[kOnError] = (err) => onError(this, err) + } -const util = __nccwpck_require__(983) -const { kBodyUsed } = __nccwpck_require__(9562) -const assert = __nccwpck_require__(4589) -const { InvalidArgumentError } = __nccwpck_require__(4928) -const EE = __nccwpck_require__(8474) + get pipelining () { + return this[kPipelining] + } -const redirectableStatusCodes = [300, 301, 302, 303, 307, 308] + set pipelining (value) { + this[kPipelining] = value + this[kResume](true) + } -const kBody = Symbol('body') + get stats () { + return new ClientStats(this) + } -const noop = () => {} + get [kPending] () { + return this[kQueue].length - this[kPendingIdx] + } -class BodyAsyncIterable { - constructor (body) { - this[kBody] = body - this[kBodyUsed] = false + get [kRunning] () { + return this[kPendingIdx] - this[kRunningIdx] } - async * [Symbol.asyncIterator] () { - assert(!this[kBodyUsed], 'disturbed') - this[kBodyUsed] = true - yield * this[kBody] + get [kSize] () { + return this[kQueue].length - this[kRunningIdx] } -} -class RedirectHandler { - static buildDispatch (dispatcher, maxRedirections) { - if (maxRedirections != null && (!Number.isInteger(maxRedirections) || maxRedirections < 0)) { - throw new InvalidArgumentError('maxRedirections must be a positive number') - } + get [kConnected] () { + return !!this[kHTTPContext] && !this[kConnecting] && !this[kHTTPContext].destroyed + } - const dispatch = dispatcher.dispatch.bind(dispatcher) - return (opts, originalHandler) => dispatch(opts, new RedirectHandler(dispatch, maxRedirections, opts, originalHandler)) + get [kBusy] () { + return Boolean( + this[kHTTPContext]?.busy(null) || + (this[kSize] >= (getPipelining(this) || 1)) || + this[kPending] > 0 + ) } - constructor (dispatch, maxRedirections, opts, handler) { - if (maxRedirections != null && (!Number.isInteger(maxRedirections) || maxRedirections < 0)) { - throw new InvalidArgumentError('maxRedirections must be a positive number') - } + [kConnect] (cb) { + connect(this) + this.once('connect', cb) + } - this.dispatch = dispatch - this.location = null - const { maxRedirections: _, ...cleanOpts } = opts - this.opts = cleanOpts // opts must be a copy, exclude maxRedirections - this.maxRedirections = maxRedirections - this.handler = handler - this.history = [] + [kDispatch] (opts, handler) { + const request = new Request(this[kUrl].origin, opts, handler) - if (util.isStream(this.opts.body)) { - // TODO (fix): Provide some way for the user to cache the file to e.g. /tmp - // so that it can be dispatched again? - // TODO (fix): Do we need 100-expect support to provide a way to do this properly? - if (util.bodyLength(this.opts.body) === 0) { - this.opts.body - .on('data', function () { - assert(false) - }) - } + this[kQueue].push(request) + if (this[kResuming]) { + // Do nothing. + } else if (util.bodyLength(request.body) == null && util.isIterable(request.body)) { + // Wait a tick in case stream/iterator is ended in the same tick. + this[kResuming] = 1 + queueMicrotask(() => resume(this)) + } else { + this[kResume](true) + } - if (typeof this.opts.body.readableDidRead !== 'boolean') { - this.opts.body[kBodyUsed] = false - EE.prototype.on.call(this.opts.body, 'data', function () { - this[kBodyUsed] = true - }) - } - } else if (this.opts.body && typeof this.opts.body.pipeTo === 'function') { - // TODO (fix): We can't access ReadableStream internal state - // to determine whether or not it has been disturbed. This is just - // a workaround. - this.opts.body = new BodyAsyncIterable(this.opts.body) - } else if ( - this.opts.body && - typeof this.opts.body !== 'string' && - !ArrayBuffer.isView(this.opts.body) && - util.isIterable(this.opts.body) && - !util.isFormDataLike(this.opts.body) - ) { - // TODO: Should we allow re-using iterable if !this.opts.idempotent - // or through some other flag? - this.opts.body = new BodyAsyncIterable(this.opts.body) + if (this[kResuming] && this[kNeedDrain] !== 2 && this[kBusy]) { + this[kNeedDrain] = 2 } - } - onRequestStart (controller, context) { - this.handler.onRequestStart?.(controller, { ...context, history: this.history }) + return this[kNeedDrain] < 2 } - onRequestUpgrade (controller, statusCode, headers, socket) { - this.handler.onRequestUpgrade?.(controller, statusCode, headers, socket) + [kClose] () { + // TODO: for H2 we need to gracefully flush the remaining enqueued + // request and close each stream. + return new Promise((resolve) => { + if (this[kSize]) { + this[kClosedResolve] = resolve + } else { + resolve(null) + } + }) } - onResponseStart (controller, statusCode, headers, statusMessage) { - if (this.opts.throwOnMaxRedirect && this.history.length >= this.maxRedirections) { - throw new Error('max redirects') - } + [kDestroy] (err) { + return new Promise((resolve) => { + const requests = this[kQueue].splice(this[kPendingIdx]) + for (let i = 0; i < requests.length; i++) { + const request = requests[i] + util.errorRequest(this, request, err) + } - // https://tools.ietf.org/html/rfc7231#section-6.4.2 - // https://fetch.spec.whatwg.org/#http-redirect-fetch - // In case of HTTP 301 or 302 with POST, change the method to GET - if ((statusCode === 301 || statusCode === 302) && this.opts.method === 'POST') { - this.opts.method = 'GET' - if (util.isStream(this.opts.body)) { - util.destroy(this.opts.body.on('error', noop)) + const callback = () => { + if (this[kClosedResolve]) { + // TODO (fix): Should we error here with ClientDestroyedError? + this[kClosedResolve]() + this[kClosedResolve] = null + } + resolve(null) } - this.opts.body = null - } - // https://tools.ietf.org/html/rfc7231#section-6.4.4 - // In case of HTTP 303, always replace method to be either HEAD or GET - if (statusCode === 303 && this.opts.method !== 'HEAD') { - this.opts.method = 'GET' - if (util.isStream(this.opts.body)) { - util.destroy(this.opts.body.on('error', noop)) + if (this[kHTTPContext]) { + this[kHTTPContext].destroy(err, callback) + this[kHTTPContext] = null + } else { + queueMicrotask(callback) } - this.opts.body = null - } - this.location = this.history.length >= this.maxRedirections || util.isDisturbed(this.opts.body) || redirectableStatusCodes.indexOf(statusCode) === -1 - ? null - : headers.location + this[kResume]() + }) + } +} - if (this.opts.origin) { - this.history.push(new URL(this.opts.path, this.opts.origin)) - } +function onError (client, err) { + if ( + client[kRunning] === 0 && + err.code !== 'UND_ERR_INFO' && + err.code !== 'UND_ERR_SOCKET' + ) { + // Error is not caused by running request and not a recoverable + // socket error. - if (!this.location) { - this.handler.onResponseStart?.(controller, statusCode, headers, statusMessage) - return - } + assert(client[kPendingIdx] === client[kRunningIdx]) - const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin))) - const path = search ? `${pathname}${search}` : pathname + const requests = client[kQueue].splice(client[kRunningIdx]) - // Check for redirect loops by seeing if we've already visited this URL in our history - // This catches the case where Client/Pool try to handle cross-origin redirects but fail - // and keep redirecting to the same URL in an infinite loop - const redirectUrlString = `${origin}${path}` - for (const historyUrl of this.history) { - if (historyUrl.toString() === redirectUrlString) { - throw new InvalidArgumentError(`Redirect loop detected. Cannot redirect to ${origin}. This typically happens when using a Client or Pool with cross-origin redirects. Use an Agent for cross-origin redirects.`) - } + for (let i = 0; i < requests.length; i++) { + const request = requests[i] + util.errorRequest(client, request, err) } - - // Remove headers referring to the original URL. - // By default it is Host only, unless it's a 303 (see below), which removes also all Content-* headers. - // https://tools.ietf.org/html/rfc7231#section-6.4 - this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin) - this.opts.path = path - this.opts.origin = origin - this.opts.query = null + assert(client[kSize] === 0) } +} - onResponseData (controller, chunk) { - if (this.location) { - /* - https://tools.ietf.org/html/rfc7231#section-6.4 +/** + * @param {Client} client + * @returns {void} + */ +function connect (client) { + assert(!client[kConnecting]) + assert(!client[kHTTPContext]) - TLDR: undici always ignores 3xx response bodies. + let { host, hostname, protocol, port } = client[kUrl] - Redirection is used to serve the requested resource from another URL, so it assumes that - no body is generated (and thus can be ignored). Even though generating a body is not prohibited. + // Resolve ipv6 + if (hostname[0] === '[') { + const idx = hostname.indexOf(']') - For status 301, 302, 303, 307 and 308 (the latter from RFC 7238), the specs mention that the body usually - (which means it's optional and not mandated) contain just an hyperlink to the value of - the Location response header, so the body can be ignored safely. + assert(idx !== -1) + const ip = hostname.substring(1, idx) - For status 300, which is "Multiple Choices", the spec mentions both generating a Location - response header AND a response body with the other possible location to follow. - Since the spec explicitly chooses not to specify a format for such body and leave it to - servers and browsers implementors, we ignore the body as there is no specified way to eventually parse it. - */ - } else { - this.handler.onResponseData?.(controller, chunk) - } + assert(net.isIPv6(ip)) + hostname = ip } - onResponseEnd (controller, trailers) { - if (this.location) { - /* - https://tools.ietf.org/html/rfc7231#section-6.4 + client[kConnecting] = true - TLDR: undici always ignores 3xx response trailers as they are not expected in case of redirections - and neither are useful if present. + if (channels.beforeConnect.hasSubscribers) { + channels.beforeConnect.publish({ + connectParams: { + host, + hostname, + protocol, + port, + version: client[kHTTPContext]?.version, + servername: client[kServerName], + localAddress: client[kLocalAddress] + }, + connector: client[kConnector] + }) + } - See comment on onData method above for more detailed information. - */ - this.dispatch(this.opts, this) - } else { - this.handler.onResponseEnd(controller, trailers) + client[kConnector]({ + host, + hostname, + protocol, + port, + servername: client[kServerName], + localAddress: client[kLocalAddress] + }, (err, socket) => { + if (err) { + handleConnectError(client, err, { host, hostname, protocol, port }) + client[kResume]() + return } - } - onResponseError (controller, error) { - this.handler.onResponseError?.(controller, error) - } + if (client.destroyed) { + util.destroy(socket.on('error', noop), new ClientDestroyedError()) + client[kResume]() + return + } + + assert(socket) + + try { + client[kHTTPContext] = socket.alpnProtocol === 'h2' + ? connectH2(client, socket) + : connectH1(client, socket) + } catch (err) { + socket.destroy().on('error', noop) + handleConnectError(client, err, { host, hostname, protocol, port }) + client[kResume]() + return + } + + client[kConnecting] = false + + socket[kCounter] = 0 + socket[kMaxRequests] = client[kMaxRequests] + socket[kClient] = client + socket[kError] = null + + if (channels.connected.hasSubscribers) { + channels.connected.publish({ + connectParams: { + host, + hostname, + protocol, + port, + version: client[kHTTPContext]?.version, + servername: client[kServerName], + localAddress: client[kLocalAddress] + }, + connector: client[kConnector], + socket + }) + } + + client.emit('connect', client[kUrl], [client]) + client[kResume]() + }) } -// https://tools.ietf.org/html/rfc7231#section-6.4.4 -function shouldRemoveHeader (header, removeContent, unknownOrigin) { - if (header.length === 4) { - return util.headerNameToString(header) === 'host' - } - if (removeContent && util.headerNameToString(header).startsWith('content-')) { - return true +function handleConnectError (client, err, { host, hostname, protocol, port }) { + if (client.destroyed) { + return } - if (unknownOrigin && (header.length === 13 || header.length === 6 || header.length === 19)) { - const name = util.headerNameToString(header) - return name === 'authorization' || name === 'cookie' || name === 'proxy-authorization' + + client[kConnecting] = false + + if (channels.connectError.hasSubscribers) { + channels.connectError.publish({ + connectParams: { + host, + hostname, + protocol, + port, + version: client[kHTTPContext]?.version, + servername: client[kServerName], + localAddress: client[kLocalAddress] + }, + connector: client[kConnector], + error: err + }) } - return false -} -// https://tools.ietf.org/html/rfc7231#section-6.4 -function cleanRequestHeaders (headers, removeContent, unknownOrigin) { - const ret = [] - if (Array.isArray(headers)) { - for (let i = 0; i < headers.length; i += 2) { - if (!shouldRemoveHeader(headers[i], removeContent, unknownOrigin)) { - ret.push(headers[i], headers[i + 1]) - } - } - } else if (headers && typeof headers === 'object') { - const entries = typeof headers[Symbol.iterator] === 'function' ? headers : Object.entries(headers) - for (const [key, value] of entries) { - if (!shouldRemoveHeader(key, removeContent, unknownOrigin)) { - ret.push(key, value) - } + if (err.code === 'ERR_TLS_CERT_ALTNAME_INVALID') { + assert(client[kRunning] === 0) + while (client[kPending] > 0 && client[kQueue][client[kPendingIdx]].servername === client[kServerName]) { + const request = client[kQueue][client[kPendingIdx]++] + util.errorRequest(client, request, err) } } else { - assert(headers == null, 'headers must be an object or an array') + onError(client, err) } - return ret -} -module.exports = RedirectHandler - - -/***/ }), + client.emit('connectionError', client[kUrl], [client], err) +} -/***/ 4943: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +function emitDrain (client) { + client[kNeedDrain] = 0 + client.emit('drain', client[kUrl], [client]) +} -"use strict"; +function resume (client, sync) { + if (client[kResuming] === 2) { + return + } -const assert = __nccwpck_require__(4589) + client[kResuming] = 2 -const { kRetryHandlerDefaultRetry } = __nccwpck_require__(9562) -const { RequestRetryError } = __nccwpck_require__(4928) -const WrapHandler = __nccwpck_require__(3195) -const { - isDisturbed, - parseRangeHeader, - wrapRequestBody -} = __nccwpck_require__(983) + _resume(client, sync) + client[kResuming] = 0 -function calculateRetryAfterHeader (retryAfter) { - const retryTime = new Date(retryAfter).getTime() - return isNaN(retryTime) ? 0 : retryTime - Date.now() + if (client[kRunningIdx] > 256) { + client[kQueue].splice(0, client[kRunningIdx]) + client[kPendingIdx] -= client[kRunningIdx] + client[kRunningIdx] = 0 + } } -class RetryHandler { - constructor (opts, { dispatch, handler }) { - const { retryOptions, ...dispatchOpts } = opts - const { - // Retry scoped - retry: retryFn, - maxRetries, - maxTimeout, - minTimeout, - timeoutFactor, - // Response scoped - methods, - errorCodes, - retryAfter, - statusCodes, - throwOnError - } = retryOptions ?? {} +function _resume (client, sync) { + while (true) { + if (client.destroyed) { + assert(client[kPending] === 0) + return + } - this.error = null - this.dispatch = dispatch - this.handler = WrapHandler.wrap(handler) - this.opts = { ...dispatchOpts, body: wrapRequestBody(opts.body) } - this.retryOpts = { - throwOnError: throwOnError ?? true, - retry: retryFn ?? RetryHandler[kRetryHandlerDefaultRetry], - retryAfter: retryAfter ?? true, - maxTimeout: maxTimeout ?? 30 * 1000, // 30s, - minTimeout: minTimeout ?? 500, // .5s - timeoutFactor: timeoutFactor ?? 2, - maxRetries: maxRetries ?? 5, - // What errors we should retry - methods: methods ?? ['GET', 'HEAD', 'OPTIONS', 'PUT', 'DELETE', 'TRACE'], - // Indicates which errors to retry - statusCodes: statusCodes ?? [500, 502, 503, 504, 429], - // List of errors to retry - errorCodes: errorCodes ?? [ - 'ECONNRESET', - 'ECONNREFUSED', - 'ENOTFOUND', - 'ENETDOWN', - 'ENETUNREACH', - 'EHOSTDOWN', - 'EHOSTUNREACH', - 'EPIPE', - 'UND_ERR_SOCKET' - ] + if (client[kClosedResolve] && !client[kSize]) { + client[kClosedResolve]() + client[kClosedResolve] = null + return } - this.retryCount = 0 - this.retryCountCheckpoint = 0 - this.headersSent = false - this.start = 0 - this.end = null - this.etag = null - } + if (client[kHTTPContext]) { + client[kHTTPContext].resume() + } - onResponseStartWithRetry (controller, statusCode, headers, statusMessage, err) { - if (this.retryOpts.throwOnError) { - // Preserve old behavior for status codes that are not eligible for retry - if (this.retryOpts.statusCodes.includes(statusCode) === false) { - this.headersSent = true - this.handler.onResponseStart?.(controller, statusCode, headers, statusMessage) + if (client[kBusy]) { + client[kNeedDrain] = 2 + } else if (client[kNeedDrain] === 2) { + if (sync) { + client[kNeedDrain] = 1 + queueMicrotask(() => emitDrain(client)) } else { - this.error = err + emitDrain(client) } + continue + } + if (client[kPending] === 0) { return } - if (isDisturbed(this.opts.body)) { - this.headersSent = true - this.handler.onResponseStart?.(controller, statusCode, headers, statusMessage) + if (client[kRunning] >= (getPipelining(client) || 1)) { return } - function shouldRetry (passedErr) { - if (passedErr) { - this.headersSent = true - this.handler.onResponseStart?.(controller, statusCode, headers, statusMessage) - controller.resume() + const request = client[kQueue][client[kPendingIdx]] + + if (client[kUrl].protocol === 'https:' && client[kServerName] !== request.servername) { + if (client[kRunning] > 0) { return } - this.error = err - controller.resume() - } - - controller.pause() - this.retryOpts.retry( - err, - { - state: { counter: this.retryCount }, - opts: { retryOptions: this.retryOpts, ...this.opts } - }, - shouldRetry.bind(this) - ) - } - - onRequestStart (controller, context) { - if (!this.headersSent) { - this.handler.onRequestStart?.(controller, context) + client[kServerName] = request.servername + client[kHTTPContext]?.destroy(new InformationalError('servername changed'), () => { + client[kHTTPContext] = null + resume(client) + }) } - } - - onRequestUpgrade (controller, statusCode, headers, socket) { - this.handler.onRequestUpgrade?.(controller, statusCode, headers, socket) - } - - static [kRetryHandlerDefaultRetry] (err, { state, opts }, cb) { - const { statusCode, code, headers } = err - const { method, retryOptions } = opts - const { - maxRetries, - minTimeout, - maxTimeout, - timeoutFactor, - statusCodes, - errorCodes, - methods - } = retryOptions - const { counter } = state - // Any code that is not a Undici's originated and allowed to retry - if (code && code !== 'UND_ERR_REQ_RETRY' && !errorCodes.includes(code)) { - cb(err) + if (client[kConnecting]) { return } - // If a set of method are provided and the current method is not in the list - if (Array.isArray(methods) && !methods.includes(method)) { - cb(err) + if (!client[kHTTPContext]) { + connect(client) return } - // If a set of status code are provided and the current status code is not in the list - if ( - statusCode != null && - Array.isArray(statusCodes) && - !statusCodes.includes(statusCode) - ) { - cb(err) + if (client[kHTTPContext].destroyed) { return } - // If we reached the max number of retries - if (counter > maxRetries) { - cb(err) + if (client[kHTTPContext].busy(request)) { return } - let retryAfterHeader = headers?.['retry-after'] - if (retryAfterHeader) { - retryAfterHeader = Number(retryAfterHeader) - retryAfterHeader = Number.isNaN(retryAfterHeader) - ? calculateRetryAfterHeader(headers['retry-after']) - : retryAfterHeader * 1e3 // Retry-After is in seconds + if (!request.aborted && client[kHTTPContext].write(request)) { + client[kPendingIdx]++ + } else { + client[kQueue].splice(client[kPendingIdx], 1) } - - const retryTimeout = - retryAfterHeader > 0 - ? Math.min(retryAfterHeader, maxTimeout) - : Math.min(minTimeout * timeoutFactor ** (counter - 1), maxTimeout) - - setTimeout(() => cb(null), retryTimeout) } +} - onResponseStart (controller, statusCode, headers, statusMessage) { - this.error = null - this.retryCount += 1 - - if (statusCode >= 300) { - const err = new RequestRetryError('Request failed', statusCode, { - headers, - data: { - count: this.retryCount - } - }) - - this.onResponseStartWithRetry(controller, statusCode, headers, statusMessage, err) - return - } - - // Checkpoint for resume from where we left it - if (this.headersSent) { - // Only Partial Content 206 supposed to provide Content-Range, - // any other status code that partially consumed the payload - // should not be retried because it would result in downstream - // wrongly concatenate multiple responses. - if (statusCode !== 206 && (this.start > 0 || statusCode !== 200)) { - throw new RequestRetryError('server does not support the range header and the payload was partially consumed', statusCode, { - headers, - data: { count: this.retryCount } - }) - } +module.exports = Client - const contentRange = parseRangeHeader(headers['content-range']) - // If no content range - if (!contentRange) { - // We always throw here as we want to indicate that we entred unexpected path - throw new RequestRetryError('Content-Range mismatch', statusCode, { - headers, - data: { count: this.retryCount } - }) - } - // Let's start with a weak etag check - if (this.etag != null && this.etag !== headers.etag) { - // We always throw here as we want to indicate that we entred unexpected path - throw new RequestRetryError('ETag mismatch', statusCode, { - headers, - data: { count: this.retryCount } - }) - } +/***/ }), - const { start, size, end = size ? size - 1 : null } = contentRange +/***/ 6223: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - assert(this.start === start, 'content-range mismatch') - assert(this.end == null || this.end === end, 'content-range mismatch') - return - } - if (this.end == null) { - if (statusCode === 206) { - // First time we receive 206 - const range = parseRangeHeader(headers['content-range']) +const Dispatcher = __nccwpck_require__(5085) +const UnwrapHandler = __nccwpck_require__(2791) +const { + ClientDestroyedError, + ClientClosedError, + InvalidArgumentError +} = __nccwpck_require__(5093) +const { kDestroy, kClose, kClosed, kDestroyed, kDispatch } = __nccwpck_require__(8261) - if (range == null) { - this.headersSent = true - this.handler.onResponseStart?.( - controller, - statusCode, - headers, - statusMessage - ) - return - } +const kOnDestroyed = Symbol('onDestroyed') +const kOnClosed = Symbol('onClosed') - const { start, size, end = size ? size - 1 : null } = range - assert( - start != null && Number.isFinite(start), - 'content-range mismatch' - ) - assert(end != null && Number.isFinite(end), 'invalid content-length') +class DispatcherBase extends Dispatcher { + /** @type {boolean} */ + [kDestroyed] = false; - this.start = start - this.end = end - } + /** @type {Array|null} */ + [kOnClosed] = null - this.resume = true - this.etag = headers.etag != null ? headers.etag : null + /** @returns {boolean} */ + get destroyed () { + return this[kDestroyed] + } - // Weak etags are not useful for comparison nor cache - // for instance not safe to assume if the response is byte-per-byte - // equal - if ( - this.etag != null && - this.etag[0] === 'W' && - this.etag[1] === '/' - ) { - this.etag = null - } + /** @returns {boolean} */ + get closed () { + return this[kClosed] + } - this.headersSent = true - this.handler.onResponseStart?.( - controller, - statusCode, - headers, - statusMessage - ) - } else { - throw new RequestRetryError('Request failed', statusCode, { - headers, - data: { count: this.retryCount } + close (callback) { + if (callback === undefined) { + return new Promise((resolve, reject) => { + this.close((err, data) => { + return err ? reject(err) : resolve(data) + }) }) } - } - onResponseData (controller, chunk) { - if (this.error) { - return + if (typeof callback !== 'function') { + throw new InvalidArgumentError('invalid callback') } - this.start += chunk.length - - this.handler.onResponseData?.(controller, chunk) - } - - onResponseEnd (controller, trailers) { - if (this.error && this.retryOpts.throwOnError) { - throw this.error + if (this[kDestroyed]) { + const err = new ClientDestroyedError() + queueMicrotask(() => callback(err, null)) + return } - if (!this.error) { - this.retryCount = 0 - return this.handler.onResponseEnd?.(controller, trailers) + if (this[kClosed]) { + if (this[kOnClosed]) { + this[kOnClosed].push(callback) + } else { + queueMicrotask(() => callback(null, null)) + } + return } - this.retry(controller) - } - - retry (controller) { - if (this.start !== 0) { - const headers = { range: `bytes=${this.start}-${this.end ?? ''}` } - - // Weak etag check - weak etags will make comparison algorithms never match - if (this.etag != null) { - headers['if-match'] = this.etag - } + this[kClosed] = true + this[kOnClosed] ??= [] + this[kOnClosed].push(callback) - this.opts = { - ...this.opts, - headers: { - ...this.opts.headers, - ...headers - } + const onClosed = () => { + const callbacks = this[kOnClosed] + this[kOnClosed] = null + for (let i = 0; i < callbacks.length; i++) { + callbacks[i](null, null) } } - try { - this.retryCountCheckpoint = this.retryCount - this.dispatch(this.opts, this) - } catch (err) { - this.handler.onResponseError?.(controller, err) - } + // Should not error. + this[kClose]() + .then(() => this.destroy()) + .then(() => queueMicrotask(onClosed)) } - onResponseError (controller, err) { - if (controller?.aborted || isDisturbed(this.opts.body)) { - this.handler.onResponseError?.(controller, err) - return + destroy (err, callback) { + if (typeof err === 'function') { + callback = err + err = null } - function shouldRetry (returnedErr) { - if (!returnedErr) { - this.retry(controller) - return - } + if (callback === undefined) { + return new Promise((resolve, reject) => { + this.destroy(err, (err, data) => { + return err ? reject(err) : resolve(data) + }) + }) + } - this.handler?.onResponseError?.(controller, returnedErr) + if (typeof callback !== 'function') { + throw new InvalidArgumentError('invalid callback') } - // We reconcile in case of a mix between network errors - // and server error response - if (this.retryCount - this.retryCountCheckpoint > 0) { - // We count the difference between the last checkpoint and the current retry count - this.retryCount = - this.retryCountCheckpoint + - (this.retryCount - this.retryCountCheckpoint) - } else { - this.retryCount += 1 + if (this[kDestroyed]) { + if (this[kOnDestroyed]) { + this[kOnDestroyed].push(callback) + } else { + queueMicrotask(() => callback(null, null)) + } + return } - this.retryOpts.retry( - err, - { - state: { counter: this.retryCount }, - opts: { retryOptions: this.retryOpts, ...this.opts } - }, - shouldRetry.bind(this) - ) - } -} + if (!err) { + err = new ClientDestroyedError() + } -module.exports = RetryHandler + this[kDestroyed] = true + this[kOnDestroyed] ??= [] + this[kOnDestroyed].push(callback) + const onDestroyed = () => { + const callbacks = this[kOnDestroyed] + this[kOnDestroyed] = null + for (let i = 0; i < callbacks.length; i++) { + callbacks[i](null, null) + } + } -/***/ }), + // Should not error. + this[kDestroy](err) + .then(() => queueMicrotask(onDestroyed)) + } -/***/ 220: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + dispatch (opts, handler) { + if (!handler || typeof handler !== 'object') { + throw new InvalidArgumentError('handler must be an object') + } -"use strict"; + handler = UnwrapHandler.unwrap(handler) + try { + if (!opts || typeof opts !== 'object') { + throw new InvalidArgumentError('opts must be an object.') + } -const { parseHeaders } = __nccwpck_require__(983) -const { InvalidArgumentError } = __nccwpck_require__(4928) + if (this[kDestroyed] || this[kOnDestroyed]) { + throw new ClientDestroyedError() + } -const kResume = Symbol('resume') + if (this[kClosed]) { + throw new ClientClosedError() + } -class UnwrapController { - #paused = false - #reason = null - #aborted = false - #abort + return this[kDispatch](opts, handler) + } catch (err) { + if (typeof handler.onError !== 'function') { + throw err + } - [kResume] = null + handler.onError(err) - constructor (abort) { - this.#abort = abort + return false + } } +} - pause () { - this.#paused = true - } +module.exports = DispatcherBase - resume () { - if (this.#paused) { - this.#paused = false - this[kResume]?.() - } - } - abort (reason) { - if (!this.#aborted) { - this.#aborted = true - this.#reason = reason - this.#abort(reason) - } - } +/***/ }), - get aborted () { - return this.#aborted - } +/***/ 5085: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - get reason () { - return this.#reason - } - get paused () { - return this.#paused - } -} +const EventEmitter = __nccwpck_require__(8474) +const WrapHandler = __nccwpck_require__(6444) -module.exports = class UnwrapHandler { - #handler - #controller +const wrapInterceptor = (dispatch) => (opts, handler) => dispatch(opts, WrapHandler.wrap(handler)) - constructor (handler) { - this.#handler = handler +class Dispatcher extends EventEmitter { + dispatch () { + throw new Error('not implemented') } - static unwrap (handler) { - // TODO (fix): More checks... - return !handler.onRequestStart ? handler : new UnwrapHandler(handler) + close () { + throw new Error('not implemented') } - onConnect (abort, context) { - this.#controller = new UnwrapController(abort) - this.#handler.onRequestStart?.(this.#controller, context) + destroy () { + throw new Error('not implemented') } - onUpgrade (statusCode, rawHeaders, socket) { - this.#handler.onRequestUpgrade?.(this.#controller, statusCode, parseHeaders(rawHeaders), socket) - } + compose (...args) { + // So we handle [interceptor1, interceptor2] or interceptor1, interceptor2, ... + const interceptors = Array.isArray(args[0]) ? args[0] : args + let dispatch = this.dispatch.bind(this) - onHeaders (statusCode, rawHeaders, resume, statusMessage) { - this.#controller[kResume] = resume - this.#handler.onResponseStart?.(this.#controller, statusCode, parseHeaders(rawHeaders), statusMessage) - return !this.#controller.paused - } + for (const interceptor of interceptors) { + if (interceptor == null) { + continue + } - onData (data) { - this.#handler.onResponseData?.(this.#controller, data) - return !this.#controller.paused - } + if (typeof interceptor !== 'function') { + throw new TypeError(`invalid interceptor, expected function received ${typeof interceptor}`) + } - onComplete (rawTrailers) { - this.#handler.onResponseEnd?.(this.#controller, parseHeaders(rawTrailers)) - } + dispatch = interceptor(dispatch) + dispatch = wrapInterceptor(dispatch) - onError (err) { - if (!this.#handler.onResponseError) { - throw new InvalidArgumentError('invalid onError method') + if (dispatch == null || typeof dispatch !== 'function' || dispatch.length !== 2) { + throw new TypeError('invalid interceptor') + } } - this.#handler.onResponseError?.(this.#controller, err) + return new Proxy(this, { + get: (target, key) => key === 'dispatch' ? dispatch : target[key] + }) } } +module.exports = Dispatcher + /***/ }), -/***/ 3195: +/***/ 5071: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -const { InvalidArgumentError } = __nccwpck_require__(4928) +const DispatcherBase = __nccwpck_require__(6223) +const { kClose, kDestroy, kClosed, kDestroyed, kDispatch, kNoProxyAgent, kHttpProxyAgent, kHttpsProxyAgent } = __nccwpck_require__(8261) +const ProxyAgent = __nccwpck_require__(2050) +const Agent = __nccwpck_require__(9959) -module.exports = class WrapHandler { - #handler +const DEFAULT_PORTS = { + 'http:': 80, + 'https:': 443 +} - constructor (handler) { - this.#handler = handler - } +class EnvHttpProxyAgent extends DispatcherBase { + #noProxyValue = null + #noProxyEntries = null + #opts = null - static wrap (handler) { - // TODO (fix): More checks... - return handler.onRequestStart ? handler : new WrapHandler(handler) - } + constructor (opts = {}) { + super() + this.#opts = opts - // Unwrap Interface + const { httpProxy, httpsProxy, noProxy, ...agentOpts } = opts - onConnect (abort, context) { - return this.#handler.onConnect?.(abort, context) - } + this[kNoProxyAgent] = new Agent(agentOpts) - onHeaders (statusCode, rawHeaders, resume, statusMessage) { - return this.#handler.onHeaders?.(statusCode, rawHeaders, resume, statusMessage) - } + const HTTP_PROXY = httpProxy ?? process.env.http_proxy ?? process.env.HTTP_PROXY + if (HTTP_PROXY) { + this[kHttpProxyAgent] = new ProxyAgent({ ...agentOpts, uri: HTTP_PROXY }) + } else { + this[kHttpProxyAgent] = this[kNoProxyAgent] + } - onUpgrade (statusCode, rawHeaders, socket) { - return this.#handler.onUpgrade?.(statusCode, rawHeaders, socket) - } + const HTTPS_PROXY = httpsProxy ?? process.env.https_proxy ?? process.env.HTTPS_PROXY + if (HTTPS_PROXY) { + this[kHttpsProxyAgent] = new ProxyAgent({ ...agentOpts, uri: HTTPS_PROXY }) + } else { + this[kHttpsProxyAgent] = this[kHttpProxyAgent] + } - onData (data) { - return this.#handler.onData?.(data) + this.#parseNoProxy() } - onComplete (trailers) { - return this.#handler.onComplete?.(trailers) + [kDispatch] (opts, handler) { + const url = new URL(opts.origin) + const agent = this.#getProxyAgentForUrl(url) + return agent.dispatch(opts, handler) } - onError (err) { - if (!this.#handler.onError) { - throw err - } - - return this.#handler.onError?.(err) + [kClose] () { + return Promise.all([ + this[kNoProxyAgent].close(), + !this[kHttpProxyAgent][kClosed] && this[kHttpProxyAgent].close(), + !this[kHttpsProxyAgent][kClosed] && this[kHttpsProxyAgent].close() + ]) } - // Wrap Interface - - onRequestStart (controller, context) { - this.#handler.onConnect?.((reason) => controller.abort(reason), context) + [kDestroy] (err) { + return Promise.all([ + this[kNoProxyAgent].destroy(err), + !this[kHttpProxyAgent][kDestroyed] && this[kHttpProxyAgent].destroy(err), + !this[kHttpsProxyAgent][kDestroyed] && this[kHttpsProxyAgent].destroy(err) + ]) } - onRequestUpgrade (controller, statusCode, headers, socket) { - const rawHeaders = [] - for (const [key, val] of Object.entries(headers)) { - rawHeaders.push(Buffer.from(key), Array.isArray(val) ? val.map(v => Buffer.from(v)) : Buffer.from(val)) - } + #getProxyAgentForUrl (url) { + let { protocol, host: hostname, port } = url - this.#handler.onUpgrade?.(statusCode, rawHeaders, socket) + // Stripping ports in this way instead of using parsedUrl.hostname to make + // sure that the brackets around IPv6 addresses are kept. + hostname = hostname.replace(/:\d*$/, '').toLowerCase() + port = Number.parseInt(port, 10) || DEFAULT_PORTS[protocol] || 0 + if (!this.#shouldProxy(hostname, port)) { + return this[kNoProxyAgent] + } + if (protocol === 'https:') { + return this[kHttpsProxyAgent] + } + return this[kHttpProxyAgent] } - onResponseStart (controller, statusCode, headers, statusMessage) { - const rawHeaders = [] - for (const [key, val] of Object.entries(headers)) { - rawHeaders.push(Buffer.from(key), Array.isArray(val) ? val.map(v => Buffer.from(v)) : Buffer.from(val)) + #shouldProxy (hostname, port) { + if (this.#noProxyChanged) { + this.#parseNoProxy() } - if (this.#handler.onHeaders?.(statusCode, rawHeaders, () => controller.resume(), statusMessage) === false) { - controller.pause() + if (this.#noProxyEntries.length === 0) { + return true // Always proxy if NO_PROXY is not set or empty. + } + if (this.#noProxyValue === '*') { + return false // Never proxy if wildcard is set. } - } - onResponseData (controller, data) { - if (this.#handler.onData?.(data) === false) { - controller.pause() + for (let i = 0; i < this.#noProxyEntries.length; i++) { + const entry = this.#noProxyEntries[i] + if (entry.port && entry.port !== port) { + continue // Skip if ports don't match. + } + if (!/^[.*]/.test(entry.hostname)) { + // No wildcards, so don't proxy only if there is not an exact match. + if (hostname === entry.hostname) { + return false + } + } else { + // Don't proxy if the hostname ends with the no_proxy host. + if (hostname.endsWith(entry.hostname.replace(/^\*/, ''))) { + return false + } + } } + + return true } - onResponseEnd (controller, trailers) { - const rawTrailers = [] - for (const [key, val] of Object.entries(trailers)) { - rawTrailers.push(Buffer.from(key), Array.isArray(val) ? val.map(v => Buffer.from(v)) : Buffer.from(val)) + #parseNoProxy () { + const noProxyValue = this.#opts.noProxy ?? this.#noProxyEnv + const noProxySplit = noProxyValue.split(/[,\s]/) + const noProxyEntries = [] + + for (let i = 0; i < noProxySplit.length; i++) { + const entry = noProxySplit[i] + if (!entry) { + continue + } + const parsed = entry.match(/^(.+):(\d+)$/) + noProxyEntries.push({ + hostname: (parsed ? parsed[1] : entry).toLowerCase(), + port: parsed ? Number.parseInt(parsed[2], 10) : 0 + }) } - this.#handler.onComplete?.(rawTrailers) + this.#noProxyValue = noProxyValue + this.#noProxyEntries = noProxyEntries } - onResponseError (controller, err) { - if (!this.#handler.onError) { - throw new InvalidArgumentError('invalid onError method') + get #noProxyChanged () { + if (this.#opts.noProxy !== undefined) { + return false } + return this.#noProxyValue !== this.#noProxyEnv + } - this.#handler.onError?.(err) + get #noProxyEnv () { + return process.env.no_proxy ?? process.env.NO_PROXY ?? '' } } +module.exports = EnvHttpProxyAgent + /***/ }), -/***/ 5661: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +/***/ 1506: +/***/ ((module) => { -"use strict"; -const assert = __nccwpck_require__(4589) -const { Readable } = __nccwpck_require__(7075) -const util = __nccwpck_require__(983) -const CacheHandler = __nccwpck_require__(2387) -const MemoryCacheStore = __nccwpck_require__(9972) -const CacheRevalidationHandler = __nccwpck_require__(7524) -const { assertCacheStore, assertCacheMethods, makeCacheKey, normalizeHeaders, parseCacheControlHeader } = __nccwpck_require__(630) -const { AbortError } = __nccwpck_require__(4928) +// Extracted from node/lib/internal/fixed_queue.js -/** - * @param {(string | RegExp)[] | undefined} origins - * @param {string} name - */ -function assertCacheOrigins (origins, name) { - if (origins === undefined) return - if (!Array.isArray(origins)) { - throw new TypeError(`expected ${name} to be an array or undefined, got ${typeof origins}`) - } - for (let i = 0; i < origins.length; i++) { - const origin = origins[i] - if (typeof origin !== 'string' && !(origin instanceof RegExp)) { - throw new TypeError(`expected ${name}[${i}] to be a string or RegExp, got ${typeof origin}`) - } - } -} +// Currently optimal queue size, tested on V8 6.0 - 6.6. Must be power of two. +const kSize = 2048 +const kMask = kSize - 1 -const nop = () => {} +// The FixedQueue is implemented as a singly-linked list of fixed-size +// circular buffers. It looks something like this: +// +// head tail +// | | +// v v +// +-----------+ <-----\ +-----------+ <------\ +-----------+ +// | [null] | \----- | next | \------- | next | +// +-----------+ +-----------+ +-----------+ +// | item | <-- bottom | item | <-- bottom | undefined | +// | item | | item | | undefined | +// | item | | item | | undefined | +// | item | | item | | undefined | +// | item | | item | bottom --> | item | +// | item | | item | | item | +// | ... | | ... | | ... | +// | item | | item | | item | +// | item | | item | | item | +// | undefined | <-- top | item | | item | +// | undefined | | item | | item | +// | undefined | | undefined | <-- top top --> | undefined | +// +-----------+ +-----------+ +-----------+ +// +// Or, if there is only one circular buffer, it looks something +// like either of these: +// +// head tail head tail +// | | | | +// v v v v +// +-----------+ +-----------+ +// | [null] | | [null] | +// +-----------+ +-----------+ +// | undefined | | item | +// | undefined | | item | +// | item | <-- bottom top --> | undefined | +// | item | | undefined | +// | undefined | <-- top bottom --> | item | +// | undefined | | item | +// +-----------+ +-----------+ +// +// Adding a value means moving `top` forward by one, removing means +// moving `bottom` forward by one. After reaching the end, the queue +// wraps around. +// +// When `top === bottom` the current queue is empty and when +// `top + 1 === bottom` it's full. This wastes a single space of storage +// but allows much quicker checks. /** - * @typedef {(options: import('../../types/dispatcher.d.ts').default.DispatchOptions, handler: import('../../types/dispatcher.d.ts').default.DispatchHandler) => void} DispatchFn + * @type {FixedCircularBuffer} + * @template T */ +class FixedCircularBuffer { + /** @type {number} */ + bottom = 0 + /** @type {number} */ + top = 0 + /** @type {Array} */ + list = new Array(kSize).fill(undefined) + /** @type {T|null} */ + next = null -/** - * @param {import('../../types/cache-interceptor.d.ts').default.GetResult} result - * @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives | undefined} cacheControlDirectives - * @param {import('../../types/dispatcher.d.ts').default.RequestOptions} opts - * @returns {boolean} - */ -function needsRevalidation (result, cacheControlDirectives, { headers = {} }) { - // Always revalidate requests with the no-cache request directive. - if (cacheControlDirectives?.['no-cache']) { - return true + /** @returns {boolean} */ + isEmpty () { + return this.top === this.bottom } - // Always revalidate requests with unqualified no-cache response directive. - if (result.cacheControlDirectives?.['no-cache'] && !Array.isArray(result.cacheControlDirectives['no-cache'])) { - return true + /** @returns {boolean} */ + isFull () { + return ((this.top + 1) & kMask) === this.bottom } - // Always revalidate requests with conditional headers. - if (headers['if-modified-since'] || headers['if-none-match']) { - return true + /** + * @param {T} data + * @returns {void} + */ + push (data) { + this.list[this.top] = data + this.top = (this.top + 1) & kMask } - return false + /** @returns {T|null} */ + shift () { + const nextItem = this.list[this.bottom] + if (nextItem === undefined) { return null } + this.list[this.bottom] = undefined + this.bottom = (this.bottom + 1) & kMask + return nextItem + } } /** - * @param {import('../../types/cache-interceptor.d.ts').default.GetResult} result - * @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives | undefined} cacheControlDirectives - * @returns {boolean} + * @template T */ -function isStale (result, cacheControlDirectives) { - const now = Date.now() - if (now > result.staleAt) { - // Response is stale - if (cacheControlDirectives?.['max-stale']) { - // There's a threshold where we can serve stale responses, let's see if - // we're in it - // https://www.rfc-editor.org/rfc/rfc9111.html#name-max-stale - const gracePeriod = result.staleAt + (cacheControlDirectives['max-stale'] * 1000) - return now > gracePeriod - } - - return true +module.exports = class FixedQueue { + constructor () { + /** @type {FixedCircularBuffer} */ + this.head = this.tail = new FixedCircularBuffer() } - if (cacheControlDirectives?.['min-fresh']) { - // https://www.rfc-editor.org/rfc/rfc9111.html#section-5.2.1.3 - - // At this point, staleAt is always > now - const timeLeftTillStale = result.staleAt - now - const threshold = cacheControlDirectives['min-fresh'] * 1000 + /** @returns {boolean} */ + isEmpty () { + return this.head.isEmpty() + } - return timeLeftTillStale <= threshold + /** @param {T} data */ + push (data) { + if (this.head.isFull()) { + // Head is full: Creates a new queue, sets the old queue's `.next` to it, + // and sets it as the new main queue. + this.head = this.head.next = new FixedCircularBuffer() + } + this.head.push(data) } - return false + /** @returns {T|null} */ + shift () { + const tail = this.tail + const next = tail.shift() + if (tail.isEmpty() && tail.next !== null) { + // If there is another queue, it forms the new tail. + this.tail = tail.next + tail.next = null + } + return next + } } -/** - * Check if we're within the stale-while-revalidate window for a stale response - * @param {import('../../types/cache-interceptor.d.ts').default.GetResult} result - * @returns {boolean} - */ -function withinStaleWhileRevalidateWindow (result) { - const staleWhileRevalidate = result.cacheControlDirectives?.['stale-while-revalidate'] - if (!staleWhileRevalidate) { - return false - } - const now = Date.now() - const staleWhileRevalidateExpiry = result.staleAt + (staleWhileRevalidate * 1000) - return now <= staleWhileRevalidateExpiry -} +/***/ }), -/** - * @param {DispatchFn} dispatch - * @param {import('../../types/cache-interceptor.d.ts').default.CacheHandlerOptions} globalOpts - * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} cacheKey - * @param {import('../../types/dispatcher.d.ts').default.DispatchHandler} handler - * @param {import('../../types/dispatcher.d.ts').default.RequestOptions} opts - * @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives | undefined} reqCacheControl - */ -function handleUncachedResponse ( - dispatch, - globalOpts, - cacheKey, - handler, - opts, - reqCacheControl -) { - if (reqCacheControl?.['only-if-cached']) { - let aborted = false - try { - if (typeof handler.onConnect === 'function') { - handler.onConnect(() => { - aborted = true - }) +/***/ 861: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - if (aborted) { - return - } - } - if (typeof handler.onHeaders === 'function') { - handler.onHeaders(504, [], nop, 'Gateway Timeout') - if (aborted) { - return - } - } - if (typeof handler.onComplete === 'function') { - handler.onComplete([]) - } - } catch (err) { - if (typeof handler.onError === 'function') { - handler.onError(err) - } +const { InvalidArgumentError } = __nccwpck_require__(5093) +const Client = __nccwpck_require__(1115) + +class H2CClient extends Client { + constructor (origin, clientOpts) { + if (typeof origin === 'string') { + origin = new URL(origin) } - return true - } + if (origin.protocol !== 'http:') { + throw new InvalidArgumentError( + 'h2c-client: Only h2c protocol is supported' + ) + } - return dispatch(opts, new CacheHandler(globalOpts, cacheKey, handler)) -} + const { connect, maxConcurrentStreams, pipelining, ...opts } = + clientOpts ?? {} + let defaultMaxConcurrentStreams = 100 + let defaultPipelining = 100 -/** - * @param {import('../../types/dispatcher.d.ts').default.DispatchHandler} handler - * @param {import('../../types/dispatcher.d.ts').default.RequestOptions} opts - * @param {import('../../types/cache-interceptor.d.ts').default.GetResult} result - * @param {number} age - * @param {any} context - * @param {boolean} isStale - */ -function sendCachedValue (handler, opts, result, age, context, isStale) { - // TODO (perf): Readable.from path can be optimized... - const stream = util.isStream(result.body) - ? result.body - : Readable.from(result.body ?? []) + if ( + maxConcurrentStreams != null && + Number.isInteger(maxConcurrentStreams) && + maxConcurrentStreams > 0 + ) { + defaultMaxConcurrentStreams = maxConcurrentStreams + } - assert(!stream.destroyed, 'stream should not be destroyed') - assert(!stream.readableDidRead, 'stream should not be readableDidRead') + if (pipelining != null && Number.isInteger(pipelining) && pipelining > 0) { + defaultPipelining = pipelining + } - const controller = { - resume () { - stream.resume() - }, - pause () { - stream.pause() - }, - get paused () { - return stream.isPaused() - }, - get aborted () { - return stream.destroyed - }, - get reason () { - return stream.errored - }, - abort (reason) { - stream.destroy(reason ?? new AbortError()) + if (defaultPipelining > defaultMaxConcurrentStreams) { + throw new InvalidArgumentError( + 'h2c-client: pipelining cannot be greater than maxConcurrentStreams' + ) } - } - stream - .on('error', function (err) { - if (!this.readableEnded) { - if (typeof handler.onResponseError === 'function') { - handler.onResponseError(controller, err) - } else { - throw err - } - } - }) - .on('close', function () { - if (!this.errored) { - handler.onResponseEnd?.(controller, {}) - } + super(origin, { + ...opts, + maxConcurrentStreams: defaultMaxConcurrentStreams, + pipelining: defaultPipelining, + allowH2: true, + useH2c: true }) - - handler.onRequestStart?.(controller, context) - - if (stream.destroyed) { - return } +} - // Add the age header - // https://www.rfc-editor.org/rfc/rfc9111.html#name-age - const headers = { ...result.headers, age: String(age) } - - if (isStale) { - // Add warning header - // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Warning - headers.warning = '110 - "response is stale"' - } +module.exports = H2CClient - handler.onResponseStart?.(controller, result.statusCode, headers, result.statusMessage) - if (opts.method === 'HEAD') { - stream.destroy() - } else { - stream.on('data', function (chunk) { - handler.onResponseData?.(controller, chunk) - }) - } -} +/***/ }), -/** - * @param {DispatchFn} dispatch - * @param {import('../../types/cache-interceptor.d.ts').default.CacheHandlerOptions} globalOpts - * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} cacheKey - * @param {import('../../types/dispatcher.d.ts').default.DispatchHandler} handler - * @param {import('../../types/dispatcher.d.ts').default.RequestOptions} opts - * @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives | undefined} reqCacheControl - * @param {import('../../types/cache-interceptor.d.ts').default.GetResult | undefined} result - */ -function handleResult ( - dispatch, - globalOpts, - cacheKey, - handler, - opts, - reqCacheControl, - result -) { - if (!result) { - return handleUncachedResponse(dispatch, globalOpts, cacheKey, handler, opts, reqCacheControl) - } +/***/ 7978: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - const now = Date.now() - if (now > result.deleteAt) { - // Response is expired, cache store shouldn't have given this to us - return dispatch(opts, new CacheHandler(globalOpts, cacheKey, handler)) - } - const age = Math.round((now - result.cachedAt) / 1000) - if (reqCacheControl?.['max-age'] && age >= reqCacheControl['max-age']) { - // Response is considered expired for this specific request - // https://www.rfc-editor.org/rfc/rfc9111.html#section-5.2.1.1 - return dispatch(opts, handler) - } - const stale = isStale(result, reqCacheControl) - const revalidate = needsRevalidation(result, reqCacheControl, opts) +const { PoolStats } = __nccwpck_require__(7044) +const DispatcherBase = __nccwpck_require__(6223) +const FixedQueue = __nccwpck_require__(1506) +const { kConnected, kSize, kRunning, kPending, kQueued, kBusy, kFree, kUrl, kClose, kDestroy, kDispatch } = __nccwpck_require__(8261) - // Check if the response is stale - if (stale || revalidate) { - if (util.isStream(opts.body) && util.bodyLength(opts.body) !== 0) { - // If body is a stream we can't revalidate... - // TODO (fix): This could be less strict... - return dispatch(opts, new CacheHandler(globalOpts, cacheKey, handler)) - } +const kClients = Symbol('clients') +const kNeedDrain = Symbol('needDrain') +const kQueue = Symbol('queue') +const kClosedResolve = Symbol('closed resolve') +const kOnDrain = Symbol('onDrain') +const kOnConnect = Symbol('onConnect') +const kOnDisconnect = Symbol('onDisconnect') +const kOnConnectionError = Symbol('onConnectionError') +const kGetDispatcher = Symbol('get dispatcher') +const kAddClient = Symbol('add client') +const kRemoveClient = Symbol('remove client') - // RFC 5861: If we're within stale-while-revalidate window, serve stale immediately - // and revalidate in background, unless immediate revalidation is necessary - if (!revalidate && withinStaleWhileRevalidateWindow(result)) { - // Serve stale response immediately - sendCachedValue(handler, opts, result, age, null, true) +class PoolBase extends DispatcherBase { + [kQueue] = new FixedQueue(); - // Start background revalidation (fire-and-forget) - queueMicrotask(() => { - let headers = { - ...opts.headers, - 'if-modified-since': new Date(result.cachedAt).toUTCString() - } + [kQueued] = 0; - if (result.etag) { - headers['if-none-match'] = result.etag - } + [kClients] = []; - if (result.vary) { - headers = { - ...headers, - ...result.vary - } - } + [kNeedDrain] = false; - // Background revalidation - update cache if we get new data - dispatch( - { - ...opts, - headers - }, - new CacheHandler(globalOpts, cacheKey, { - // Silent handler that just updates the cache - onRequestStart () {}, - onRequestUpgrade () {}, - onResponseStart () {}, - onResponseData () {}, - onResponseEnd () {}, - onResponseError () {} - }) - ) - }) + [kOnDrain] (client, origin, targets) { + const queue = this[kQueue] - return true - } + let needDrain = false - let withinStaleIfErrorThreshold = false - const staleIfErrorExpiry = result.cacheControlDirectives['stale-if-error'] ?? reqCacheControl?.['stale-if-error'] - if (staleIfErrorExpiry) { - withinStaleIfErrorThreshold = now < (result.staleAt + (staleIfErrorExpiry * 1000)) + while (!needDrain) { + const item = queue.shift() + if (!item) { + break + } + this[kQueued]-- + needDrain = !client.dispatch(item.opts, item.handler) } - let headers = { - ...opts.headers, - 'if-modified-since': new Date(result.cachedAt).toUTCString() - } + client[kNeedDrain] = needDrain - if (result.etag) { - headers['if-none-match'] = result.etag + if (!needDrain && this[kNeedDrain]) { + this[kNeedDrain] = false + this.emit('drain', origin, [this, ...targets]) } - if (result.vary) { - headers = { - ...headers, - ...result.vary + if (this[kClosedResolve] && queue.isEmpty()) { + const closeAll = new Array(this[kClients].length) + for (let i = 0; i < this[kClients].length; i++) { + closeAll[i] = this[kClients][i].close() } + return Promise.all(closeAll) + .then(this[kClosedResolve]) } - - // We need to revalidate the response - return dispatch( - { - ...opts, - headers - }, - new CacheRevalidationHandler( - (success, context) => { - if (success) { - // TODO: successful revalidation should be considered fresh (not give stale warning). - sendCachedValue(handler, opts, result, age, context, stale) - } else if (util.isStream(result.body)) { - result.body.on('error', nop).destroy() - } - }, - new CacheHandler(globalOpts, cacheKey, handler), - withinStaleIfErrorThreshold - ) - ) - } - - // Dump request body. - if (util.isStream(opts.body)) { - opts.body.on('error', nop).destroy() } - sendCachedValue(handler, opts, result, age, null, false) -} + [kOnConnect] = (origin, targets) => { + this.emit('connect', origin, [this, ...targets]) + }; -/** - * @param {import('../../types/cache-interceptor.d.ts').default.CacheOptions} [opts] - * @returns {import('../../types/dispatcher.d.ts').default.DispatcherComposeInterceptor} - */ -module.exports = (opts = {}) => { - const { - store = new MemoryCacheStore(), - methods = ['GET'], - cacheByDefault = undefined, - type = 'shared', - origins = undefined - } = opts + [kOnDisconnect] = (origin, targets, err) => { + this.emit('disconnect', origin, [this, ...targets], err) + }; - if (typeof opts !== 'object' || opts === null) { - throw new TypeError(`expected type of opts to be an Object, got ${opts === null ? 'null' : typeof opts}`) + [kOnConnectionError] = (origin, targets, err) => { + this.emit('connectionError', origin, [this, ...targets], err) } - assertCacheStore(store, 'opts.store') - assertCacheMethods(methods, 'opts.methods') - assertCacheOrigins(origins, 'opts.origins') - - if (typeof cacheByDefault !== 'undefined' && typeof cacheByDefault !== 'number') { - throw new TypeError(`expected opts.cacheByDefault to be number or undefined, got ${typeof cacheByDefault}`) + get [kBusy] () { + return this[kNeedDrain] } - if (typeof type !== 'undefined' && type !== 'shared' && type !== 'private') { - throw new TypeError(`expected opts.type to be shared, private, or undefined, got ${typeof type}`) + get [kConnected] () { + let ret = 0 + for (const { [kConnected]: connected } of this[kClients]) { + ret += connected + } + return ret } - const globalOpts = { - store, - methods, - cacheByDefault, - type + get [kFree] () { + let ret = 0 + for (const { [kConnected]: connected, [kNeedDrain]: needDrain } of this[kClients]) { + ret += connected && !needDrain + } + return ret } - const safeMethodsToNotCache = util.safeHTTPMethods.filter(method => methods.includes(method) === false) + get [kPending] () { + let ret = this[kQueued] + for (const { [kPending]: pending } of this[kClients]) { + ret += pending + } + return ret + } - return dispatch => { - return (opts, handler) => { - if (!opts.origin || safeMethodsToNotCache.includes(opts.method)) { - // Not a method we want to cache or we don't have the origin, skip - return dispatch(opts, handler) - } + get [kRunning] () { + let ret = 0 + for (const { [kRunning]: running } of this[kClients]) { + ret += running + } + return ret + } - // Check if origin is in whitelist - if (origins !== undefined) { - const requestOrigin = opts.origin.toString().toLowerCase() - let isAllowed = false + get [kSize] () { + let ret = this[kQueued] + for (const { [kSize]: size } of this[kClients]) { + ret += size + } + return ret + } - for (let i = 0; i < origins.length; i++) { - const allowed = origins[i] - if (typeof allowed === 'string') { - if (allowed.toLowerCase() === requestOrigin) { - isAllowed = true - break - } - } else if (allowed.test(requestOrigin)) { - isAllowed = true - break - } - } + get stats () { + return new PoolStats(this) + } - if (!isAllowed) { - return dispatch(opts, handler) - } + [kClose] () { + if (this[kQueue].isEmpty()) { + const closeAll = new Array(this[kClients].length) + for (let i = 0; i < this[kClients].length; i++) { + closeAll[i] = this[kClients][i].close() } + return Promise.all(closeAll) + } else { + return new Promise((resolve) => { + this[kClosedResolve] = resolve + }) + } + } - opts = { - ...opts, - headers: normalizeHeaders(opts) + [kDestroy] (err) { + while (true) { + const item = this[kQueue].shift() + if (!item) { + break } + item.handler.onError(err) + } - const reqCacheControl = opts.headers?.['cache-control'] - ? parseCacheControlHeader(opts.headers['cache-control']) - : undefined + const destroyAll = new Array(this[kClients].length) + for (let i = 0; i < this[kClients].length; i++) { + destroyAll[i] = this[kClients][i].destroy(err) + } + return Promise.all(destroyAll) + } - if (reqCacheControl?.['no-store']) { - return dispatch(opts, handler) - } + [kDispatch] (opts, handler) { + const dispatcher = this[kGetDispatcher]() - /** - * @type {import('../../types/cache-interceptor.d.ts').default.CacheKey} - */ - const cacheKey = makeCacheKey(opts) - const result = store.get(cacheKey) - - if (result && typeof result.then === 'function') { - return result - .then(result => handleResult(dispatch, - globalOpts, - cacheKey, - handler, - opts, - reqCacheControl, - result - )) - } else { - return handleResult( - dispatch, - globalOpts, - cacheKey, - handler, - opts, - reqCacheControl, - result - ) - } + if (!dispatcher) { + this[kNeedDrain] = true + this[kQueue].push({ opts, handler }) + this[kQueued]++ + } else if (!dispatcher.dispatch(opts, handler)) { + dispatcher[kNeedDrain] = true + this[kNeedDrain] = !this[kGetDispatcher]() } - } -} + return !this[kNeedDrain] + } -/***/ }), + [kAddClient] (client) { + client + .on('drain', this[kOnDrain].bind(this, client)) + .on('connect', this[kOnConnect]) + .on('disconnect', this[kOnDisconnect]) + .on('connectionError', this[kOnConnectionError]) -/***/ 4100: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + this[kClients].push(client) -"use strict"; + if (this[kNeedDrain]) { + queueMicrotask(() => { + if (this[kNeedDrain]) { + this[kOnDrain](client, client[kUrl], [client, this]) + } + }) + } + return this + } -const { createInflate, createGunzip, createBrotliDecompress, createZstdDecompress } = __nccwpck_require__(8522) -const { pipeline } = __nccwpck_require__(7075) -const DecoratorHandler = __nccwpck_require__(5156) -const { runtimeFeatures } = __nccwpck_require__(1422) + [kRemoveClient] (client) { + client.close(() => { + const idx = this[kClients].indexOf(client) + if (idx !== -1) { + this[kClients].splice(idx, 1) + } + }) -/** @typedef {import('node:stream').Transform} Transform */ -/** @typedef {import('node:stream').Transform} Controller */ -/** @typedef {Transform&import('node:zlib').Zlib} DecompressorStream */ + this[kNeedDrain] = this[kClients].some(dispatcher => ( + !dispatcher[kNeedDrain] && + dispatcher.closed !== true && + dispatcher.destroyed !== true + )) + } +} -/** @type {Record DecompressorStream>} */ -const supportedEncodings = { - gzip: createGunzip, - 'x-gzip': createGunzip, - br: createBrotliDecompress, - deflate: createInflate, - compress: createInflate, - 'x-compress': createInflate, - ...(runtimeFeatures.has('zstd') ? { zstd: createZstdDecompress } : {}) +module.exports = { + PoolBase, + kClients, + kNeedDrain, + kAddClient, + kRemoveClient, + kGetDispatcher } -const defaultSkipStatusCodes = /** @type {const} */ ([204, 304]) -let warningEmitted = /** @type {boolean} */ (false) +/***/ }), -/** - * @typedef {Object} DecompressHandlerOptions - * @property {number[]|Readonly} [skipStatusCodes=[204, 304]] - List of status codes to skip decompression for - * @property {boolean} [skipErrorResponses] - Whether to skip decompression for error responses (status codes >= 400) - */ +/***/ 8034: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -class DecompressHandler extends DecoratorHandler { - /** @type {Transform[]} */ - #decompressors = [] - /** @type {NodeJS.WritableStream&NodeJS.ReadableStream|null} */ - #pipelineStream - /** @type {Readonly} */ - #skipStatusCodes - /** @type {boolean} */ - #skipErrorResponses - constructor (handler, { skipStatusCodes = defaultSkipStatusCodes, skipErrorResponses = true } = {}) { - super(handler) - this.#skipStatusCodes = skipStatusCodes - this.#skipErrorResponses = skipErrorResponses - } - /** - * Determines if decompression should be skipped based on encoding and status code - * @param {string} contentEncoding - Content-Encoding header value - * @param {number} statusCode - HTTP status code of the response - * @returns {boolean} - True if decompression should be skipped - */ - #shouldSkipDecompression (contentEncoding, statusCode) { - if (!contentEncoding || statusCode < 200) return true - if (this.#skipStatusCodes.includes(statusCode)) return true - if (this.#skipErrorResponses && statusCode >= 400) return true - return false - } +const { + PoolBase, + kClients, + kNeedDrain, + kAddClient, + kGetDispatcher, + kRemoveClient +} = __nccwpck_require__(7978) +const Client = __nccwpck_require__(1115) +const { + InvalidArgumentError +} = __nccwpck_require__(5093) +const util = __nccwpck_require__(2550) +const { kUrl } = __nccwpck_require__(8261) +const buildConnector = __nccwpck_require__(1430) - /** - * Creates a chain of decompressors for multiple content encodings - * - * @param {string} encodings - Comma-separated list of content encodings - * @returns {Array} - Array of decompressor streams - * @throws {Error} - If the number of content-encodings exceeds the maximum allowed - */ - #createDecompressionChain (encodings) { - const parts = encodings.split(',') +const kOptions = Symbol('options') +const kConnections = Symbol('connections') +const kFactory = Symbol('factory') - // Limit the number of content-encodings to prevent resource exhaustion. - // CVE fix similar to urllib3 (GHSA-gm62-xv2j-4w53) and curl (CVE-2022-32206). - const maxContentEncodings = 5 - if (parts.length > maxContentEncodings) { - throw new Error(`too many content-encodings in response: ${parts.length}, maximum allowed is ${maxContentEncodings}`) - } +function defaultFactory (origin, opts) { + return new Client(origin, opts) +} - /** @type {DecompressorStream[]} */ - const decompressors = [] +class Pool extends PoolBase { + constructor (origin, { + connections, + factory = defaultFactory, + connect, + connectTimeout, + tls, + maxCachedSessions, + socketPath, + autoSelectFamily, + autoSelectFamilyAttemptTimeout, + allowH2, + clientTtl, + ...options + } = {}) { + if (connections != null && (!Number.isFinite(connections) || connections < 0)) { + throw new InvalidArgumentError('invalid connections') + } - for (let i = parts.length - 1; i >= 0; i--) { - const encoding = parts[i].trim() - if (!encoding) continue + if (typeof factory !== 'function') { + throw new InvalidArgumentError('factory must be a function.') + } - if (!supportedEncodings[encoding]) { - decompressors.length = 0 // Clear if unsupported encoding - return decompressors // Unsupported encoding - } + if (connect != null && typeof connect !== 'function' && typeof connect !== 'object') { + throw new InvalidArgumentError('connect must be a function or an object') + } - decompressors.push(supportedEncodings[encoding]()) + if (typeof connect !== 'function') { + connect = buildConnector({ + ...tls, + maxCachedSessions, + allowH2, + socketPath, + timeout: connectTimeout, + ...(typeof autoSelectFamily === 'boolean' ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : undefined), + ...connect + }) } - return decompressors - } + super() - /** - * Sets up event handlers for a decompressor stream using readable events - * @param {DecompressorStream} decompressor - The decompressor stream - * @param {Controller} controller - The controller to coordinate with - * @returns {void} - */ - #setupDecompressorEvents (decompressor, controller) { - decompressor.on('readable', () => { - let chunk - while ((chunk = decompressor.read()) !== null) { - const result = super.onResponseData(controller, chunk) - if (result === false) { - break + this[kConnections] = connections || null + this[kUrl] = util.parseOrigin(origin) + this[kOptions] = { ...util.deepClone(options), connect, allowH2, clientTtl } + this[kOptions].interceptors = options.interceptors + ? { ...options.interceptors } + : undefined + this[kFactory] = factory + + this.on('connect', (origin, targets) => { + if (clientTtl != null && clientTtl > 0) { + for (const target of targets) { + Object.assign(target, { ttl: Date.now() }) } } }) - decompressor.on('error', (error) => { - super.onResponseError(controller, error) - }) - } - - /** - * Sets up event handling for a single decompressor - * @param {Controller} controller - The controller to handle events - * @returns {void} - */ - #setupSingleDecompressor (controller) { - const decompressor = this.#decompressors[0] - this.#setupDecompressorEvents(decompressor, controller) - - decompressor.on('end', () => { - super.onResponseEnd(controller, {}) + this.on('connectionError', (origin, targets, error) => { + // If a connection error occurs, we remove the client from the pool, + // and emit a connectionError event. They will not be re-used. + // Fixes https://github.com/nodejs/undici/issues/3895 + for (const target of targets) { + // Do not use kRemoveClient here, as it will close the client, + // but the client cannot be closed in this state. + const idx = this[kClients].indexOf(target) + if (idx !== -1) { + this[kClients].splice(idx, 1) + } + } }) } - /** - * Sets up event handling for multiple chained decompressors using pipeline - * @param {Controller} controller - The controller to handle events - * @returns {void} - */ - #setupMultipleDecompressors (controller) { - const lastDecompressor = this.#decompressors[this.#decompressors.length - 1] - this.#setupDecompressorEvents(lastDecompressor, controller) - - this.#pipelineStream = pipeline(this.#decompressors, (err) => { - if (err) { - super.onResponseError(controller, err) - return + [kGetDispatcher] () { + const clientTtlOption = this[kOptions].clientTtl + for (const client of this[kClients]) { + // check ttl of client and if it's stale, remove it from the pool + if (clientTtlOption != null && clientTtlOption > 0 && client.ttl && ((Date.now() - client.ttl) > clientTtlOption)) { + this[kRemoveClient](client) + } else if (!client[kNeedDrain]) { + return client } - super.onResponseEnd(controller, {}) - }) - } + } - /** - * Cleans up decompressor references to prevent memory leaks - * @returns {void} - */ - #cleanupDecompressors () { - this.#decompressors.length = 0 - this.#pipelineStream = null + if (!this[kConnections] || this[kClients].length < this[kConnections]) { + const dispatcher = this[kFactory](this[kUrl], this[kOptions]) + this[kAddClient](dispatcher) + return dispatcher + } } +} - /** - * @param {Controller} controller - * @param {number} statusCode - * @param {Record} headers - * @param {string} statusMessage - * @returns {void} - */ - onResponseStart (controller, statusCode, headers, statusMessage) { - const contentEncoding = headers['content-encoding'] - - // If content encoding is not supported or status code is in skip list - if (this.#shouldSkipDecompression(contentEncoding, statusCode)) { - return super.onResponseStart(controller, statusCode, headers, statusMessage) - } +module.exports = Pool - const decompressors = this.#createDecompressionChain(contentEncoding.toLowerCase()) - if (decompressors.length === 0) { - this.#cleanupDecompressors() - return super.onResponseStart(controller, statusCode, headers, statusMessage) - } +/***/ }), - this.#decompressors = decompressors +/***/ 2050: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - // Remove compression headers since we're decompressing - const { 'content-encoding': _, 'content-length': __, ...newHeaders } = headers - if (this.#decompressors.length === 1) { - this.#setupSingleDecompressor(controller) - } else { - this.#setupMultipleDecompressors(controller) - } - super.onResponseStart(controller, statusCode, newHeaders, statusMessage) - } +const { kProxy, kClose, kDestroy, kDispatch } = __nccwpck_require__(8261) +const Agent = __nccwpck_require__(9959) +const Pool = __nccwpck_require__(8034) +const DispatcherBase = __nccwpck_require__(6223) +const { InvalidArgumentError, RequestAbortedError, SecureProxyConnectionError } = __nccwpck_require__(5093) +const buildConnector = __nccwpck_require__(1430) +const Client = __nccwpck_require__(1115) +const { channels } = __nccwpck_require__(2248) - /** - * @param {Controller} controller - * @param {Buffer} chunk - * @returns {void} - */ - onResponseData (controller, chunk) { - if (this.#decompressors.length > 0) { - this.#decompressors[0].write(chunk) - return - } - super.onResponseData(controller, chunk) - } +const kAgent = Symbol('proxy agent') +const kClient = Symbol('proxy client') +const kProxyHeaders = Symbol('proxy headers') +const kRequestTls = Symbol('request tls settings') +const kProxyTls = Symbol('proxy tls settings') +const kConnectEndpoint = Symbol('connect endpoint function') +const kTunnelProxy = Symbol('tunnel proxy') - /** - * @param {Controller} controller - * @param {Record | undefined} trailers - * @returns {void} - */ - onResponseEnd (controller, trailers) { - if (this.#decompressors.length > 0) { - this.#decompressors[0].end() - this.#cleanupDecompressors() - return - } - super.onResponseEnd(controller, trailers) - } +function defaultProtocolPort (protocol) { + return protocol === 'https:' ? 443 : 80 +} - /** - * @param {Controller} controller - * @param {Error} err - * @returns {void} - */ - onResponseError (controller, err) { - if (this.#decompressors.length > 0) { - for (const decompressor of this.#decompressors) { - decompressor.destroy(err) - } - this.#cleanupDecompressors() - } - super.onResponseError(controller, err) - } +function defaultFactory (origin, opts) { + return new Pool(origin, opts) } -/** - * Creates a decompression interceptor for HTTP responses - * @param {DecompressHandlerOptions} [options] - Options for the interceptor - * @returns {Function} - Interceptor function - */ -function createDecompressInterceptor (options = {}) { - // Emit experimental warning only once - if (!warningEmitted) { - process.emitWarning( - 'DecompressInterceptor is experimental and subject to change', - 'ExperimentalWarning' - ) - warningEmitted = true - } +const noop = () => {} - return (dispatch) => { - return (opts, handler) => { - const decompressHandler = new DecompressHandler(handler, options) - return dispatch(opts, decompressHandler) - } +function defaultAgentFactory (origin, opts) { + if (opts.connections === 1) { + return new Client(origin, opts) } + return new Pool(origin, opts) } -module.exports = createDecompressInterceptor +class Http1ProxyWrapper extends DispatcherBase { + #client + constructor (proxyUrl, { headers = {}, connect, factory }) { + if (!proxyUrl) { + throw new InvalidArgumentError('Proxy URL is mandatory') + } -/***/ }), + super() -/***/ 675: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + this[kProxyHeaders] = headers + if (factory) { + this.#client = factory(proxyUrl, { connect }) + } else { + this.#client = new Client(proxyUrl, { connect }) + } + } -"use strict"; + [kDispatch] (opts, handler) { + const onHeaders = handler.onHeaders + handler.onHeaders = function (statusCode, data, resume) { + if (statusCode === 407) { + if (typeof handler.onError === 'function') { + handler.onError(new InvalidArgumentError('Proxy Authentication Required (407)')) + } + return + } + if (onHeaders) onHeaders.call(this, statusCode, data, resume) + } + // Rewrite request as an HTTP1 Proxy request, without tunneling. + const { + origin, + path = '/', + headers = {} + } = opts -const diagnosticsChannel = __nccwpck_require__(3053) -const util = __nccwpck_require__(983) -const DeduplicationHandler = __nccwpck_require__(2064) -const { normalizeHeaders, makeCacheKey, makeDeduplicationKey } = __nccwpck_require__(630) + opts.path = origin + path -const pendingRequestsChannel = diagnosticsChannel.channel('undici:request:pending-requests') + if (!('host' in headers) && !('Host' in headers)) { + const { host } = new URL(origin) + headers.host = host + } + opts.headers = { ...this[kProxyHeaders], ...headers } -/** - * @param {import('../../types/interceptors.d.ts').default.DeduplicateInterceptorOpts} [opts] - * @returns {import('../../types/dispatcher.d.ts').default.DispatcherComposeInterceptor} - */ -module.exports = (opts = {}) => { - const { - methods = ['GET'], - skipHeaderNames = [], - excludeHeaderNames = [] - } = opts + return this.#client[kDispatch](opts, handler) + } - if (typeof opts !== 'object' || opts === null) { - throw new TypeError(`expected type of opts to be an Object, got ${opts === null ? 'null' : typeof opts}`) + [kClose] () { + return this.#client.close() } - if (!Array.isArray(methods)) { - throw new TypeError(`expected opts.methods to be an array, got ${typeof methods}`) + [kDestroy] (err) { + return this.#client.destroy(err) } +} - for (const method of methods) { - if (!util.safeHTTPMethods.includes(method)) { - throw new TypeError(`expected opts.methods to only contain safe HTTP methods, got ${method}`) +class ProxyAgent extends DispatcherBase { + constructor (opts) { + if (!opts || (typeof opts === 'object' && !(opts instanceof URL) && !opts.uri)) { + throw new InvalidArgumentError('Proxy uri is mandatory') } - } - if (!Array.isArray(skipHeaderNames)) { - throw new TypeError(`expected opts.skipHeaderNames to be an array, got ${typeof skipHeaderNames}`) - } + const { clientFactory = defaultFactory } = opts + if (typeof clientFactory !== 'function') { + throw new InvalidArgumentError('Proxy opts.clientFactory must be a function.') + } - if (!Array.isArray(excludeHeaderNames)) { - throw new TypeError(`expected opts.excludeHeaderNames to be an array, got ${typeof excludeHeaderNames}`) - } + const { proxyTunnel = true } = opts - // Convert to lowercase Set for case-insensitive header matching - const skipHeaderNamesSet = new Set(skipHeaderNames.map(name => name.toLowerCase())) + super() - // Convert to lowercase Set for case-insensitive header exclusion from deduplication key - const excludeHeaderNamesSet = new Set(excludeHeaderNames.map(name => name.toLowerCase())) + const url = this.#getUrl(opts) + const { href, origin, port, protocol, username, password, hostname: proxyHostname } = url - const safeMethodsToNotDeduplicate = util.safeHTTPMethods.filter(method => methods.includes(method) === false) + this[kProxy] = { uri: href, protocol } + this[kRequestTls] = opts.requestTls + this[kProxyTls] = opts.proxyTls + this[kProxyHeaders] = opts.headers || {} + this[kTunnelProxy] = proxyTunnel - /** - * Map of pending requests for deduplication - * @type {Map} - */ - const pendingRequests = new Map() + if (opts.auth && opts.token) { + throw new InvalidArgumentError('opts.auth cannot be used in combination with opts.token') + } else if (opts.auth) { + /* @deprecated in favour of opts.token */ + this[kProxyHeaders]['proxy-authorization'] = `Basic ${opts.auth}` + } else if (opts.token) { + this[kProxyHeaders]['proxy-authorization'] = opts.token + } else if (username && password) { + this[kProxyHeaders]['proxy-authorization'] = `Basic ${Buffer.from(`${decodeURIComponent(username)}:${decodeURIComponent(password)}`).toString('base64')}` + } - return dispatch => { - return (opts, handler) => { - if (!opts.origin || safeMethodsToNotDeduplicate.includes(opts.method)) { - return dispatch(opts, handler) - } + const connect = buildConnector({ ...opts.proxyTls }) + this[kConnectEndpoint] = buildConnector({ ...opts.requestTls }) - opts = { - ...opts, - headers: normalizeHeaders(opts) + const agentFactory = opts.factory || defaultAgentFactory + const factory = (origin, options) => { + const { protocol } = new URL(origin) + if (!this[kTunnelProxy] && protocol === 'http:' && this[kProxy].protocol === 'http:') { + return new Http1ProxyWrapper(this[kProxy].uri, { + headers: this[kProxyHeaders], + connect, + factory: agentFactory + }) } + return agentFactory(origin, options) + } + this[kClient] = clientFactory(url, { connect }) + this[kAgent] = new Agent({ + ...opts, + factory, + connect: async (opts, callback) => { + let requestedPath = opts.host + if (!opts.port) { + requestedPath += `:${defaultProtocolPort(opts.protocol)}` + } + try { + const connectParams = { + origin, + port, + path: requestedPath, + signal: opts.signal, + headers: { + ...this[kProxyHeaders], + host: opts.host, + ...(opts.connections == null || opts.connections > 0 ? { 'proxy-connection': 'keep-alive' } : {}) + }, + servername: this[kProxyTls]?.servername || proxyHostname + } + const { socket, statusCode } = await this[kClient].connect(connectParams) + if (statusCode !== 200) { + socket.on('error', noop).destroy() + callback(new RequestAbortedError(`Proxy response (${statusCode}) !== 200 when HTTP Tunneling`)) + return + } - // Skip deduplication if request contains any of the specified headers - if (skipHeaderNamesSet.size > 0) { - for (const headerName of Object.keys(opts.headers)) { - if (skipHeaderNamesSet.has(headerName.toLowerCase())) { - return dispatch(opts, handler) + if (channels.proxyConnected.hasSubscribers) { + channels.proxyConnected.publish({ + socket, + connectParams + }) + } + + if (opts.protocol !== 'https:') { + callback(null, socket) + return + } + let servername + if (this[kRequestTls]) { + servername = this[kRequestTls].servername + } else { + servername = opts.servername + } + this[kConnectEndpoint]({ ...opts, servername, httpSocket: socket }, callback) + } catch (err) { + if (err.code === 'ERR_TLS_CERT_ALTNAME_INVALID') { + // Throw a custom error to avoid loop in client.js#connect + callback(new SecureProxyConnectionError(err)) + } else { + callback(err) } } } + }) + } - const cacheKey = makeCacheKey(opts) - const dedupeKey = makeDeduplicationKey(cacheKey, excludeHeaderNamesSet) + dispatch (opts, handler) { + const headers = buildHeaders(opts.headers) + throwIfProxyAuthIsSent(headers) - // Check if there's already a pending request for this key - const pendingHandler = pendingRequests.get(dedupeKey) - if (pendingHandler) { - // Add this handler to the waiting list - pendingHandler.addWaitingHandler(handler) - return true - } + if (headers && !('host' in headers) && !('Host' in headers)) { + const { host } = new URL(opts.origin) + headers.host = host + } - // Create a new deduplication handler - const deduplicationHandler = new DeduplicationHandler( - handler, - () => { - // Clean up when request completes - pendingRequests.delete(dedupeKey) - if (pendingRequestsChannel.hasSubscribers) { - pendingRequestsChannel.publish({ size: pendingRequests.size, key: dedupeKey, type: 'removed' }) - } - } - ) + return this[kAgent].dispatch( + { + ...opts, + headers + }, + handler + ) + } - // Register the pending request - pendingRequests.set(dedupeKey, deduplicationHandler) - if (pendingRequestsChannel.hasSubscribers) { - pendingRequestsChannel.publish({ size: pendingRequests.size, key: dedupeKey, type: 'added' }) - } + /** + * @param {import('../../types/proxy-agent').ProxyAgent.Options | string | URL} opts + * @returns {URL} + */ + #getUrl (opts) { + if (typeof opts === 'string') { + return new URL(opts) + } else if (opts instanceof URL) { + return opts + } else { + return new URL(opts.uri) + } + } - return dispatch(opts, deduplicationHandler) + [kClose] () { + return Promise.all([ + this[kAgent].close(), + this[kClient].close() + ]) + } + + [kDestroy] () { + return Promise.all([ + this[kAgent].destroy(), + this[kClient].destroy() + ]) + } +} + +/** + * @param {string[] | Record} headers + * @returns {Record} + */ +function buildHeaders (headers) { + // When using undici.fetch, the headers list is stored + // as an array. + if (Array.isArray(headers)) { + /** @type {Record} */ + const headersPair = {} + + for (let i = 0; i < headers.length; i += 2) { + headersPair[headers[i]] = headers[i + 1] } + + return headersPair + } + + return headers +} + +/** + * @param {Record} headers + * + * Previous versions of ProxyAgent suggests the Proxy-Authorization in request headers + * Nevertheless, it was changed and to avoid a security vulnerability by end users + * this check was created. + * It should be removed in the next major version for performance reasons + */ +function throwIfProxyAuthIsSent (headers) { + const existProxyAuth = headers && Object.keys(headers) + .find((key) => key.toLowerCase() === 'proxy-authorization') + if (existProxyAuth) { + throw new InvalidArgumentError('Proxy-Authorization should be sent in ProxyAgent constructor') } } +module.exports = ProxyAgent + /***/ }), -/***/ 4020: +/***/ 5908: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; - -const { isIP } = __nccwpck_require__(7030) -const { lookup } = __nccwpck_require__(610) -const DecoratorHandler = __nccwpck_require__(5156) -const { InvalidArgumentError, InformationalError } = __nccwpck_require__(4928) -const maxInt = Math.pow(2, 31) - 1 - -class DNSStorage { - #maxItems = 0 - #records = new Map() - constructor (opts) { - this.#maxItems = opts.maxItems - } - get size () { - return this.#records.size - } +const Dispatcher = __nccwpck_require__(5085) +const RetryHandler = __nccwpck_require__(1557) - get (hostname) { - return this.#records.get(hostname) ?? null +class RetryAgent extends Dispatcher { + #agent = null + #options = null + constructor (agent, options = {}) { + super(options) + this.#agent = agent + this.#options = options } - set (hostname, records) { - this.#records.set(hostname, records) + dispatch (opts, handler) { + const retry = new RetryHandler({ + ...opts, + retryOptions: this.#options + }, { + dispatch: this.#agent.dispatch.bind(this.#agent), + handler + }) + return this.#agent.dispatch(opts, retry) } - delete (hostname) { - this.#records.delete(hostname) + close () { + return this.#agent.close() } - // Delegate to storage decide can we do more lookups or not - full () { - return this.size >= this.#maxItems + destroy () { + return this.#agent.destroy() } } -class DNSInstance { - #maxTTL = 0 - #maxItems = 0 - dualStack = true - affinity = null - lookup = null - pick = null - storage = null +module.exports = RetryAgent - constructor (opts) { - this.#maxTTL = opts.maxTTL - this.#maxItems = opts.maxItems - this.dualStack = opts.dualStack - this.affinity = opts.affinity - this.lookup = opts.lookup ?? this.#defaultLookup - this.pick = opts.pick ?? this.#defaultPick - this.storage = opts.storage ?? new DNSStorage(opts) - } - runLookup (origin, opts, cb) { - const ips = this.storage.get(origin.hostname) +/***/ }), - // If full, we just return the origin - if (ips == null && this.storage.full()) { - cb(null, origin) - return - } +/***/ 4626: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - const newOpts = { - affinity: this.affinity, - dualStack: this.dualStack, - lookup: this.lookup, - pick: this.pick, - ...opts.dns, - maxTTL: this.#maxTTL, - maxItems: this.#maxItems - } - // If no IPs we lookup - if (ips == null) { - this.lookup(origin, newOpts, (err, addresses) => { - if (err || addresses == null || addresses.length === 0) { - cb(err ?? new InformationalError('No DNS entries found')) - return - } - this.setRecords(origin, addresses) - const records = this.storage.get(origin.hostname) +const { + PoolBase, + kClients, + kNeedDrain, + kAddClient, + kGetDispatcher, + kRemoveClient +} = __nccwpck_require__(7978) +const Client = __nccwpck_require__(1115) +const { + InvalidArgumentError +} = __nccwpck_require__(5093) +const util = __nccwpck_require__(2550) +const { kUrl } = __nccwpck_require__(8261) +const buildConnector = __nccwpck_require__(1430) - const ip = this.pick( - origin, - records, - newOpts.affinity - ) +const kOptions = Symbol('options') +const kConnections = Symbol('connections') +const kFactory = Symbol('factory') +const kIndex = Symbol('index') - let port - if (typeof ip.port === 'number') { - port = `:${ip.port}` - } else if (origin.port !== '') { - port = `:${origin.port}` - } else { - port = '' - } +function defaultFactory (origin, opts) { + return new Client(origin, opts) +} - cb( - null, - new URL(`${origin.protocol}//${ - ip.family === 6 ? `[${ip.address}]` : ip.address - }${port}`) - ) - }) - } else { - // If there's IPs we pick - const ip = this.pick( - origin, - ips, - newOpts.affinity - ) +class RoundRobinPool extends PoolBase { + constructor (origin, { + connections, + factory = defaultFactory, + connect, + connectTimeout, + tls, + maxCachedSessions, + socketPath, + autoSelectFamily, + autoSelectFamilyAttemptTimeout, + allowH2, + clientTtl, + ...options + } = {}) { + if (connections != null && (!Number.isFinite(connections) || connections < 0)) { + throw new InvalidArgumentError('invalid connections') + } - // If no IPs we lookup - deleting old records - if (ip == null) { - this.storage.delete(origin.hostname) - this.runLookup(origin, opts, cb) - return - } + if (typeof factory !== 'function') { + throw new InvalidArgumentError('factory must be a function.') + } - let port - if (typeof ip.port === 'number') { - port = `:${ip.port}` - } else if (origin.port !== '') { - port = `:${origin.port}` - } else { - port = '' - } + if (connect != null && typeof connect !== 'function' && typeof connect !== 'object') { + throw new InvalidArgumentError('connect must be a function or an object') + } - cb( - null, - new URL(`${origin.protocol}//${ - ip.family === 6 ? `[${ip.address}]` : ip.address - }${port}`) - ) + if (typeof connect !== 'function') { + connect = buildConnector({ + ...tls, + maxCachedSessions, + allowH2, + socketPath, + timeout: connectTimeout, + ...(typeof autoSelectFamily === 'boolean' ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : undefined), + ...connect + }) } - } - #defaultLookup (origin, opts, cb) { - lookup( - origin.hostname, - { - all: true, - family: this.dualStack === false ? this.affinity : 0, - order: 'ipv4first' - }, - (err, addresses) => { - if (err) { - return cb(err) - } + super() - const results = new Map() + this[kConnections] = connections || null + this[kUrl] = util.parseOrigin(origin) + this[kOptions] = { ...util.deepClone(options), connect, allowH2, clientTtl } + this[kOptions].interceptors = options.interceptors + ? { ...options.interceptors } + : undefined + this[kFactory] = factory + this[kIndex] = -1 - for (const addr of addresses) { - // On linux we found duplicates, we attempt to remove them with - // the latest record - results.set(`${addr.address}:${addr.family}`, addr) + this.on('connect', (origin, targets) => { + if (clientTtl != null && clientTtl > 0) { + for (const target of targets) { + Object.assign(target, { ttl: Date.now() }) } - - cb(null, results.values()) } - ) - } - - #defaultPick (origin, hostnameRecords, affinity) { - let ip = null - const { records, offset } = hostnameRecords + }) - let family - if (this.dualStack) { - if (affinity == null) { - // Balance between ip families - if (offset == null || offset === maxInt) { - hostnameRecords.offset = 0 - affinity = 4 - } else { - hostnameRecords.offset++ - affinity = (hostnameRecords.offset & 1) === 1 ? 6 : 4 + this.on('connectionError', (origin, targets, error) => { + for (const target of targets) { + const idx = this[kClients].indexOf(target) + if (idx !== -1) { + this[kClients].splice(idx, 1) } } + }) + } - if (records[affinity] != null && records[affinity].ips.length > 0) { - family = records[affinity] - } else { - family = records[affinity === 4 ? 6 : 4] - } - } else { - family = records[affinity] - } + [kGetDispatcher] () { + const clientTtlOption = this[kOptions].clientTtl + const clientsLength = this[kClients].length - // If no IPs we return null - if (family == null || family.ips.length === 0) { - return ip + // If we have no clients yet, create one + if (clientsLength === 0) { + const dispatcher = this[kFactory](this[kUrl], this[kOptions]) + this[kAddClient](dispatcher) + return dispatcher } - if (family.offset == null || family.offset === maxInt) { - family.offset = 0 - } else { - family.offset++ - } + // Round-robin through existing clients + let checked = 0 + while (checked < clientsLength) { + this[kIndex] = (this[kIndex] + 1) % clientsLength + const client = this[kClients][this[kIndex]] - const position = family.offset % family.ips.length - ip = family.ips[position] ?? null + // Check if client is stale (TTL expired) + if (clientTtlOption != null && clientTtlOption > 0 && client.ttl && ((Date.now() - client.ttl) > clientTtlOption)) { + this[kRemoveClient](client) + checked++ + continue + } - if (ip == null) { - return ip - } + // Return client if it's not draining + if (!client[kNeedDrain]) { + return client + } - if (Date.now() - ip.timestamp > ip.ttl) { // record TTL is already in ms - // We delete expired records - // It is possible that they have different TTL, so we manage them individually - family.ips.splice(position, 1) - return this.pick(origin, hostnameRecords, affinity) + checked++ } - return ip + // All clients are busy, create a new one if we haven't reached the limit + if (!this[kConnections] || clientsLength < this[kConnections]) { + const dispatcher = this[kFactory](this[kUrl], this[kOptions]) + this[kAddClient](dispatcher) + return dispatcher + } } +} - pickFamily (origin, ipFamily) { - const records = this.storage.get(origin.hostname)?.records - if (!records) { - return null - } +module.exports = RoundRobinPool - const family = records[ipFamily] - if (!family) { - return null - } - if (family.offset == null || family.offset === maxInt) { - family.offset = 0 - } else { - family.offset++ - } +/***/ }), - const position = family.offset % family.ips.length - const ip = family.ips[position] ?? null - if (ip == null) { - return ip - } +/***/ 6546: +/***/ ((module) => { - if (Date.now() - ip.timestamp > ip.ttl) { // record TTL is already in ms - // We delete expired records - // It is possible that they have different TTL, so we manage them individually - family.ips.splice(position, 1) - } - return ip - } - setRecords (origin, addresses) { - const timestamp = Date.now() - const records = { records: { 4: null, 6: null } } - let minTTL = this.#maxTTL - for (const record of addresses) { - record.timestamp = timestamp - if (typeof record.ttl === 'number') { - // The record TTL is expected to be in ms - record.ttl = Math.min(record.ttl, this.#maxTTL) - minTTL = Math.min(minTTL, record.ttl) - } else { - record.ttl = this.#maxTTL - } - - const familyRecords = records.records[record.family] ?? { ips: [] } - - familyRecords.ips.push(record) - records.records[record.family] = familyRecords - } - - // We provide a default TTL if external storage will be used without TTL per record-level support - this.storage.set(origin.hostname, records, { ttl: minTTL }) - } - - deleteRecords (origin) { - this.storage.delete(origin.hostname) - } +const textDecoder = new TextDecoder() - getHandler (meta, opts) { - return new DNSDispatchHandler(this, meta, opts) +/** + * @see https://encoding.spec.whatwg.org/#utf-8-decode + * @param {Uint8Array} buffer + */ +function utf8DecodeBytes (buffer) { + if (buffer.length === 0) { + return '' } -} -class DNSDispatchHandler extends DecoratorHandler { - #state = null - #opts = null - #dispatch = null - #origin = null - #controller = null - #newOrigin = null - #firstTry = true + // 1. Let buffer be the result of peeking three bytes from + // ioQueue, converted to a byte sequence. - constructor (state, { origin, handler, dispatch, newOrigin }, opts) { - super(handler) - this.#origin = origin - this.#newOrigin = newOrigin - this.#opts = { ...opts } - this.#state = state - this.#dispatch = dispatch + // 2. If buffer is 0xEF 0xBB 0xBF, then read three + // bytes from ioQueue. (Do nothing with those bytes.) + if (buffer[0] === 0xEF && buffer[1] === 0xBB && buffer[2] === 0xBF) { + buffer = buffer.subarray(3) } - onResponseError (controller, err) { - switch (err.code) { - case 'ETIMEDOUT': - case 'ECONNREFUSED': { - if (this.#state.dualStack) { - if (!this.#firstTry) { - super.onResponseError(controller, err) - return - } - this.#firstTry = false - - // Pick an ip address from the other family - const otherFamily = this.#newOrigin.hostname[0] === '[' ? 4 : 6 - const ip = this.#state.pickFamily(this.#origin, otherFamily) - if (ip == null) { - super.onResponseError(controller, err) - return - } - - let port - if (typeof ip.port === 'number') { - port = `:${ip.port}` - } else if (this.#origin.port !== '') { - port = `:${this.#origin.port}` - } else { - port = '' - } - - const dispatchOpts = { - ...this.#opts, - origin: `${this.#origin.protocol}//${ - ip.family === 6 ? `[${ip.address}]` : ip.address - }${port}` - } - this.#dispatch(dispatchOpts, this) - return - } + // 3. Process a queue with an instance of UTF-8’s + // decoder, ioQueue, output, and "replacement". + const output = textDecoder.decode(buffer) - // if dual-stack disabled, we error out - super.onResponseError(controller, err) - break - } - case 'ENOTFOUND': - this.#state.deleteRecords(this.#origin) - super.onResponseError(controller, err) - break - default: - super.onResponseError(controller, err) - break - } - } + // 4. Return output. + return output } -module.exports = interceptorOpts => { - if ( - interceptorOpts?.maxTTL != null && - (typeof interceptorOpts?.maxTTL !== 'number' || interceptorOpts?.maxTTL < 0) - ) { - throw new InvalidArgumentError('Invalid maxTTL. Must be a positive number') - } +module.exports = { + utf8DecodeBytes +} - if ( - interceptorOpts?.maxItems != null && - (typeof interceptorOpts?.maxItems !== 'number' || - interceptorOpts?.maxItems < 1) - ) { - throw new InvalidArgumentError( - 'Invalid maxItems. Must be a positive number and greater than zero' - ) - } - if ( - interceptorOpts?.affinity != null && - interceptorOpts?.affinity !== 4 && - interceptorOpts?.affinity !== 6 - ) { - throw new InvalidArgumentError('Invalid affinity. Must be either 4 or 6') - } +/***/ }), - if ( - interceptorOpts?.dualStack != null && - typeof interceptorOpts?.dualStack !== 'boolean' - ) { - throw new InvalidArgumentError('Invalid dualStack. Must be a boolean') - } +/***/ 7483: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - if ( - interceptorOpts?.lookup != null && - typeof interceptorOpts?.lookup !== 'function' - ) { - throw new InvalidArgumentError('Invalid lookup. Must be a function') - } - if ( - interceptorOpts?.pick != null && - typeof interceptorOpts?.pick !== 'function' - ) { - throw new InvalidArgumentError('Invalid pick. Must be a function') - } - if ( - interceptorOpts?.storage != null && - (typeof interceptorOpts?.storage?.get !== 'function' || - typeof interceptorOpts?.storage?.set !== 'function' || - typeof interceptorOpts?.storage?.full !== 'function' || - typeof interceptorOpts?.storage?.delete !== 'function' - ) - ) { - throw new InvalidArgumentError('Invalid storage. Must be a object with methods: { get, set, full, delete }') - } +// We include a version number for the Dispatcher API. In case of breaking changes, +// this version number must be increased to avoid conflicts. +const globalDispatcher = Symbol.for('undici.globalDispatcher.1') +const { InvalidArgumentError } = __nccwpck_require__(5093) +const Agent = __nccwpck_require__(9959) - const dualStack = interceptorOpts?.dualStack ?? true - let affinity - if (dualStack) { - affinity = interceptorOpts?.affinity ?? null - } else { - affinity = interceptorOpts?.affinity ?? 4 - } +if (getGlobalDispatcher() === undefined) { + setGlobalDispatcher(new Agent()) +} - const opts = { - maxTTL: interceptorOpts?.maxTTL ?? 10e3, // Expressed in ms - lookup: interceptorOpts?.lookup ?? null, - pick: interceptorOpts?.pick ?? null, - dualStack, - affinity, - maxItems: interceptorOpts?.maxItems ?? Infinity, - storage: interceptorOpts?.storage +function setGlobalDispatcher (agent) { + if (!agent || typeof agent.dispatch !== 'function') { + throw new InvalidArgumentError('Argument agent must implement Agent') } + Object.defineProperty(globalThis, globalDispatcher, { + value: agent, + writable: true, + enumerable: false, + configurable: false + }) +} - const instance = new DNSInstance(opts) - - return dispatch => { - return function dnsInterceptor (origDispatchOpts, handler) { - const origin = - origDispatchOpts.origin.constructor === URL - ? origDispatchOpts.origin - : new URL(origDispatchOpts.origin) - - if (isIP(origin.hostname) !== 0) { - return dispatch(origDispatchOpts, handler) - } - - instance.runLookup(origin, origDispatchOpts, (err, newOrigin) => { - if (err) { - return handler.onResponseError(null, err) - } - - const dispatchOpts = { - ...origDispatchOpts, - servername: origin.hostname, // For SNI on TLS - origin: newOrigin.origin, - headers: { - host: origin.host, - ...origDispatchOpts.headers - } - } +function getGlobalDispatcher () { + return globalThis[globalDispatcher] +} - dispatch( - dispatchOpts, - instance.getHandler( - { origin, dispatch, handler, newOrigin }, - origDispatchOpts - ) - ) - }) +// These are the globals that can be installed by undici.install(). +// Not exported by index.js to avoid use outside of this module. +const installedExports = /** @type {const} */ ( + [ + 'fetch', + 'Headers', + 'Response', + 'Request', + 'FormData', + 'WebSocket', + 'CloseEvent', + 'ErrorEvent', + 'MessageEvent', + 'EventSource' + ] +) - return true - } - } +module.exports = { + setGlobalDispatcher, + getGlobalDispatcher, + installedExports } /***/ }), -/***/ 873: +/***/ 1322: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -const { InvalidArgumentError, RequestAbortedError } = __nccwpck_require__(4928) -const DecoratorHandler = __nccwpck_require__(5156) +const util = __nccwpck_require__(2550) +const { + parseCacheControlHeader, + parseVaryHeader, + isEtagUsable +} = __nccwpck_require__(4649) +const { parseHttpDate } = __nccwpck_require__(7159) -class DumpHandler extends DecoratorHandler { - #maxSize = 1024 * 1024 - #dumped = false - #size = 0 - #controller = null - aborted = false - reason = false +function noop () {} - constructor ({ maxSize, signal }, handler) { - if (maxSize != null && (!Number.isFinite(maxSize) || maxSize < 1)) { - throw new InvalidArgumentError('maxSize must be a number greater than 0') - } +// Status codes that we can use some heuristics on to cache +const HEURISTICALLY_CACHEABLE_STATUS_CODES = [ + 200, 203, 204, 206, 300, 301, 308, 404, 405, 410, 414, 501 +] - super(handler) +// Status codes which semantic is not handled by the cache +// https://datatracker.ietf.org/doc/html/rfc9111#section-3 +// This list should not grow beyond 206 unless the RFC is updated +// by a newer one including more. Please introduce another list if +// implementing caching of responses with the 'must-understand' directive. +const NOT_UNDERSTOOD_STATUS_CODES = [ + 206 +] - this.#maxSize = maxSize ?? this.#maxSize - // this.#handler = handler - } +const MAX_RESPONSE_AGE = 2147483647000 - #abort (reason) { - this.aborted = true - this.reason = reason - } +/** + * @typedef {import('../../types/dispatcher.d.ts').default.DispatchHandler} DispatchHandler + * + * @implements {DispatchHandler} + */ +class CacheHandler { + /** + * @type {import('../../types/cache-interceptor.d.ts').default.CacheKey} + */ + #cacheKey - onRequestStart (controller, context) { - controller.abort = this.#abort.bind(this) - this.#controller = controller + /** + * @type {import('../../types/cache-interceptor.d.ts').default.CacheHandlerOptions['type']} + */ + #cacheType - return super.onRequestStart(controller, context) - } + /** + * @type {number | undefined} + */ + #cacheByDefault - onResponseStart (controller, statusCode, headers, statusMessage) { - const contentLength = headers['content-length'] + /** + * @type {import('../../types/cache-interceptor.d.ts').default.CacheStore} + */ + #store - if (contentLength != null && contentLength > this.#maxSize) { - throw new RequestAbortedError( - `Response size (${contentLength}) larger than maxSize (${ - this.#maxSize - })` - ) - } + /** + * @type {import('../../types/dispatcher.d.ts').default.DispatchHandler} + */ + #handler - if (this.aborted === true) { - return true - } + /** + * @type {import('node:stream').Writable | undefined} + */ + #writeStream - return super.onResponseStart(controller, statusCode, headers, statusMessage) + /** + * @param {import('../../types/cache-interceptor.d.ts').default.CacheHandlerOptions} opts + * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} cacheKey + * @param {import('../../types/dispatcher.d.ts').default.DispatchHandler} handler + */ + constructor ({ store, type, cacheByDefault }, cacheKey, handler) { + this.#store = store + this.#cacheType = type + this.#cacheByDefault = cacheByDefault + this.#cacheKey = cacheKey + this.#handler = handler } - onResponseError (controller, err) { - if (this.#dumped) { - return - } - - // On network errors before connect, controller will be null - err = this.#controller?.reason ?? err - - super.onResponseError(controller, err) + onRequestStart (controller, context) { + this.#writeStream?.destroy() + this.#writeStream = undefined + this.#handler.onRequestStart?.(controller, context) } - onResponseData (controller, chunk) { - this.#size = this.#size + chunk.length + onRequestUpgrade (controller, statusCode, headers, socket) { + this.#handler.onRequestUpgrade?.(controller, statusCode, headers, socket) + } - if (this.#size >= this.#maxSize) { - this.#dumped = true + /** + * @param {import('../../types/dispatcher.d.ts').default.DispatchController} controller + * @param {number} statusCode + * @param {import('../../types/header.d.ts').IncomingHttpHeaders} resHeaders + * @param {string} statusMessage + */ + onResponseStart ( + controller, + statusCode, + resHeaders, + statusMessage + ) { + const downstreamOnHeaders = () => + this.#handler.onResponseStart?.( + controller, + statusCode, + resHeaders, + statusMessage + ) + const handler = this - if (this.aborted === true) { - super.onResponseError(controller, this.reason) - } else { - super.onResponseEnd(controller, {}) + if ( + !util.safeHTTPMethods.includes(this.#cacheKey.method) && + statusCode >= 200 && + statusCode <= 399 + ) { + // Successful response to an unsafe method, delete it from cache + // https://www.rfc-editor.org/rfc/rfc9111.html#name-invalidating-stored-response + try { + this.#store.delete(this.#cacheKey)?.catch?.(noop) + } catch { + // Fail silently } + return downstreamOnHeaders() } - return true - } - - onResponseEnd (controller, trailers) { - if (this.#dumped) { - return + const cacheControlHeader = resHeaders['cache-control'] + const heuristicallyCacheable = resHeaders['last-modified'] && HEURISTICALLY_CACHEABLE_STATUS_CODES.includes(statusCode) + if ( + !cacheControlHeader && + !resHeaders['expires'] && + !heuristicallyCacheable && + !this.#cacheByDefault + ) { + // Don't have anything to tell us this response is cachable and we're not + // caching by default + return downstreamOnHeaders() } - if (this.#controller.aborted === true) { - super.onResponseError(controller, this.reason) - return + const cacheControlDirectives = cacheControlHeader ? parseCacheControlHeader(cacheControlHeader) : {} + if (!canCacheResponse(this.#cacheType, statusCode, resHeaders, cacheControlDirectives)) { + return downstreamOnHeaders() } - super.onResponseEnd(controller, trailers) - } -} + const now = Date.now() + const resAge = resHeaders.age ? getAge(resHeaders.age) : undefined + if (resAge && resAge >= MAX_RESPONSE_AGE) { + // Response considered stale + return downstreamOnHeaders() + } -function createDumpInterceptor ( - { maxSize: defaultMaxSize } = { - maxSize: 1024 * 1024 - } -) { - return dispatch => { - return function Intercept (opts, handler) { - const { dumpMaxSize = defaultMaxSize } = opts + const resDate = typeof resHeaders.date === 'string' + ? parseHttpDate(resHeaders.date) + : undefined - const dumpHandler = new DumpHandler({ maxSize: dumpMaxSize, signal: opts.signal }, handler) + const staleAt = + determineStaleAt(this.#cacheType, now, resAge, resHeaders, resDate, cacheControlDirectives) ?? + this.#cacheByDefault + if (staleAt === undefined || (resAge && resAge > staleAt)) { + return downstreamOnHeaders() + } - return dispatch(opts, dumpHandler) + const baseTime = resDate ? resDate.getTime() : now + const absoluteStaleAt = staleAt + baseTime + if (now >= absoluteStaleAt) { + // Response is already stale + return downstreamOnHeaders() } - } -} -module.exports = createDumpInterceptor + let varyDirectives + if (this.#cacheKey.headers && resHeaders.vary) { + varyDirectives = parseVaryHeader(resHeaders.vary, this.#cacheKey.headers) + if (!varyDirectives) { + // Parse error + return downstreamOnHeaders() + } + } + const deleteAt = determineDeleteAt(baseTime, cacheControlDirectives, absoluteStaleAt) + const strippedHeaders = stripNecessaryHeaders(resHeaders, cacheControlDirectives) -/***/ }), + /** + * @type {import('../../types/cache-interceptor.d.ts').default.CacheValue} + */ + const value = { + statusCode, + statusMessage, + headers: strippedHeaders, + vary: varyDirectives, + cacheControlDirectives, + cachedAt: resAge ? now - resAge : now, + staleAt: absoluteStaleAt, + deleteAt + } -/***/ 4455: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // Not modified, re-use the cached value + // https://www.rfc-editor.org/rfc/rfc9111.html#name-handling-304-not-modified + if (statusCode === 304) { + /** + * @type {import('../../types/cache-interceptor.d.ts').default.CacheValue} + */ + const cachedValue = this.#store.get(this.#cacheKey) + if (!cachedValue) { + // Do not create a new cache entry, as a 304 won't have a body - so cannot be cached. + return downstreamOnHeaders() + } -"use strict"; + // Re-use the cached value: statuscode, statusmessage, headers and body + value.statusCode = cachedValue.statusCode + value.statusMessage = cachedValue.statusMessage + value.etag = cachedValue.etag + value.headers = { ...cachedValue.headers, ...strippedHeaders } + downstreamOnHeaders() -const RedirectHandler = __nccwpck_require__(415) + this.#writeStream = this.#store.createWriteStream(this.#cacheKey, value) -function createRedirectInterceptor ({ maxRedirections: defaultMaxRedirections } = {}) { - return (dispatch) => { - return function Intercept (opts, handler) { - const { maxRedirections = defaultMaxRedirections, ...rest } = opts + if (!this.#writeStream || !cachedValue?.body) { + return + } - if (maxRedirections == null || maxRedirections === 0) { - return dispatch(opts, handler) + const bodyIterator = cachedValue.body.values() + + const streamCachedBody = () => { + for (const chunk of bodyIterator) { + const full = this.#writeStream.write(chunk) === false + this.#handler.onResponseData?.(controller, chunk) + // when stream is full stop writing until we get a 'drain' event + if (full) { + break + } + } } - const dispatchOpts = { ...rest } // Stop sub dispatcher from also redirecting. - const redirectHandler = new RedirectHandler(dispatch, maxRedirections, dispatchOpts, handler) - return dispatch(dispatchOpts, redirectHandler) - } - } -} + this.#writeStream + .on('error', function () { + handler.#writeStream = undefined + handler.#store.delete(handler.#cacheKey) + }) + .on('drain', () => { + streamCachedBody() + }) + .on('close', function () { + if (handler.#writeStream === this) { + handler.#writeStream = undefined + } + }) -module.exports = createRedirectInterceptor + streamCachedBody() + } else { + if (typeof resHeaders.etag === 'string' && isEtagUsable(resHeaders.etag)) { + value.etag = resHeaders.etag + } + this.#writeStream = this.#store.createWriteStream(this.#cacheKey, value) -/***/ }), + if (!this.#writeStream) { + return downstreamOnHeaders() + } -/***/ 3175: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + this.#writeStream + .on('drain', () => controller.resume()) + .on('error', function () { + // TODO (fix): Make error somehow observable? + handler.#writeStream = undefined -"use strict"; + // Delete the value in case the cache store is holding onto state from + // the call to createWriteStream + handler.#store.delete(handler.#cacheKey) + }) + .on('close', function () { + if (handler.#writeStream === this) { + handler.#writeStream = undefined + } + // TODO (fix): Should we resume even if was paused downstream? + controller.resume() + }) -// const { parseHeaders } = require('../core/util') -const DecoratorHandler = __nccwpck_require__(5156) -const { ResponseError } = __nccwpck_require__(4928) + downstreamOnHeaders() + } + } -class ResponseErrorHandler extends DecoratorHandler { - #statusCode - #contentType - #decoder - #headers - #body + onResponseData (controller, chunk) { + if (this.#writeStream?.write(chunk) === false) { + controller.pause() + } - constructor (_opts, { handler }) { - super(handler) + this.#handler.onResponseData?.(controller, chunk) } - #checkContentType (contentType) { - return (this.#contentType ?? '').indexOf(contentType) === 0 + onResponseEnd (controller, trailers) { + this.#writeStream?.end() + this.#handler.onResponseEnd?.(controller, trailers) } - onRequestStart (controller, context) { - this.#statusCode = 0 - this.#contentType = null - this.#decoder = null - this.#headers = null - this.#body = '' + onResponseError (controller, err) { + this.#writeStream?.destroy(err) + this.#writeStream = undefined + this.#handler.onResponseError?.(controller, err) + } +} - return super.onRequestStart(controller, context) +/** + * @see https://www.rfc-editor.org/rfc/rfc9111.html#name-storing-responses-to-authen + * + * @param {import('../../types/cache-interceptor.d.ts').default.CacheOptions['type']} cacheType + * @param {number} statusCode + * @param {import('../../types/header.d.ts').IncomingHttpHeaders} resHeaders + * @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives} cacheControlDirectives + */ +function canCacheResponse (cacheType, statusCode, resHeaders, cacheControlDirectives) { + // Status code must be final and understood. + if (statusCode < 200 || NOT_UNDERSTOOD_STATUS_CODES.includes(statusCode)) { + return false + } + // Responses with neither status codes that are heuristically cacheable, nor "explicit enough" caching + // directives, are not cacheable. "Explicit enough": see https://www.rfc-editor.org/rfc/rfc9111.html#section-3 + if (!HEURISTICALLY_CACHEABLE_STATUS_CODES.includes(statusCode) && !resHeaders['expires'] && + !cacheControlDirectives.public && + cacheControlDirectives['max-age'] === undefined && + // RFC 9111: a private response directive, if the cache is not shared + !(cacheControlDirectives.private && cacheType === 'private') && + !(cacheControlDirectives['s-maxage'] !== undefined && cacheType === 'shared') + ) { + return false } - onResponseStart (controller, statusCode, headers, statusMessage) { - this.#statusCode = statusCode - this.#headers = headers - this.#contentType = headers['content-type'] + if (cacheControlDirectives['no-store']) { + return false + } - if (this.#statusCode < 400) { - return super.onResponseStart(controller, statusCode, headers, statusMessage) + if (cacheType === 'shared' && cacheControlDirectives.private === true) { + return false + } + + // https://www.rfc-editor.org/rfc/rfc9111.html#section-4.1-5 + if (resHeaders.vary?.includes('*')) { + return false + } + + // https://www.rfc-editor.org/rfc/rfc9111.html#name-storing-responses-to-authen + if (resHeaders.authorization) { + if (!cacheControlDirectives.public || typeof resHeaders.authorization !== 'string') { + return false } - if (this.#checkContentType('application/json') || this.#checkContentType('text/plain')) { - this.#decoder = new TextDecoder('utf-8') + if ( + Array.isArray(cacheControlDirectives['no-cache']) && + cacheControlDirectives['no-cache'].includes('authorization') + ) { + return false + } + + if ( + Array.isArray(cacheControlDirectives['private']) && + cacheControlDirectives['private'].includes('authorization') + ) { + return false } } - onResponseData (controller, chunk) { - if (this.#statusCode < 400) { - return super.onResponseData(controller, chunk) + return true +} + +/** + * @param {string | string[]} ageHeader + * @returns {number | undefined} + */ +function getAge (ageHeader) { + const age = parseInt(Array.isArray(ageHeader) ? ageHeader[0] : ageHeader) + + return isNaN(age) ? undefined : age * 1000 +} + +/** + * @param {import('../../types/cache-interceptor.d.ts').default.CacheOptions['type']} cacheType + * @param {number} now + * @param {number | undefined} age + * @param {import('../../types/header.d.ts').IncomingHttpHeaders} resHeaders + * @param {Date | undefined} responseDate + * @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives} cacheControlDirectives + * + * @returns {number | undefined} time that the value is stale at in seconds or undefined if it shouldn't be cached + */ +function determineStaleAt (cacheType, now, age, resHeaders, responseDate, cacheControlDirectives) { + if (cacheType === 'shared') { + // Prioritize s-maxage since we're a shared cache + // s-maxage > max-age > Expire + // https://www.rfc-editor.org/rfc/rfc9111.html#section-5.2.2.10-3 + const sMaxAge = cacheControlDirectives['s-maxage'] + if (sMaxAge !== undefined) { + return sMaxAge > 0 ? sMaxAge * 1000 : undefined } + } - this.#body += this.#decoder?.decode(chunk, { stream: true }) ?? '' + const maxAge = cacheControlDirectives['max-age'] + if (maxAge !== undefined) { + return maxAge > 0 ? maxAge * 1000 : undefined } - onResponseEnd (controller, trailers) { - if (this.#statusCode >= 400) { - this.#body += this.#decoder?.decode(undefined, { stream: false }) ?? '' + if (typeof resHeaders.expires === 'string') { + // https://www.rfc-editor.org/rfc/rfc9111.html#section-5.3 + const expiresDate = parseHttpDate(resHeaders.expires) + if (expiresDate) { + if (now >= expiresDate.getTime()) { + return undefined + } - if (this.#checkContentType('application/json')) { - try { - this.#body = JSON.parse(this.#body) - } catch { - // Do nothing... + if (responseDate) { + if (responseDate >= expiresDate) { + return undefined + } + + if (age !== undefined && age > (expiresDate - responseDate)) { + return undefined } } - let err - const stackTraceLimit = Error.stackTraceLimit - Error.stackTraceLimit = 0 - try { - err = new ResponseError('Response Error', this.#statusCode, { - body: this.#body, - headers: this.#headers - }) - } finally { - Error.stackTraceLimit = stackTraceLimit + return expiresDate.getTime() - now + } + } + + if (typeof resHeaders['last-modified'] === 'string') { + // https://www.rfc-editor.org/rfc/rfc9111.html#name-calculating-heuristic-fresh + const lastModified = new Date(resHeaders['last-modified']) + if (isValidDate(lastModified)) { + if (lastModified.getTime() >= now) { + return undefined } - super.onResponseError(controller, err) - } else { - super.onResponseEnd(controller, trailers) + const responseAge = now - lastModified.getTime() + + return responseAge * 0.1 } } - onResponseError (controller, err) { - super.onResponseError(controller, err) + if (cacheControlDirectives.immutable) { + // https://www.rfc-editor.org/rfc/rfc8246.html#section-2.2 + return 31536000 } + + return undefined } -module.exports = () => { - return (dispatch) => { - return function Intercept (opts, handler) { - return dispatch(opts, new ResponseErrorHandler(opts, { handler })) +/** + * @param {number} now + * @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives} cacheControlDirectives + * @param {number} staleAt + */ +function determineDeleteAt (now, cacheControlDirectives, staleAt) { + let staleWhileRevalidate = -Infinity + let staleIfError = -Infinity + let immutable = -Infinity + + if (cacheControlDirectives['stale-while-revalidate']) { + staleWhileRevalidate = staleAt + (cacheControlDirectives['stale-while-revalidate'] * 1000) + } + + if (cacheControlDirectives['stale-if-error']) { + staleIfError = staleAt + (cacheControlDirectives['stale-if-error'] * 1000) + } + + if (staleWhileRevalidate === -Infinity && staleIfError === -Infinity) { + immutable = now + 31536000000 + } + + return Math.max(staleAt, staleWhileRevalidate, staleIfError, immutable) +} + +/** + * Strips headers required to be removed in cached responses + * @param {import('../../types/header.d.ts').IncomingHttpHeaders} resHeaders + * @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives} cacheControlDirectives + * @returns {Record} + */ +function stripNecessaryHeaders (resHeaders, cacheControlDirectives) { + const headersToRemove = [ + 'connection', + 'proxy-authenticate', + 'proxy-authentication-info', + 'proxy-authorization', + 'proxy-connection', + 'te', + 'transfer-encoding', + 'upgrade', + // We'll add age back when serving it + 'age' + ] + + if (resHeaders['connection']) { + if (Array.isArray(resHeaders['connection'])) { + // connection: a + // connection: b + headersToRemove.push(...resHeaders['connection'].map(header => header.trim())) + } else { + // connection: a, b + headersToRemove.push(...resHeaders['connection'].split(',').map(header => header.trim())) + } + } + + if (Array.isArray(cacheControlDirectives['no-cache'])) { + headersToRemove.push(...cacheControlDirectives['no-cache']) + } + + if (Array.isArray(cacheControlDirectives['private'])) { + headersToRemove.push(...cacheControlDirectives['private']) + } + + let strippedHeaders + for (const headerName of headersToRemove) { + if (resHeaders[headerName]) { + strippedHeaders ??= { ...resHeaders } + delete strippedHeaders[headerName] } } + + return strippedHeaders ?? resHeaders +} + +/** + * @param {Date} date + * @returns {boolean} + */ +function isValidDate (date) { + return date instanceof Date && Number.isFinite(date.valueOf()) } +module.exports = CacheHandler + /***/ }), -/***/ 3149: +/***/ 6795: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -const RetryHandler = __nccwpck_require__(4943) -module.exports = globalOpts => { - return dispatch => { - return function retryInterceptor (opts, handler) { - return dispatch( - opts, - new RetryHandler( - { ...opts, retryOptions: { ...globalOpts, ...opts.retryOptions } }, - { - handler, - dispatch - } - ) - ) +const assert = __nccwpck_require__(4589) + +/** + * This takes care of revalidation requests we send to the origin. If we get + * a response indicating that what we have is cached (via a HTTP 304), we can + * continue using the cached value. Otherwise, we'll receive the new response + * here, which we then just pass on to the next handler (most likely a + * CacheHandler). Note that this assumes the proper headers were already + * included in the request to tell the origin that we want to revalidate the + * response (i.e. if-modified-since or if-none-match). + * + * @see https://www.rfc-editor.org/rfc/rfc9111.html#name-validation + * + * @implements {import('../../types/dispatcher.d.ts').default.DispatchHandler} + */ +class CacheRevalidationHandler { + #successful = false + + /** + * @type {((boolean, any) => void) | null} + */ + #callback + + /** + * @type {(import('../../types/dispatcher.d.ts').default.DispatchHandler)} + */ + #handler + + #context + + /** + * @type {boolean} + */ + #allowErrorStatusCodes + + /** + * @param {(boolean) => void} callback Function to call if the cached value is valid + * @param {import('../../types/dispatcher.d.ts').default.DispatchHandlers} handler + * @param {boolean} allowErrorStatusCodes + */ + constructor (callback, handler, allowErrorStatusCodes) { + if (typeof callback !== 'function') { + throw new TypeError('callback must be a function') + } + + this.#callback = callback + this.#handler = handler + this.#allowErrorStatusCodes = allowErrorStatusCodes + } + + onRequestStart (_, context) { + this.#successful = false + this.#context = context + } + + onRequestUpgrade (controller, statusCode, headers, socket) { + this.#handler.onRequestUpgrade?.(controller, statusCode, headers, socket) + } + + onResponseStart ( + controller, + statusCode, + headers, + statusMessage + ) { + assert(this.#callback != null) + + // https://www.rfc-editor.org/rfc/rfc9111.html#name-handling-a-validation-respo + // https://datatracker.ietf.org/doc/html/rfc5861#section-4 + this.#successful = statusCode === 304 || + (this.#allowErrorStatusCodes && statusCode >= 500 && statusCode <= 504) + this.#callback(this.#successful, this.#context) + this.#callback = null + + if (this.#successful) { + return true + } + + this.#handler.onRequestStart?.(controller, this.#context) + this.#handler.onResponseStart?.( + controller, + statusCode, + headers, + statusMessage + ) + } + + onResponseData (controller, chunk) { + if (this.#successful) { + return + } + + return this.#handler.onResponseData?.(controller, chunk) + } + + onResponseEnd (controller, trailers) { + if (this.#successful) { + return + } + + this.#handler.onResponseEnd?.(controller, trailers) + } + + onResponseError (controller, err) { + if (this.#successful) { + return + } + + if (this.#callback) { + this.#callback(false) + this.#callback = null + } + + if (typeof this.#handler.onResponseError === 'function') { + this.#handler.onResponseError(controller, err) + } else { + throw err } } } +module.exports = CacheRevalidationHandler + /***/ }), -/***/ 5849: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { +/***/ 169: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.SPECIAL_HEADERS = exports.MINOR = exports.MAJOR = exports.HTAB_SP_VCHAR_OBS_TEXT = exports.QUOTED_STRING = exports.CONNECTION_TOKEN_CHARS = exports.HEADER_CHARS = exports.TOKEN = exports.HEX = exports.URL_CHAR = exports.USERINFO_CHARS = exports.MARK = exports.ALPHANUM = exports.NUM = exports.HEX_MAP = exports.NUM_MAP = exports.ALPHA = exports.STATUSES_HTTP = exports.H_METHOD_MAP = exports.METHOD_MAP = exports.METHODS_RTSP = exports.METHODS_ICE = exports.METHODS_HTTP = exports.HEADER_STATE = exports.FINISH = exports.STATUSES = exports.METHODS = exports.LENIENT_FLAGS = exports.FLAGS = exports.TYPE = exports.ERROR = void 0; -const utils_1 = __nccwpck_require__(8493); -// Emums -exports.ERROR = { - OK: 0, - INTERNAL: 1, - STRICT: 2, - CR_EXPECTED: 25, - LF_EXPECTED: 3, - UNEXPECTED_CONTENT_LENGTH: 4, - UNEXPECTED_SPACE: 30, - CLOSED_CONNECTION: 5, - INVALID_METHOD: 6, - INVALID_URL: 7, - INVALID_CONSTANT: 8, - INVALID_VERSION: 9, - INVALID_HEADER_TOKEN: 10, - INVALID_CONTENT_LENGTH: 11, - INVALID_CHUNK_SIZE: 12, - INVALID_STATUS: 13, - INVALID_EOF_STATE: 14, - INVALID_TRANSFER_ENCODING: 15, - CB_MESSAGE_BEGIN: 16, - CB_HEADERS_COMPLETE: 17, - CB_MESSAGE_COMPLETE: 18, - CB_CHUNK_HEADER: 19, - CB_CHUNK_COMPLETE: 20, - PAUSED: 21, - PAUSED_UPGRADE: 22, - PAUSED_H2_UPGRADE: 23, - USER: 24, - CB_URL_COMPLETE: 26, - CB_STATUS_COMPLETE: 27, - CB_METHOD_COMPLETE: 32, - CB_VERSION_COMPLETE: 33, - CB_HEADER_FIELD_COMPLETE: 28, - CB_HEADER_VALUE_COMPLETE: 29, - CB_CHUNK_EXTENSION_NAME_COMPLETE: 34, - CB_CHUNK_EXTENSION_VALUE_COMPLETE: 35, - CB_RESET: 31, - CB_PROTOCOL_COMPLETE: 38, -}; -exports.TYPE = { - BOTH: 0, // default - REQUEST: 1, - RESPONSE: 2, -}; -exports.FLAGS = { - CONNECTION_KEEP_ALIVE: 1 << 0, - CONNECTION_CLOSE: 1 << 1, - CONNECTION_UPGRADE: 1 << 2, - CHUNKED: 1 << 3, - UPGRADE: 1 << 4, - CONTENT_LENGTH: 1 << 5, - SKIPBODY: 1 << 6, - TRAILING: 1 << 7, - // 1 << 8 is unused - TRANSFER_ENCODING: 1 << 9, -}; -exports.LENIENT_FLAGS = { - HEADERS: 1 << 0, - CHUNKED_LENGTH: 1 << 1, - KEEP_ALIVE: 1 << 2, - TRANSFER_ENCODING: 1 << 3, - VERSION: 1 << 4, - DATA_AFTER_CLOSE: 1 << 5, - OPTIONAL_LF_AFTER_CR: 1 << 6, - OPTIONAL_CRLF_AFTER_CHUNK: 1 << 7, - OPTIONAL_CR_BEFORE_LF: 1 << 8, - SPACES_AFTER_CHUNK_SIZE: 1 << 9, -}; -exports.METHODS = { - 'DELETE': 0, - 'GET': 1, - 'HEAD': 2, - 'POST': 3, - 'PUT': 4, - /* pathological */ - 'CONNECT': 5, - 'OPTIONS': 6, - 'TRACE': 7, - /* WebDAV */ - 'COPY': 8, - 'LOCK': 9, - 'MKCOL': 10, - 'MOVE': 11, - 'PROPFIND': 12, - 'PROPPATCH': 13, - 'SEARCH': 14, - 'UNLOCK': 15, - 'BIND': 16, - 'REBIND': 17, - 'UNBIND': 18, - 'ACL': 19, - /* subversion */ - 'REPORT': 20, - 'MKACTIVITY': 21, - 'CHECKOUT': 22, - 'MERGE': 23, - /* upnp */ - 'M-SEARCH': 24, - 'NOTIFY': 25, - 'SUBSCRIBE': 26, - 'UNSUBSCRIBE': 27, - /* RFC-5789 */ - 'PATCH': 28, - 'PURGE': 29, - /* CalDAV */ - 'MKCALENDAR': 30, - /* RFC-2068, section 19.6.1.2 */ - 'LINK': 31, - 'UNLINK': 32, - /* icecast */ - 'SOURCE': 33, - /* RFC-7540, section 11.6 */ - 'PRI': 34, - /* RFC-2326 RTSP */ - 'DESCRIBE': 35, - 'ANNOUNCE': 36, - 'SETUP': 37, - 'PLAY': 38, - 'PAUSE': 39, - 'TEARDOWN': 40, - 'GET_PARAMETER': 41, - 'SET_PARAMETER': 42, - 'REDIRECT': 43, - 'RECORD': 44, - /* RAOP */ - 'FLUSH': 45, - /* DRAFT https://www.ietf.org/archive/id/draft-ietf-httpbis-safe-method-w-body-02.html */ - 'QUERY': 46, -}; -exports.STATUSES = { - CONTINUE: 100, - SWITCHING_PROTOCOLS: 101, - PROCESSING: 102, - EARLY_HINTS: 103, - RESPONSE_IS_STALE: 110, // Unofficial - REVALIDATION_FAILED: 111, // Unofficial - DISCONNECTED_OPERATION: 112, // Unofficial - HEURISTIC_EXPIRATION: 113, // Unofficial - MISCELLANEOUS_WARNING: 199, // Unofficial - OK: 200, - CREATED: 201, - ACCEPTED: 202, - NON_AUTHORITATIVE_INFORMATION: 203, - NO_CONTENT: 204, - RESET_CONTENT: 205, - PARTIAL_CONTENT: 206, - MULTI_STATUS: 207, - ALREADY_REPORTED: 208, - TRANSFORMATION_APPLIED: 214, // Unofficial - IM_USED: 226, - MISCELLANEOUS_PERSISTENT_WARNING: 299, // Unofficial - MULTIPLE_CHOICES: 300, - MOVED_PERMANENTLY: 301, - FOUND: 302, - SEE_OTHER: 303, - NOT_MODIFIED: 304, - USE_PROXY: 305, - SWITCH_PROXY: 306, // No longer used - TEMPORARY_REDIRECT: 307, - PERMANENT_REDIRECT: 308, - BAD_REQUEST: 400, - UNAUTHORIZED: 401, - PAYMENT_REQUIRED: 402, - FORBIDDEN: 403, - NOT_FOUND: 404, - METHOD_NOT_ALLOWED: 405, - NOT_ACCEPTABLE: 406, - PROXY_AUTHENTICATION_REQUIRED: 407, - REQUEST_TIMEOUT: 408, - CONFLICT: 409, - GONE: 410, - LENGTH_REQUIRED: 411, - PRECONDITION_FAILED: 412, - PAYLOAD_TOO_LARGE: 413, - URI_TOO_LONG: 414, - UNSUPPORTED_MEDIA_TYPE: 415, - RANGE_NOT_SATISFIABLE: 416, - EXPECTATION_FAILED: 417, - IM_A_TEAPOT: 418, - PAGE_EXPIRED: 419, // Unofficial - ENHANCE_YOUR_CALM: 420, // Unofficial - MISDIRECTED_REQUEST: 421, - UNPROCESSABLE_ENTITY: 422, - LOCKED: 423, - FAILED_DEPENDENCY: 424, - TOO_EARLY: 425, - UPGRADE_REQUIRED: 426, - PRECONDITION_REQUIRED: 428, - TOO_MANY_REQUESTS: 429, - REQUEST_HEADER_FIELDS_TOO_LARGE_UNOFFICIAL: 430, // Unofficial - REQUEST_HEADER_FIELDS_TOO_LARGE: 431, - LOGIN_TIMEOUT: 440, // Unofficial - NO_RESPONSE: 444, // Unofficial - RETRY_WITH: 449, // Unofficial - BLOCKED_BY_PARENTAL_CONTROL: 450, // Unofficial - UNAVAILABLE_FOR_LEGAL_REASONS: 451, - CLIENT_CLOSED_LOAD_BALANCED_REQUEST: 460, // Unofficial - INVALID_X_FORWARDED_FOR: 463, // Unofficial - REQUEST_HEADER_TOO_LARGE: 494, // Unofficial - SSL_CERTIFICATE_ERROR: 495, // Unofficial - SSL_CERTIFICATE_REQUIRED: 496, // Unofficial - HTTP_REQUEST_SENT_TO_HTTPS_PORT: 497, // Unofficial - INVALID_TOKEN: 498, // Unofficial - CLIENT_CLOSED_REQUEST: 499, // Unofficial - INTERNAL_SERVER_ERROR: 500, - NOT_IMPLEMENTED: 501, - BAD_GATEWAY: 502, - SERVICE_UNAVAILABLE: 503, - GATEWAY_TIMEOUT: 504, - HTTP_VERSION_NOT_SUPPORTED: 505, - VARIANT_ALSO_NEGOTIATES: 506, - INSUFFICIENT_STORAGE: 507, - LOOP_DETECTED: 508, - BANDWIDTH_LIMIT_EXCEEDED: 509, - NOT_EXTENDED: 510, - NETWORK_AUTHENTICATION_REQUIRED: 511, - WEB_SERVER_UNKNOWN_ERROR: 520, // Unofficial - WEB_SERVER_IS_DOWN: 521, // Unofficial - CONNECTION_TIMEOUT: 522, // Unofficial - ORIGIN_IS_UNREACHABLE: 523, // Unofficial - TIMEOUT_OCCURED: 524, // Unofficial - SSL_HANDSHAKE_FAILED: 525, // Unofficial - INVALID_SSL_CERTIFICATE: 526, // Unofficial - RAILGUN_ERROR: 527, // Unofficial - SITE_IS_OVERLOADED: 529, // Unofficial - SITE_IS_FROZEN: 530, // Unofficial - IDENTITY_PROVIDER_AUTHENTICATION_ERROR: 561, // Unofficial - NETWORK_READ_TIMEOUT: 598, // Unofficial - NETWORK_CONNECT_TIMEOUT: 599, // Unofficial -}; -exports.FINISH = { - SAFE: 0, - SAFE_WITH_CB: 1, - UNSAFE: 2, -}; -exports.HEADER_STATE = { - GENERAL: 0, - CONNECTION: 1, - CONTENT_LENGTH: 2, - TRANSFER_ENCODING: 3, - UPGRADE: 4, - CONNECTION_KEEP_ALIVE: 5, - CONNECTION_CLOSE: 6, - CONNECTION_UPGRADE: 7, - TRANSFER_ENCODING_CHUNKED: 8, -}; -// C headers -exports.METHODS_HTTP = [ - exports.METHODS.DELETE, - exports.METHODS.GET, - exports.METHODS.HEAD, - exports.METHODS.POST, - exports.METHODS.PUT, - exports.METHODS.CONNECT, - exports.METHODS.OPTIONS, - exports.METHODS.TRACE, - exports.METHODS.COPY, - exports.METHODS.LOCK, - exports.METHODS.MKCOL, - exports.METHODS.MOVE, - exports.METHODS.PROPFIND, - exports.METHODS.PROPPATCH, - exports.METHODS.SEARCH, - exports.METHODS.UNLOCK, - exports.METHODS.BIND, - exports.METHODS.REBIND, - exports.METHODS.UNBIND, - exports.METHODS.ACL, - exports.METHODS.REPORT, - exports.METHODS.MKACTIVITY, - exports.METHODS.CHECKOUT, - exports.METHODS.MERGE, - exports.METHODS['M-SEARCH'], - exports.METHODS.NOTIFY, - exports.METHODS.SUBSCRIBE, - exports.METHODS.UNSUBSCRIBE, - exports.METHODS.PATCH, - exports.METHODS.PURGE, - exports.METHODS.MKCALENDAR, - exports.METHODS.LINK, - exports.METHODS.UNLINK, - exports.METHODS.PRI, - // TODO(indutny): should we allow it with HTTP? - exports.METHODS.SOURCE, - exports.METHODS.QUERY, -]; -exports.METHODS_ICE = [ - exports.METHODS.SOURCE, -]; -exports.METHODS_RTSP = [ - exports.METHODS.OPTIONS, - exports.METHODS.DESCRIBE, - exports.METHODS.ANNOUNCE, - exports.METHODS.SETUP, - exports.METHODS.PLAY, - exports.METHODS.PAUSE, - exports.METHODS.TEARDOWN, - exports.METHODS.GET_PARAMETER, - exports.METHODS.SET_PARAMETER, - exports.METHODS.REDIRECT, - exports.METHODS.RECORD, - exports.METHODS.FLUSH, - // For AirPlay - exports.METHODS.GET, - exports.METHODS.POST, -]; -exports.METHOD_MAP = (0, utils_1.enumToMap)(exports.METHODS); -exports.H_METHOD_MAP = Object.fromEntries(Object.entries(exports.METHODS).filter(([k]) => k.startsWith('H'))); -exports.STATUSES_HTTP = [ - exports.STATUSES.CONTINUE, - exports.STATUSES.SWITCHING_PROTOCOLS, - exports.STATUSES.PROCESSING, - exports.STATUSES.EARLY_HINTS, - exports.STATUSES.RESPONSE_IS_STALE, - exports.STATUSES.REVALIDATION_FAILED, - exports.STATUSES.DISCONNECTED_OPERATION, - exports.STATUSES.HEURISTIC_EXPIRATION, - exports.STATUSES.MISCELLANEOUS_WARNING, - exports.STATUSES.OK, - exports.STATUSES.CREATED, - exports.STATUSES.ACCEPTED, - exports.STATUSES.NON_AUTHORITATIVE_INFORMATION, - exports.STATUSES.NO_CONTENT, - exports.STATUSES.RESET_CONTENT, - exports.STATUSES.PARTIAL_CONTENT, - exports.STATUSES.MULTI_STATUS, - exports.STATUSES.ALREADY_REPORTED, - exports.STATUSES.TRANSFORMATION_APPLIED, - exports.STATUSES.IM_USED, - exports.STATUSES.MISCELLANEOUS_PERSISTENT_WARNING, - exports.STATUSES.MULTIPLE_CHOICES, - exports.STATUSES.MOVED_PERMANENTLY, - exports.STATUSES.FOUND, - exports.STATUSES.SEE_OTHER, - exports.STATUSES.NOT_MODIFIED, - exports.STATUSES.USE_PROXY, - exports.STATUSES.SWITCH_PROXY, - exports.STATUSES.TEMPORARY_REDIRECT, - exports.STATUSES.PERMANENT_REDIRECT, - exports.STATUSES.BAD_REQUEST, - exports.STATUSES.UNAUTHORIZED, - exports.STATUSES.PAYMENT_REQUIRED, - exports.STATUSES.FORBIDDEN, - exports.STATUSES.NOT_FOUND, - exports.STATUSES.METHOD_NOT_ALLOWED, - exports.STATUSES.NOT_ACCEPTABLE, - exports.STATUSES.PROXY_AUTHENTICATION_REQUIRED, - exports.STATUSES.REQUEST_TIMEOUT, - exports.STATUSES.CONFLICT, - exports.STATUSES.GONE, - exports.STATUSES.LENGTH_REQUIRED, - exports.STATUSES.PRECONDITION_FAILED, - exports.STATUSES.PAYLOAD_TOO_LARGE, - exports.STATUSES.URI_TOO_LONG, - exports.STATUSES.UNSUPPORTED_MEDIA_TYPE, - exports.STATUSES.RANGE_NOT_SATISFIABLE, - exports.STATUSES.EXPECTATION_FAILED, - exports.STATUSES.IM_A_TEAPOT, - exports.STATUSES.PAGE_EXPIRED, - exports.STATUSES.ENHANCE_YOUR_CALM, - exports.STATUSES.MISDIRECTED_REQUEST, - exports.STATUSES.UNPROCESSABLE_ENTITY, - exports.STATUSES.LOCKED, - exports.STATUSES.FAILED_DEPENDENCY, - exports.STATUSES.TOO_EARLY, - exports.STATUSES.UPGRADE_REQUIRED, - exports.STATUSES.PRECONDITION_REQUIRED, - exports.STATUSES.TOO_MANY_REQUESTS, - exports.STATUSES.REQUEST_HEADER_FIELDS_TOO_LARGE_UNOFFICIAL, - exports.STATUSES.REQUEST_HEADER_FIELDS_TOO_LARGE, - exports.STATUSES.LOGIN_TIMEOUT, - exports.STATUSES.NO_RESPONSE, - exports.STATUSES.RETRY_WITH, - exports.STATUSES.BLOCKED_BY_PARENTAL_CONTROL, - exports.STATUSES.UNAVAILABLE_FOR_LEGAL_REASONS, - exports.STATUSES.CLIENT_CLOSED_LOAD_BALANCED_REQUEST, - exports.STATUSES.INVALID_X_FORWARDED_FOR, - exports.STATUSES.REQUEST_HEADER_TOO_LARGE, - exports.STATUSES.SSL_CERTIFICATE_ERROR, - exports.STATUSES.SSL_CERTIFICATE_REQUIRED, - exports.STATUSES.HTTP_REQUEST_SENT_TO_HTTPS_PORT, - exports.STATUSES.INVALID_TOKEN, - exports.STATUSES.CLIENT_CLOSED_REQUEST, - exports.STATUSES.INTERNAL_SERVER_ERROR, - exports.STATUSES.NOT_IMPLEMENTED, - exports.STATUSES.BAD_GATEWAY, - exports.STATUSES.SERVICE_UNAVAILABLE, - exports.STATUSES.GATEWAY_TIMEOUT, - exports.STATUSES.HTTP_VERSION_NOT_SUPPORTED, - exports.STATUSES.VARIANT_ALSO_NEGOTIATES, - exports.STATUSES.INSUFFICIENT_STORAGE, - exports.STATUSES.LOOP_DETECTED, - exports.STATUSES.BANDWIDTH_LIMIT_EXCEEDED, - exports.STATUSES.NOT_EXTENDED, - exports.STATUSES.NETWORK_AUTHENTICATION_REQUIRED, - exports.STATUSES.WEB_SERVER_UNKNOWN_ERROR, - exports.STATUSES.WEB_SERVER_IS_DOWN, - exports.STATUSES.CONNECTION_TIMEOUT, - exports.STATUSES.ORIGIN_IS_UNREACHABLE, - exports.STATUSES.TIMEOUT_OCCURED, - exports.STATUSES.SSL_HANDSHAKE_FAILED, - exports.STATUSES.INVALID_SSL_CERTIFICATE, - exports.STATUSES.RAILGUN_ERROR, - exports.STATUSES.SITE_IS_OVERLOADED, - exports.STATUSES.SITE_IS_FROZEN, - exports.STATUSES.IDENTITY_PROVIDER_AUTHENTICATION_ERROR, - exports.STATUSES.NETWORK_READ_TIMEOUT, - exports.STATUSES.NETWORK_CONNECT_TIMEOUT, -]; -exports.ALPHA = []; -for (let i = 'A'.charCodeAt(0); i <= 'Z'.charCodeAt(0); i++) { - // Upper case - exports.ALPHA.push(String.fromCharCode(i)); - // Lower case - exports.ALPHA.push(String.fromCharCode(i + 0x20)); -} -exports.NUM_MAP = { - 0: 0, 1: 1, 2: 2, 3: 3, 4: 4, - 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, -}; -exports.HEX_MAP = { - 0: 0, 1: 1, 2: 2, 3: 3, 4: 4, - 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, - A: 0XA, B: 0XB, C: 0XC, D: 0XD, E: 0XE, F: 0XF, - a: 0xa, b: 0xb, c: 0xc, d: 0xd, e: 0xe, f: 0xf, -}; -exports.NUM = [ - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', -]; -exports.ALPHANUM = exports.ALPHA.concat(exports.NUM); -exports.MARK = ['-', '_', '.', '!', '~', '*', '\'', '(', ')']; -exports.USERINFO_CHARS = exports.ALPHANUM - .concat(exports.MARK) - .concat(['%', ';', ':', '&', '=', '+', '$', ',']); -// TODO(indutny): use RFC -exports.URL_CHAR = [ - '!', '"', '$', '%', '&', '\'', - '(', ')', '*', '+', ',', '-', '.', '/', - ':', ';', '<', '=', '>', - '@', '[', '\\', ']', '^', '_', - '`', - '{', '|', '}', '~', -].concat(exports.ALPHANUM); -exports.HEX = exports.NUM.concat(['a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F']); -/* Tokens as defined by rfc 2616. Also lowercases them. - * token = 1* - * separators = "(" | ")" | "<" | ">" | "@" - * | "," | ";" | ":" | "\" | <"> - * | "/" | "[" | "]" | "?" | "=" - * | "{" | "}" | SP | HT - */ -exports.TOKEN = [ - '!', '#', '$', '%', '&', '\'', - '*', '+', '-', '.', - '^', '_', '`', - '|', '~', -].concat(exports.ALPHANUM); -/* - * Verify that a char is a valid visible (printable) US-ASCII - * character or %x80-FF - */ -exports.HEADER_CHARS = ['\t']; -for (let i = 32; i <= 255; i++) { - if (i !== 127) { - exports.HEADER_CHARS.push(i); - } -} -// ',' = \x44 -exports.CONNECTION_TOKEN_CHARS = exports.HEADER_CHARS.filter((c) => c !== 44); -exports.QUOTED_STRING = ['\t', ' ']; -for (let i = 0x21; i <= 0xff; i++) { - if (i !== 0x22 && i !== 0x5c) { // All characters in ASCII except \ and " - exports.QUOTED_STRING.push(i); - } -} -exports.HTAB_SP_VCHAR_OBS_TEXT = ['\t', ' ']; -// VCHAR: https://tools.ietf.org/html/rfc5234#appendix-B.1 -for (let i = 0x21; i <= 0x7E; i++) { - exports.HTAB_SP_VCHAR_OBS_TEXT.push(i); -} -// OBS_TEXT: https://datatracker.ietf.org/doc/html/rfc9110#name-collected-abnf -for (let i = 0x80; i <= 0xff; i++) { - exports.HTAB_SP_VCHAR_OBS_TEXT.push(i); -} -exports.MAJOR = exports.NUM_MAP; -exports.MINOR = exports.MAJOR; -exports.SPECIAL_HEADERS = { - 'connection': exports.HEADER_STATE.CONNECTION, - 'content-length': exports.HEADER_STATE.CONTENT_LENGTH, - 'proxy-connection': exports.HEADER_STATE.CONNECTION, - 'transfer-encoding': exports.HEADER_STATE.TRANSFER_ENCODING, - 'upgrade': exports.HEADER_STATE.UPGRADE, -}; -exports["default"] = { - ERROR: exports.ERROR, - TYPE: exports.TYPE, - FLAGS: exports.FLAGS, - LENIENT_FLAGS: exports.LENIENT_FLAGS, - METHODS: exports.METHODS, - STATUSES: exports.STATUSES, - FINISH: exports.FINISH, - HEADER_STATE: exports.HEADER_STATE, - ALPHA: exports.ALPHA, - NUM_MAP: exports.NUM_MAP, - HEX_MAP: exports.HEX_MAP, - NUM: exports.NUM, - ALPHANUM: exports.ALPHANUM, - MARK: exports.MARK, - USERINFO_CHARS: exports.USERINFO_CHARS, - URL_CHAR: exports.URL_CHAR, - HEX: exports.HEX, - TOKEN: exports.TOKEN, - HEADER_CHARS: exports.HEADER_CHARS, - CONNECTION_TOKEN_CHARS: exports.CONNECTION_TOKEN_CHARS, - QUOTED_STRING: exports.QUOTED_STRING, - HTAB_SP_VCHAR_OBS_TEXT: exports.HTAB_SP_VCHAR_OBS_TEXT, - MAJOR: exports.MAJOR, - MINOR: exports.MINOR, - SPECIAL_HEADERS: exports.SPECIAL_HEADERS, - METHODS_HTTP: exports.METHODS_HTTP, - METHODS_ICE: exports.METHODS_ICE, - METHODS_RTSP: exports.METHODS_RTSP, - METHOD_MAP: exports.METHOD_MAP, - H_METHOD_MAP: exports.H_METHOD_MAP, - STATUSES_HTTP: exports.STATUSES_HTTP, -}; +const assert = __nccwpck_require__(4589) +const WrapHandler = __nccwpck_require__(6444) -/***/ }), - -/***/ 571: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +/** + * @deprecated + */ +module.exports = class DecoratorHandler { + #handler + #onCompleteCalled = false + #onErrorCalled = false + #onResponseStartCalled = false -"use strict"; -/* module decorator */ module = __nccwpck_require__.nmd(module); + constructor (handler) { + if (typeof handler !== 'object' || handler === null) { + throw new TypeError('handler must be an object') + } + this.#handler = WrapHandler.wrap(handler) + } + onRequestStart (...args) { + this.#handler.onRequestStart?.(...args) + } -const { Buffer } = __nccwpck_require__(4573) - -const wasmBase64 = 'AGFzbQEAAAABJwdgAX8Bf2ADf39/AX9gAn9/AGABfwBgBH9/f38Bf2AAAGADf39/AALLAQgDZW52GHdhc21fb25faGVhZGVyc19jb21wbGV0ZQAEA2VudhV3YXNtX29uX21lc3NhZ2VfYmVnaW4AAANlbnYLd2FzbV9vbl91cmwAAQNlbnYOd2FzbV9vbl9zdGF0dXMAAQNlbnYUd2FzbV9vbl9oZWFkZXJfZmllbGQAAQNlbnYUd2FzbV9vbl9oZWFkZXJfdmFsdWUAAQNlbnYMd2FzbV9vbl9ib2R5AAEDZW52GHdhc21fb25fbWVzc2FnZV9jb21wbGV0ZQAAAzU0BQYAAAMAAAAAAAADAQMAAwMDAAACAAAAAAICAgICAgICAgIBAQEBAQEBAQEBAwAAAwAAAAQFAXABExMFAwEAAgYIAX8BQcDZBAsHxQcoBm1lbW9yeQIAC19pbml0aWFsaXplAAgZX19pbmRpcmVjdF9mdW5jdGlvbl90YWJsZQEAC2xsaHR0cF9pbml0AAkYbGxodHRwX3Nob3VsZF9rZWVwX2FsaXZlADcMbGxodHRwX2FsbG9jAAsGbWFsbG9jADkLbGxodHRwX2ZyZWUADARmcmVlAAwPbGxodHRwX2dldF90eXBlAA0VbGxodHRwX2dldF9odHRwX21ham9yAA4VbGxodHRwX2dldF9odHRwX21pbm9yAA8RbGxodHRwX2dldF9tZXRob2QAEBZsbGh0dHBfZ2V0X3N0YXR1c19jb2RlABESbGxodHRwX2dldF91cGdyYWRlABIMbGxodHRwX3Jlc2V0ABMObGxodHRwX2V4ZWN1dGUAFBRsbGh0dHBfc2V0dGluZ3NfaW5pdAAVDWxsaHR0cF9maW5pc2gAFgxsbGh0dHBfcGF1c2UAFw1sbGh0dHBfcmVzdW1lABgbbGxodHRwX3Jlc3VtZV9hZnRlcl91cGdyYWRlABkQbGxodHRwX2dldF9lcnJubwAaF2xsaHR0cF9nZXRfZXJyb3JfcmVhc29uABsXbGxodHRwX3NldF9lcnJvcl9yZWFzb24AHBRsbGh0dHBfZ2V0X2Vycm9yX3BvcwAdEWxsaHR0cF9lcnJub19uYW1lAB4SbGxodHRwX21ldGhvZF9uYW1lAB8SbGxodHRwX3N0YXR1c19uYW1lACAabGxodHRw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AXRrQT5qIQILIAEgAjYCHCABQgA3AhAgAkECdEH01wBqIQACQEHI1QAoAgAiA0EBIAJ0IgdxRQRAIAAgATYCAEHI1QAgAyAHcjYCACABIAA2AhggASABNgIIIAEgATYCDAwBCyAEQRkgAkEBdmtBACACQR9HG3QhAiAAKAIAIQACQANAIAAiAygCBEF4cSAERg0BIAJBHXYhACACQQF0IQIgAyAAQQRxakEQaiIHKAIAIgANAAsgByABNgIAIAEgAzYCGCABIAE2AgwgASABNgIIDAELIAMoAggiACABNgIMIAMgATYCCCABQQA2AhggASADNgIMIAEgADYCCAtB5NUAQeTVACgCAEEBayIAQX8gABs2AgALCwcAIAAtACgLBwAgAC0AKgsHACAALQArCwcAIAAtACkLBwAgAC8BNAsHACAALQAwC0ABBH8gACgCGCEBIAAvAS4hAiAALQAoIQMgACgCOCEEIAAQOCAAIAQ2AjggACADOgAoIAAgAjsBLiAAIAE2AhgL5YUCAgd/A34gASACaiEEAkAgACIDKAIMIgANACADKAIEBEAgAyABNgIECyMAQRBrIgkkAAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAn8CQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAC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C0HjAQwHC0HXAQwGC0HYAQwFC0HZAQwEC0HaAQwDC0HbAQwCC0HdAQwBC0HcAQshAgNAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCADAn8CQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAn8CQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAn8CQAJAAkACQAJAAkACQAJ/AkACQAJAAn8CQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIAMCfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAg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ogKiAqICogKiAqICogKiAqICogKiAqICogIAogILIAQgAUEBaiIBRw0AC0HJACECDOwCCyABQQFqIQEgA0Evai0AAEEBcQ2lAiADQQA2AhwgAyABNgIUIANBlxA2AhAgA0EKNgIMQQAhAgzrAgsgASAERwRAA0AgAS0AAEEgRw0VIAQgAUEBaiIBRw0AC0H4ACECDOsCC0H4ACECDOoCCyADQQI6ACgMOAtBACECIANBADYCHCADQb8LNgIQIANBAjYCDCADIAFBAWo2AhQM6AILQQAhAgzOAgtBDSECDM0CC0ETIQIMzAILQRUhAgzLAgtBFiECDMoCC0EYIQIMyQILQRkhAgzIAgtBGiECDMcCC0EbIQIMxgILQRwhAgzFAgtBHSECDMQCC0EeIQIMwwILQR8hAgzCAgtBICECDMECC0EiIQIMwAILQSMhAgy/AgtBJSECDL4CC0HlACECDL0CCyADQT02AhwgAyABNgIUIAMgADYCDEEAIQIM1QILIANBGzYCHCADIAE2AhQgA0GkHDYCECADQRU2AgxBACECDNQCCyADQSA2AhwgAyABNgIUIANBmBo2AhAgA0EVNgIMQQAhAgzTAgsgA0ETNgIcIAMgATYCFCADQZgaNgIQIANBFTYCDEEAIQIM0gILIANBCzYCHCADIAE2AhQgA0GYGjYCECADQRU2AgxBACECDNECCyADQRA2AhwgAyABNgIUIANBmBo2AhAgA0EVNgIMQQAhAgzQAgsgA0EgNgIcIAMgATYCFCADQaQcNgIQIANBFTYCDEEAIQIMzwILIANBCzYCHCADIAE2AhQgA0GkHDYCECADQRU2AgxBACECDM4CCyADQQw2AhwgAyABNgIUIANBpBw2AhAgA0EVNgIMQQAhAgzNAgtBACECIANBADYCHCADIAE2AhQgA0HdDjYCECADQRI2AgwMzAILAkADQAJAIAEtAABBCmsOBAACAgACCyAEIAFBAWoiAUcNAAtB/QEhAgzMAgsCQAJAIAMtADZBAUcNAEEAIQACQCADKAI4IgJFDQAgAigCYCICRQ0AIAMgAhEAACEACyAARQ0AIABBFUcNASADQfwBNgIcIAMgATYCFCADQdwZNgIQIANBFTYCDEEAIQIMzQILQdwBIQIMswILIANBADYCHCADIAE2AhQgA0H5CzYCECADQR82AgxBACECDMsCCwJAAkAgAy0AKEEBaw4CBAEAC0HbASECDLICC0HUASECDLECCyADQQI6ADFBACEAAkAgAygCOCICRQ0AIAIoAgAiAkUNACADIAIRAAAhAAsgAEUEQEHdASECDLECCyAAQRVHBEAgA0EANgIcIAMgATYCFCADQbQMNgIQIANBEDYCDEEAIQIMygILIANB+wE2AhwgAyABNgIUIANBgRo2AhAgA0EVNgIMQQAhAgzJAgsgASAERgRAQfoBIQIMyQILIAEtAABByABGDQEgA0EBOgAoC0HAASECDK4CC0HaASECDK0CCyABIARHBEAgA0EMNgIIIAMgATYCBEHZASECDK0CC0H5ASECDMUCCyABIARGBEBB+AEhAgzFAgsgAS0AAEHIAEcNBCABQQFqIQFB2AEhAgyrAgsgASAERgRAQfcBIQIMxAILAkACQCABLQAAQcUAaw4QAAUFBQUFBQUFBQUFBQUFAQULIAFBAWohAUHWASECDKsCCyABQQFqIQFB1wEhAgyqAgtB9gEhAiABIARGDcICIAMoAgAiACAEIAFraiEFIAEgAGtBAmohBgJAA0AgAS0AACAAQbrVAGotAABHDQMgAEECRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADMMCCyADKAIEIQAgA0IANwMAIAMgACAGQQFqIgEQLiIARQRAQeMBIQIMqgILIANB9QE2AhwgAyABNgIUIAMgADYCDEEAIQIMwgILQfQBIQIgASAERg3BAiADKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEG41QBqLQAARw0CIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzCAgsgA0GBBDsBKCADKAIEIQAgA0IANwMAIAMgACAGQQFqIgEQLiIADQMMAgsgA0EANgIAC0EAIQIgA0EANgIcIAMgATYCFCADQeUfNgIQIANBCDYCDAy/AgtB1QEhAgylAgsgA0HzATYCHCADIAE2AhQgAyAANgIMQQAhAgy9AgtBACEAAkAgAygCOCICRQ0AIAIoAkAiAkUNACADIAIRAAAhAAsgAEUNbiAAQRVHBEAgA0EANgIcIAMgATYCFCADQYIPNgIQIANBIDYCDEEAIQIMvQILIANBjwE2AhwgAyABNgIUIANB7Bs2AhAgA0EVNgIMQQAhAgy8AgsgASAERwRAIANBDTYCCCADIAE2AgRB0wEhAgyjAgtB8gEhAgy7AgsgASAERgRAQfEBIQIMuwILAkACQAJAIAEtAABByABrDgsAAQgICAgICAgIAggLIAFBAWohAUHQASECDKMCCyABQQFqIQFB0QEhAgyiAgsgAUEBaiEBQdIBIQIMoQILQfABIQIgASAERg25AiADKAIAIgAgBCABa2ohBiABIABrQQJqIQUDQCABLQAAIABBtdUAai0AAEcNBCAAQQJGDQMgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAY2AgAMuQILQe8BIQIgASAERg24AiADKAIAIgAgBCABa2ohBiABIABrQQFqIQUDQCABLQAAIABBs9UAai0AAEcNAyAAQQFGDQIgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAY2AgAMuAILQe4BIQIgASAERg23AiADKAIAIgAgBCABa2ohBiABIABrQQJqIQUDQCABLQAAIABBsNUAai0AAEcNAiAAQQJGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAY2AgAMtwILIAMoAgQhACADQgA3AwAgAyAAIAVBAWoiARArIgBFDQIgA0HsATYCHCADIAE2AhQgAyAANgIMQQAhAgy2AgsgA0EANgIACyADKAIEIQAgA0EANgIEIAMgACABECsiAEUNnAIgA0HtATYCHCADIAE2AhQgAyAANgIMQQAhAgy0AgtBzwEhAgyaAgtBACEAAkAgAygCOCICRQ0AIAIoAjQiAkUNACADIAIRAAAhAAsCQCAABEAgAEEVRg0BIANBADYCHCADIAE2AhQgA0HqDTYCECADQSY2AgxBACECDLQCC0HOASECDJoCCyADQesBNgIcIAMgATYCFCADQYAbNgIQIANBFTYCDEEAIQIMsgILIAEgBEYEQEHrASECDLICCyABLQAAQS9GBEAgAUEBaiEBDAELIANBADYCHCADIAE2AhQgA0GyODYCECADQQg2AgxBACECDLECC0HNASECDJcCCyABIARHBEAgA0EONgIIIAMgATYCBEHMASECDJcCC0HqASECDK8CCyABIARGBEBB6QEhAgyvAgsgAS0AAEEwayIAQf8BcUEKSQRAIAMgADoAKiABQQFqIQFBywEhAgyWAgsgAygCBCEAIANBADYCBCADIAAgARAvIgBFDZcCIANB6AE2AhwgAyABNgIUIAMgADYCDEEAIQIMrgILIAEgBEYEQEHnASECDK4CCwJAIAEtAABBLkYEQCABQQFqIQEMAQsgAygCBCEAIANBADYCBCADIAAgARAvIgBFDZgCIANB5gE2AhwgAyABNgIUIAMgADYCDEEAIQIMrgILQcoBIQIMlAILIAEgBEYEQEHlASECDK0CC0EAIQBBASEFQQEhB0EAIQICQAJAAkACQAJAAn8CQAJAAkACQAJAAkACQCABLQAAQTBrDgoKCQABAgMEBQYICwtBAgwGC0EDDAULQQQMBAtBBQwDC0EGDAILQQcMAQtBCAshAkEAIQVBACEHDAILQQkhAkEBIQBBACEFQQAhBwwBC0EAIQVBASECCyADIAI6ACsgAUEBaiEBAkACQCADLQAuQRBxDQACQAJAAkAgAy0AKg4DAQACBAsgB0UNAwwCCyAADQEMAgsgBUUNAQsgAygCBCEAIANBADYCBCADIAAgARAvIgBFDQIgA0HiATYCHCADIAE2AhQgAyAANgIMQQAhAgyvAgsgAygCBCEAIANBADYCBCADIAAgARAvIgBFDZoCIANB4wE2AhwgAyABNgIUIAMgADYCDEEAIQIMrgILIAMoAgQhACADQQA2AgQgAyAAIAEQLyIARQ2YAiADQeQBNgIcIAMgATYCFCADIAA2AgwMrQILQckBIQIMkwILQQAhAAJAIAMoAjgiAkUNACACKAJEIgJFDQAgAyACEQAAIQALAkAgAARAIABBFUYNASADQQA2AhwgAyABNgIUIANBpA02AhAgA0EhNgIMQQAhAgytAgtByAEhAgyTAgsgA0HhATYCHCADIAE2AhQgA0HQGjYCECADQRU2AgxBACECDKsCCyABIARGBEBB4QEhAgyrAgsCQCABLQAAQSBGBEAgA0EAOwE0IAFBAWohAQwBCyADQQA2AhwgAyABNgIUIANBmRE2AhAgA0EJNgIMQQAhAgyrAgtBxwEhAgyRAgsgASAERgRAQeABIQIMqgILAkAgAS0AAEEwa0H/AXEiAkEKSQRAIAFBAWohAQJAIAMvATQiAEGZM0sNACADIABBCmwiADsBNCAAQf7/A3EgAkH//wNzSw0AIAMgACACajsBNAwCC0EAIQIgA0EANgIcIAMgATYCFCADQZUeNgIQIANBDTYCDAyrAgsgA0EANgIcIAMgATYCFCADQZUeNgIQIANBDTYCDEEAIQIMqgILQcYBIQIMkAILIAEgBEYEQEHfASECDKkCCwJAIAEtAABBMGtB/wFxIgJBCkkEQCABQQFqIQECQCADLwE0IgBBmTNLDQAgAyAAQQpsIgA7ATQgAEH+/wNxIAJB//8Dc0sNACADIAAgAmo7ATQMAgtBACECIANBADYCHCADIAE2AhQgA0GVHjYCECADQQ02AgwMqgILIANBADYCHCADIAE2AhQgA0GVHjYCECADQQ02AgxBACECDKkCC0HFASECDI8CCyABIARGBEBB3gEhAgyoAgsCQCABLQAAQTBrQf8BcSICQQpJBEAgAUEBaiEBAkAgAy8BNCIAQZkzSw0AIAMgAEEKbCIAOwE0IABB/v8DcSACQf//A3NLDQAgAyAAIAJqOwE0DAILQQAhAiADQQA2AhwgAyABNgIUIANBlR42AhAgA0ENNgIMDKkCCyADQQA2AhwgAyABNgIUIANBlR42AhAgA0ENNgIMQQAhAgyoAgtBxAEhAgyOAgsgASAERgRAQd0BIQIMpwILAkACQAJAAkAgAS0AAEEKaw4XAgMDAAMDAwMDAwMDAwMDAwMDAwMDAwEDCyABQQFqDAULIAFBAWohAUHDASECDI8CCyABQQFqIQEgA0Evai0AAEEBcQ0IIANBADYCHCADIAE2AhQgA0GNCzYCECADQQ02AgxBACECDKcCCyADQQA2AhwgAyABNgIUIANBjQs2AhAgA0ENNgIMQQAhAgymAgsgASAERwRAIANBDzYCCCADIAE2AgRBASECDI0CC0HcASECDKUCCwJAAkADQAJAIAEtAABBCmsOBAIAAAMACyAEIAFBAWoiAUcNAAtB2wEhAgymAgsgAygCBCEAIANBADYCBCADIAAgARAtIgBFBEAgAUEBaiEBDAQLIANB2gE2AhwgAyAANgIMIAMgAUEBajYCFEEAIQIMpQILIAMoAgQhACADQQA2AgQgAyAAIAEQLSIADQEgAUEBagshAUHBASECDIoCCyADQdkBNgIcIAMgADYCDCADIAFBAWo2AhRBACECDKICC0HCASECDIgCCyADQS9qLQAAQQFxDQEgA0EANgIcIAMgATYCFCADQeQcNgIQIANBGTYCDEEAIQIMoAILIAEgBEYEQEHZASEC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IAFBAWohAUGeASECDOQBCyABQQFqIQFBnwEhAgzjAQtBtwEhAiABIARGDfsBIAMoAgAiACAEIAFraiEFIAEgAGtBA2ohBgJAA0AgAS0AACAAQezUAGotAABHDSggAEEDRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADPwBCyADQQA2AgAgBkEBaiEBQQ0MKAtBtgEhAiABIARGDfoBIAMoAgAiACAEIAFraiEFIAEgAGtBAmohBgJAA0AgAS0AACAAQaHVAGotAABHDScgAEECRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADPsBCyADQQA2AgAgBkEBaiEBQQwMJwtBtQEhAiABIARGDfkBIAMoAgAiACAEIAFraiEFIAEgAGtBAWohBgJAA0AgAS0AACAAQerUAGotAABHDSYgAEEBRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADPoBCyADQQA2AgAgBkEBaiEBQQMMJgtBtAEhAiABIARGDfgBIAMoAgAiACAEIAFraiEFIAEgAGtBAWohBgJAA0AgAS0AACAAQejUAGotAABHDSUgAEEBRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADPkBCyADQQA2AgAgBkEBaiEBQSYMJQsgASAERgRAQbMBIQIM+AELAkACQCABLQAAQdQAaw4CAAEnCyABQQFqIQFBmQEhAgzfAQsgAUEBaiEBQZoBIQIM3gELQbIBIQIgASAERg32ASADKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEHm1ABqLQAARw0jIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAz3AQsgA0EANgIAIAZBAWohAUEnDCMLQbEBIQIgASAERg31ASADKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEHk1ABqLQAARw0iIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAz2AQsgA0EANgIAIAZBAWohAUEcDCILQbABIQIgASAERg30ASADKAIAIgAgBCABa2ohBSABIABrQQVqIQYCQANAIAEtAAAgAEHe1ABqLQAARw0hIABBBUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAz1AQsgA0EANgIAIAZBAWohAUEGDCELQa8BIQIgASAERg3zASADKAIAIgAgBCABa2ohBSABIABrQQRqIQYCQANAIAEtAAAgAEHZ1ABqLQAARw0gIABBBEYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAz0AQsgA0EANgIAIAZBAWohAUEZDCALIAEgBEYEQEGuASECDPMBCwJAAkACQAJAIAEtAABBLWsOIwAkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJAEkJCQkJAIkJCQDJAsgAUEBaiEBQY4BIQIM3AELIAFBAWohAUGPASECDNsBCyABQQFqIQFBlAEhAgzaAQsgAUEBaiEBQZUBIQIM2QELQa0BIQIgASAERg3xASADKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEHX1ABqLQAARw0eIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzyAQsgA0EANgIAIAZBAWohAUELDB4LIAEgBEYEQEGsASECDPEBCwJAAkAgAS0AAEHBAGsOAwAgASALIAFBAWohAUGQASECDNgBCyABQQFqIQFBkwEhAgzXAQsgASAERgRAQasBIQIM8AELAkACQCABLQAAQcEAaw4PAB8fHx8fHx8fHx8fHx8BHwsgAUEBaiEBQZEBIQIM1wELIAFBAWohAUGSASECDNYBCyABIARGBEBBqgEhAgzvAQsgAS0AAEHMAEcNHCABQQFqIQFBCgwbC0GpASECIAEgBEYN7QEgAygCACIAIAQgAWtqIQUgASAAa0EFaiEGAkADQCABLQAAIABB0dQAai0AAEcNGiAAQQVGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM7gELIANBADYCACAGQQFqIQFBHgwaC0GoASECIAEgBEYN7AEgAygCACIAIAQgAWtqIQUgASAAa0EGaiEGAkADQCABLQAAIABBytQAai0AAEcNGSAAQQZGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM7QELIANBADYCACAGQQFqIQFBFQwZC0GnASECIAEgBEYN6wEgAygCACIAIAQgAWtqIQUgASAAa0ECaiEGAkADQCABLQAAIABBx9QAai0AAEcNGCAAQQJGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM7AELIANBADYCACAGQQFqIQFBFwwYC0GmASECIAEgBEYN6gEgAygCACIAIAQgAWtqIQUgASAAa0EFaiEGAkADQCABLQAAIABBwdQAai0AAEcNFyAAQQVGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM6wELIANBADYCACAGQQFqIQFBGAwXCyABIARGBEBBpQEhAgzqAQsCQAJAIAEtAABByQBrDgcAGRkZGRkBGQsgAUEBaiEBQYsBIQIM0QELIAFBAWohAUGMASECDNABC0GkASECIAEgBEYN6AEgAygCACIAIAQgAWtqIQUgASAAa0EBaiEGAkADQCABLQAAIABBptUAai0AAEcNFSAAQQFGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM6QELIANBADYCACAGQQFqIQFBCQwVC0GjASECIAEgBEYN5wEgAygCACIAIAQgAWtqIQUgASAAa0EBaiEGAkADQCABLQAAIABBpNUAai0AAEcNFCAAQQFGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM6AELIANBADYCACAGQQFqIQFBHwwUC0GiASECIAEgBEYN5gEgAygCACIAIAQgAWtqIQUgASAAa0ECaiEGAkADQCABLQAAIABBvtQAai0AAEcNEyAAQQJGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM5wELIANBADYCACAGQQFqIQFBAgwTC0GhASECIAEgBEYN5QEgAygCACIAIAQgAWtqIQUgASAAa0EBaiEGA0AgAS0AACAAQbzUAGotAABHDREgAEEBRg0CIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADOUBCyABIARGBEBBoAEhAgzlAQtBASABLQAAQd8ARw0RGiABQQFqIQFBhwEhAgzLAQsgA0EANgIAIAZBAWohAUGIASECDMoBC0GfASECIAEgBEYN4gEgAygCACIAIAQgAWtqIQUgASAAa0EIaiEGAkADQCABLQAAIABBhNUAai0AAEcNDyAAQQhGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM4wELIANBADYCACAGQQFqIQFBKQwPC0GeASECIAEgBEYN4QEgAygCACIAIAQgAWtqIQUgASAAa0EDaiEGAkADQCABLQAAIABBuNQAai0AAEcNDiAAQQNGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM4gELIANBADYCACAGQQFqIQFBLQwOCyABIARGBEBBnQEhAgzhAQsgAS0AAEHFAEcNDiABQQFqIQFBhAEhAgzHAQsgASAERgRAQZwBIQIM4AELAkACQCABLQAAQcwAaw4IAA8PDw8PDwEPCyABQQFqIQFBggEhAgzHAQsgAUEBaiEBQYMBIQIMxgELQZsBIQIgASAERg3eASADKAIAIgAgBCABa2ohBSABIABrQQRqIQYCQANAIAEtAAAgAEGz1ABqLQAARw0LIABBBEYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzfAQsgA0EANgIAIAZBAWohAUEjDAsLQZoBIQIgASAERg3dASADKAIAIgAgBCABa2ohBSABIABrQQJqIQYCQANAIAEtAAAgAEGw1ABqLQAARw0KIABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzeAQsgA0EANgIAIAZBAWohAUEADAoLIAEgBEYEQEGZASECDN0BCwJAAkAgAS0AAEHIAGsOCAAMDAwMDAwBDAsgAUEBaiEBQf0AIQIMxAELIAFBAWohAUGAASECDMMBCyABIARGBEBBmAEhAgzcAQsCQAJAIAEtAABBzgBrDgMACwELCyABQQFqIQFB/gAhAgzDAQsgAUEBaiEBQf8AIQIMwgELIAEgBEYEQEGXASECDNsBCyABLQAAQdkARw0IIAFBAWohAUEIDAcLQZYBIQIgASAERg3ZASADKAIAIgAgBCABa2ohBSABIABrQQNqIQYCQANAIAEtAAAgAEGs1ABqLQAARw0GIABBA0YNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzaAQsgA0EANgIAIAZBAWohAUEFDAYLQZUBIQIgASAERg3YASADKAIAIgAgBCABa2ohBSABIABrQQVqIQYCQANAIAEtAAAgAEGm1ABqLQAARw0FIABBBUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzZAQsgA0EANgIAIAZBAWohAUEWDAULQZQBIQIgASAERg3XASADKAIAIgAgBCABa2ohBSABIABrQQJqIQYCQANAIAEtAAAgAEGh1QBqLQAARw0EIABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzYAQsgA0EANgIAIAZBAWohAUEQDAQLIAEgBEYEQEGTASECDNcBCwJAAkAgAS0AAEHDAGsODAAGBgYGBgYGBgYGAQYLIAFBAWohAUH5ACECDL4BCyABQQFqIQFB+gAhAgy9AQtBkgEhAiABIARGDdUBIAMoAgAiACAEIAFraiEFIAEgAGtBBWohBgJAA0AgAS0AACAAQaDUAGotAABHDQIgAEEFRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADNYBCyADQQA2AgAgBkEBaiEBQSQMAgsgA0EANgIADAILIAEgBEYEQEGRASECDNQBCyABLQAAQcwARw0BIAFBAWohAUETCzoAKSADKAIEIQAgA0EANgIEIAMgACABEC4iAA0CDAELQQAhAiADQQA2AhwgAyABNgIUIANB/h82AhAgA0EGNgIMDNEBC0H4ACECDLcBCyADQZABNgIcIAMgATYCFCADIAA2AgxBACECDM8BC0EAIQACQCADKAI4IgJFDQAgAigCQCICRQ0AIAMgAhEAACEACyAARQ0AIABBFUYNASADQQA2AhwgAyABNgIUIANBgg82AhAgA0EgNgIMQQAhAgzOAQtB9wAhAgy0AQsgA0GPATYCHCADIAE2AhQgA0HsGzYCECADQRU2AgxBACECDMwBCyABIARGBEBBjwEhAgzMAQsCQCABLQAAQSBGBEAgAUEBaiEBDAELIANBADYCHCADIAE2AhQgA0GbHzYCECADQQY2AgxBACECDMwBC0ECIQIMsgELA0AgAS0AAEEgRw0CIAQgAUEBaiIBRw0AC0GOASECDMoBCyABIARGBEBBjQEhAgzKAQsCQCABLQAAQQlrDgRKAABKAAtB9QAhAgywAQsgAy0AKUEFRgRAQfYAIQIMsAELQfQAIQIMrwELIAEgBEYEQEGMASECDMgBCyADQRA2AgggAyABNgIEDAoLIAEgBEYEQEGLASECDMcBCwJAIAEtAABBCWsOBEcAAEcAC0HzACECDK0BCyABIARHBEAgA0EQNgIIIAMgATYCBEHxACECDK0BC0GKASECDMUBCwJAIAEgBEcEQANAIAEtAABBoNAAai0AACIAQQNHBEACQCAAQQFrDgJJAAQLQfAAIQIMrwELIAQgAUEBaiIBRw0AC0GIASECDMYBC0GIASECDMUBCyADQQA2AhwgAyABNgIUIANB2yA2AhAgA0EHNgIMQQAhAgzEAQsgASAERgRAQYkBIQIMxAELAkACQAJAIAEtAABBoNIAai0AAEEBaw4DRgIAAQtB8gAhAgysAQsgA0EANgIcIAMgATYCFCADQbQSNgIQIANBBzYCDEEAIQIMxAELQeoAIQIMqgELIAEgBEcEQCABQQFqIQFB7wAhAgyqAQtBhwEhAgzCAQsgBCABIgBGBEBBhgEhAgzCAQsgAC0AACIBQS9GBEAgAEEBaiEBQe4AIQIMqQELIAFBCWsiAkEXSw0BIAAhAUEBIAJ0QZuAgARxDUEMAQsgBCABIgBGBEBBhQEhAgzBAQsgAC0AAEEvRw0AIABBAWohAQwDC0EAIQIgA0EANgIcIAMgADYCFCADQdsgNgIQIANBBzYCDAy/AQsCQAJAAkACQAJAA0AgAS0AAEGgzgBqLQAAIgBBBUcEQAJAAkAgAEEBaw4IRwUGBwgABAEIC0HrACECDK0BCyABQQFqIQFB7QAhAgysAQsgBCABQQFqIgFHDQALQYQBIQIMwwELIAFBAWoMFAsgAygCBCEAIANBADYCBCADIAAgARAsIgBFDR4gA0HbADYCHCADIAE2AhQgAyAANgIMQQAhAgzBAQsgAygCBCEAIANBADYCBCADIAAgARAsIgBFDR4gA0HdADYCHCADIAE2AhQgAyAANgIMQQAhAgzAAQsgAygCBCEAIANBADYCBCADIAAgARAsIgBFDR4gA0H6ADYCHCADIAE2AhQgAyAANgIMQQAhAgy/AQsgA0EANgIcIAMgATYCFCADQfkPNgIQIANBBzYCDEEAIQIMvgELIAEgBEYEQEGDASECDL4BCwJAIAEtAABBoM4Aai0AAEEBaw4IPgQFBgAIAgMHCyABQQFqIQELQQMhAgyjAQsgAUEBagwNC0EAIQIgA0EANgIcIANB0RI2AhAgA0EHNgIMIAMgAUEBajYCFAy6AQsgAygCBCEAIANBADYCBCADIAAgARAsIgBFDRYgA0HbADYCHCADIAE2AhQgAyAANgIMQQAhAgy5AQsgAygCBCEAIANBADYCBCADIAAgARAsIgBFDRYgA0HdADYCHCADIAE2AhQgAyAANgIMQQAhAgy4AQsgAygCBCEAIANBADYCBCADIAAgARAsIgBFDRYgA0H6ADYCHCADIAE2AhQgAyAANgIMQQAhAgy3AQsgA0EANgIcIAMgATYCFCADQfkPNgIQIANBBzYCDEEAIQIMtgELQewAIQIMnAELIAEgBEYEQEGCASECDLUBCyABQQFqDAILIAEgBEYEQEGBASECDLQBCyABQQFqDAELIAEgBEYNASABQQFqCyEBQQQhAgyYAQtBgAEhAgywAQsDQCABLQAAQaDMAGotAAAiAEECRwRAIABBAUcEQEHpACECDJkBCwwxCyAEIAFBAWoiAUcNAAtB/wAhAgyvAQsgASAERgRAQf4AIQIMrwELAkAgAS0AAEEJaw43LwMGLwQGBgYGBgYGBgYGBgYGBgYGBgYFBgYCBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGAAYLIAFBAWoLIQFBBSECDJQBCyABQQFqDAYLIAMoAgQhACADQQA2AgQgAyAAIAEQLCIARQ0IIANB2wA2AhwgAyABNgIUIAMgADYCDEEAIQIMqwELIAMoAgQhACADQQA2AgQgAyAAIAEQLCIARQ0IIANB3QA2AhwgAyABNgIUIAMgADYCDEEAIQIMqgELIAMoAgQhACADQQA2AgQgAyAAIAEQLCIARQ0IIANB+gA2AhwgAyABNgIUIAMgADYCDEEAIQIMqQELIANBADYCHCADIAE2AhQgA0GNFDYCECADQQc2AgxBACECDKgBCwJAAkACQAJAA0AgAS0AAEGgygBqLQAAIgBBBUcEQAJAIABBAWsOBi4DBAUGAAYLQegAIQIMlAELIAQgAUEBaiIBRw0AC0H9ACECDKsBCyADKAIEIQAgA0EANgIEIAMgACABECwiAEUNByADQdsANgIcIAMgATYCFCADIAA2AgxBACECDKoBCyADKAIEIQAgA0EANgIEIAMgACABECwiAEUNByADQd0ANgIcIAMgATYCFCADIAA2AgxBACECDKkBCyADKAIEIQAgA0EANgIEIAMgACABECwiAEUNByADQfoANgIcIAMgATYCFCADIAA2AgxBACECDKgBCyADQQA2AhwgAyABNgIUIANB5Ag2AhAgA0EHNgIMQQAhAgynAQsgASAERg0BIAFBAWoLIQFBBiECDIwBC0H8ACECDKQBCwJAAkACQAJAA0AgAS0AAEGgyABqLQAAIgBBBUcEQCAAQQFrDgQpAgMEBQsgBCABQQFqIgFHDQALQfsAIQIMpwELIAMoAgQhACADQQA2AgQgAyAAIAEQLCIARQ0DIANB2wA2AhwgAyABNgIUIAMgADYCDEEAIQIMpgELIAMoAgQhACADQQA2AgQgAyAAIAEQLCIARQ0DIANB3QA2AhwgAyABNgIUIAMgADYCDEEAIQIMpQELIAMoAgQhACADQQA2AgQgAyAAIAEQLCIARQ0DIANB+gA2AhwgAyABNgIUIAMgADYCDEEAIQIMpAELIANBADYCHCADIAE2AhQgA0G8CjYCECADQQc2AgxBACECDKMBC0HPACECDIkBC0HRACECDIgBC0HnACECDIcBCyABIARGBEBB+gAhAgygAQsCQCABLQAAQQlrDgQgAAAgAAsgAUEBaiEBQeYAIQIMhgELIAEgBEYEQEH5ACECDJ8BCwJAIAEtAABBCWsOBB8AAB8AC0EAIQACQCADKAI4IgJFDQAgAigCOCICRQ0AIAMgAhEAACEACyAARQRAQeIBIQIMhgELIABBFUcEQCADQQA2AhwgAyABNgIUIANByQ02AhAgA0EaNgIMQQAhAgyfAQsgA0H4ADYCHCADIAE2AhQgA0HqGjYCECADQRU2AgxBACECDJ4BCyABIARHBEAgA0ENNgIIIAMgATYCBEHkACECDIUBC0H3ACECDJ0BCyABIARGBEBB9gAhAgydAQsCQAJAAkAgAS0AAEHIAGsOCwABCwsLCwsLCwsCCwsgAUEBaiEBQd0AIQIMhQELIAFBAWohAUHgACECDIQBCyABQQFqIQFB4wAhAgyDAQtB9QAhAiABIARGDZsBIAMoAgAiACAEIAFraiEFIAEgAGtBAmohBgJAA0AgAS0AACAAQbXVAGotAABHDQggAEECRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADJwBCyADKAIEIQAgA0IANwMAIAMgACAGQQFqIgEQKyIABEAgA0H0ADYCHCADIAE2AhQgAyAANgIMQQAhAgycAQtB4gAhAgyCAQtBACEAAkAgAygCOCICRQ0AIAIoAjQiAkUNACADIAIRAAAhAAsCQCAABEAgAEEVRg0BIANBADYCHCADIAE2AhQgA0HqDTYCECADQSY2AgxBACECDJwBC0HhACECDIIBCyADQfMANgIcIAMgATYCFCADQYAbNgIQIANBFTYCDEEAIQIMmgELIAMtACkiAEEja0ELSQ0JAkAgAEEGSw0AQQEgAHRBygBxRQ0ADAoLQQAhAiADQQA2AhwgAyABNgIUIANB7Qk2AhAgA0EINgIMDJkBC0HyACECIAEgBEYNmAEgAygCACIAIAQgAWtqIQUgASAAa0EBaiEGAkADQCABLQAAIABBs9UAai0AAEcNBSAAQQFGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAMmQELIAMoAgQhACADQgA3AwAgAyAAIAZBAWoiARArIgAEQCADQfEANgIcIAMgATYCFCADIAA2AgxBACECDJkBC0HfACECDH8LQQAhAAJAIAMoAjgiAkUNACACKAI0IgJFDQAgAyACEQAAIQALAkAgAARAIABBFUYNASADQQA2AhwgAyABNgIUIANB6g02AhAgA0EmNgIMQQAhAgyZAQtB3gAhAgx/CyADQfAANgIcIAMgATYCFCADQYAbNgIQIANBFTYCDEEAIQIMlwELIAMtAClBIUYNBiADQQA2AhwgAyABNgIUIANBkQo2AhAgA0EINgIMQQAhAgyWAQtB7wAhAiABIARGDZUBIAMoAgAiACAEIAFraiEFIAEgAGtBAmohBgJAA0AgAS0AACAAQbDVAGotAABHDQIgAEECRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADJYBCyADKAIEIQAgA0IANwMAIAMgACAGQQFqIgEQKyIARQ0CIANB7QA2AhwgAyABNgIUIAMgADYCDEEAIQIMlQELIANBADYCAAsgAygCBCEAIANBADYCBCADIAAgARArIgBFDYABIANB7gA2AhwgAyABNgIUIAMgADYCDEEAIQIMkwELQdwAIQIMeQtBACEAAkAgAygCOCICRQ0AIAIoAjQiAkUNACADIAIRAAAhAAsCQCAABEAgAEEVRg0BIANBADYCHCADIAE2AhQgA0HqDTYCECADQSY2AgxBACECDJMBC0HbACECDHkLIANB7AA2AhwgAyABNgIUIANBgBs2AhAgA0EVNgIMQQAhAgyRAQsgAy0AKSIAQSNJDQAgAEEuRg0AIANBADYCHCADIAE2AhQgA0HJCTYCECADQQg2AgxBACECDJABC0HaACECDHYLIAEgBEYEQEHrACECDI8BCwJAIAEtAABBL0YEQCABQQFqIQEMAQsgA0EANgIcIAMgATYCFCADQbI4NgIQIANBCDYCDEEAIQIMjwELQdkAIQIMdQsgASAERwRAIANBDjYCCCADIAE2AgRB2AAhAgx1C0HqACECDI0BCyABIARGBEBB6QAhAgyNAQsgAS0AAEEwayIAQf8BcUEKSQRAIAMgADoAKiABQQFqIQFB1wAhAgx0CyADKAIEIQAgA0EANgIEIAMgACABEC8iAEUNeiADQegANgIcIAMgATYCFCADIAA2AgxBACECDIwBCyABIARGBEBB5wAhAgyMAQsCQCABLQAAQS5GBEAgAUEBaiEBDAELIAMoAgQhACADQQA2AgQgAyAAIAEQLyIARQ17IANB5gA2AhwgAyABNgIUIAMgADYCDEEAIQIMjAELQdYAIQIMcgsgASAERgRAQeUAIQIMiwELQQAhAEEBIQVBASEHQQAhAgJAAkACQAJAAkACfwJAAkACQAJAAkACQAJAIAEtAABBMGsOCgoJAAECAwQFBggLC0ECDAYLQQMMBQtBBAwEC0EFDAMLQQYMAgtBBwwBC0EICyECQQAhBUEAIQcMAgtBCSECQQEhAEEAIQVBACEHDAELQQAhBUEBIQILIAMgAjoAKyABQQFqIQECQAJAIAMtAC5BEHENAAJAAkACQCADLQAqDgMBAAIECyAHRQ0DDAILIAANAQwCCyAFRQ0BCyADKAIEIQAgA0EANgIEIAMgACABEC8iAEUNAiADQeIANgIcIAMgATYCFCADIAA2AgxBACECDI0BCyADKAIEIQAgA0EANgIEIAMgACABEC8iAEUNfSADQeMANgIcIAMgATYCFCADIAA2AgxBACECDIwBCyADKAIEIQAgA0EANgIEIAMgACABEC8iAEUNeyADQeQANgIcIAMgATYCFCADIAA2AgwMiwELQdQAIQIMcQsgAy0AKUEiRg2GAUHTACECDHALQQAhAAJAIAMoAjgiAkUNACACKAJEIgJFDQAgAyACEQAAIQALIABFBEBB1QAhAgxwCyAAQRVHBEAgA0EANgIcIAMgATYCFCADQaQNNgIQIANBITYCDEEAIQIMiQELIANB4QA2AhwgAyABNgIUIANB0Bo2AhAgA0EVNgIMQQAhAgyIAQsgASAERgRAQeAAIQIMiAELAkACQAJAAkACQCABLQAAQQprDgQBBAQABAsgAUEBaiEBDAELIAFBAWohASADQS9qLQAAQQFxRQ0BC0HSACECDHALIANBADYCHCADIAE2AhQgA0G2ETYCECADQQk2AgxBACECDIgBCyADQQA2AhwgAyABNgIUIANBthE2AhAgA0EJNgIMQQAhAgyHAQsgASAERgRAQd8AIQIMhwELIAEtAABBCkYEQCABQQFqIQEMCQsgAy0ALkHAAHENCCADQQA2AhwgAyABNgIUIANBthE2AhAgA0ECNgIMQQAhAgyGAQsgASAERgRAQd0AIQIMhgELIAEtAAAiAkENRgRAIAFBAWohAUHQACECDG0LIAEhACACQQlrDgQFAQEFAQsgBCABIgBGBEBB3AAhAgyFAQsgAC0AAEEKRw0AIABBAWoMAgtBACECIANBADYCHCADIAA2AhQgA0HKLTYCECADQQc2AgwMgwELIAEgBEYEQEHbACECDIMBCwJAIAEtAABBCWsOBAMAAAMACyABQQFqCyEBQc4AIQIMaAsgASAERgRAQdoAIQIMgQELIAEtAABBCWsOBAABAQABC0EAIQIgA0EANgIcIANBmhI2AhAgA0EHNgIMIAMgAUEBajYCFAx/CyADQYASOwEqQQAhAAJAIAMoAjgiAkUNACACKAI4IgJFDQAgAyACEQAAIQALIABFDQAgAEEVRw0BIANB2QA2AhwgAyABNgIUIANB6ho2AhAgA0EVNgIMQQAhAgx+C0HNACECDGQLIANBADYCHCADIAE2AhQgA0HJDTYCECADQRo2AgxBACECDHwLIAEgBEYEQEHZACECDHwLIAEtAABBIEcNPSABQQFqIQEgAy0ALkEBcQ09IANBADYCHCADIAE2AhQgA0HCHDYCECADQR42AgxBACECDHsLIAEgBEYEQEHYACECDHsLAkACQAJAAkACQCABLQAAIgBBCmsOBAIDAwABCyABQQFqIQFBLCECDGULIABBOkcNASADQQA2AhwgAyABNgIUIANB5xE2AhAgA0EKNgIMQQAhAgx9CyABQQFqIQEgA0Evai0AAEEBcUUNcyADLQAyQYABcUUEQCADQTJqIQIgAxA1QQAhAAJAIAMoAjgiBkUNACAGKAIoIgZFDQAgAyAGEQAAIQALAkACQCAADhZNTEsBAQEBAQEBAQEBAQEBAQEBAQEAAQsgA0EpNgIcIAMgATYCFCADQawZNgIQIANBFTYCDEEAIQIMfgsg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c3BvbnNlIHN0YXR1cwBFeHBlY3RlZCBMRiBhZnRlciBoZWFkZXJzAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMAVXNlciBjYWxsYmFjayBlcnJvcgBgb25fcmVzZXRgIGNhbGxiYWNrIGVycm9yAGBvbl9jaHVua19oZWFkZXJgIGNhbGxiYWNrIGVycm9yAGBvbl9tZXNzYWdlX2JlZ2luYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlYCBjYWxsYmFjayBlcnJvcgBgb25fc3RhdHVzX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fdmVyc2lvbl9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX3VybF9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX3Byb3RvY29sX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9oZWFkZXJfdmFsdWVfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9tZXNzYWdlX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fbWV0aG9kX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25faGVhZGVyX2ZpZWxkX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfZXh0ZW5zaW9uX25hbWVgIGNhbGxiYWNrIGVycm9yAFVuZXhwZWN0ZWQgY2hhciBpbiB1cmwgc2VydmVyAEludmFsaWQgaGVhZGVyIHZhbHVlIGNoYXIASW52YWxpZCBoZWFkZXIgZmllbGQgY2hhcgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3ZlcnNpb24ASW52YWxpZCBtaW5vciB2ZXJzaW9uAEludmFsaWQgbWFqb3IgdmVyc2lvbgBFeHBlY3RlZCBzcGFjZSBhZnRlciB2ZXJzaW9uAEV4cGVjdGVkIENSTEYgYWZ0ZXIgdmVyc2lvbgBJbnZhbGlkIEhUVFAgdmVyc2lvbgBJbnZhbGlkIGhlYWRlciB0b2tlbgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3VybABJbnZhbGlkIGNoYXJhY3RlcnMgaW4gdXJsAFVuZXhwZWN0ZWQgc3RhcnQgY2hhciBpbiB1cmwARG91YmxlIEAgaW4gdXJsAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fcHJvdG9jb2wARW1wdHkgQ29udGVudC1MZW5ndGgASW52YWxpZCBjaGFyYWN0ZXIgaW4gQ29udGVudC1MZW5ndGgAVHJhbnNmZXItRW5jb2RpbmcgY2FuJ3QgYmUgcHJlc2VudCB3aXRoIENvbnRlbnQtTGVuZ3RoAER1cGxpY2F0ZSBDb250ZW50LUxlbmd0aABJbnZhbGlkIGNoYXIgaW4gdXJsIHBhdGgAQ29udGVudC1MZW5ndGggY2FuJ3QgYmUgcHJlc2VudCB3aXRoIFRyYW5zZmVyLUVuY29kaW5nAE1pc3NpbmcgZXhwZWN0ZWQgQ1IgYWZ0ZXIgY2h1bmsgc2l6ZQBFeHBlY3RlZCBMRiBhZnRlciBjaHVuayBzaXplAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIHNpemUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfdmFsdWUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9jaHVua19leHRlbnNpb25fdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyB2YWx1ZQBVbmV4cGVjdGVkIHdoaXRlc3BhY2UgYWZ0ZXIgaGVhZGVyIHZhbHVlAE1pc3NpbmcgZXhwZWN0ZWQgQ1IgYWZ0ZXIgaGVhZGVyIHZhbHVlAE1pc3NpbmcgZXhwZWN0ZWQgTEYgYWZ0ZXIgaGVhZGVyIHZhbHVlAEludmFsaWQgYFRyYW5zZmVyLUVuY29kaW5nYCBoZWFkZXIgdmFsdWUATWlzc2luZyBleHBlY3RlZCBDUiBhZnRlciBjaHVuayBleHRlbnNpb24gdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyBxdW90ZSB2YWx1ZQBJbnZhbGlkIHF1b3RlZC1wYWlyIGluIGNodW5rIGV4dGVuc2lvbnMgcXVvdGVkIHZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgcXVvdGVkIHZhbHVlAFBhdXNlZCBieSBvbl9oZWFkZXJzX2NvbXBsZXRlAEludmFsaWQgRU9GIHN0YXRlAG9uX3Jlc2V0IHBhdXNlAG9uX2NodW5rX2hlYWRlciBwYXVzZQBvbl9tZXNzYWdlX2JlZ2luIHBhdXNlAG9uX2NodW5rX2V4dGVuc2lvbl92YWx1ZSBwYXVzZQBvbl9zdGF0dXNfY29tcGxldGUgcGF1c2UAb25fdmVyc2lvbl9jb21wbGV0ZSBwYXVzZQBvbl91cmxfY29tcGxldGUgcGF1c2UAb25fcHJvdG9jb2xfY29tcGxldGUgcGF1c2UAb25fY2h1bmtfY29tcGxldGUgcGF1c2UAb25faGVhZGVyX3ZhbHVlX2NvbXBsZXRlIHBhdXNlAG9uX21lc3NhZ2VfY29tcGxldGUgcGF1c2UAb25fbWV0aG9kX2NvbXBsZXRlIHBhdXNlAG9uX2hlYWRlcl9maWVsZF9jb21wbGV0ZSBwYXVzZQBvbl9jaHVua19leHRlbnNpb25fbmFtZSBwYXVzZQBVbmV4cGVjdGVkIHNwYWNlIGFmdGVyIHN0YXJ0IGxpbmUATWlzc2luZyBleHBlY3RlZCBDUiBhZnRlciByZXNwb25zZSBsaW5lAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fY2h1bmtfZXh0ZW5zaW9uX25hbWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyBuYW1lAE1pc3NpbmcgZXhwZWN0ZWQgQ1IgYWZ0ZXIgY2h1bmsgZXh0ZW5zaW9uIG5hbWUASW52YWxpZCBzdGF0dXMgY29kZQBQYXVzZSBvbiBDT05ORUNUL1VwZ3JhZGUAUGF1c2Ugb24gUFJJL1VwZ3JhZGUARXhwZWN0ZWQgSFRUUC8yIENvbm5lY3Rpb24gUHJlZmFjZQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX21ldGhvZABFeHBlY3RlZCBzcGFjZSBhZnRlciBtZXRob2QAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfZmllbGQAUGF1c2VkAEludmFsaWQgd29yZCBlbmNvdW50ZXJlZABJbnZhbGlkIG1ldGhvZCBlbmNvdW50ZXJlZABNaXNzaW5nIGV4cGVjdGVkIENSIGFmdGVyIGNodW5rIGRhdGEARXhwZWN0ZWQgTEYgYWZ0ZXIgY2h1bmsgZGF0YQBVbmV4cGVjdGVkIGNoYXIgaW4gdXJsIHNjaGVtYQBSZXF1ZXN0IGhhcyBpbnZhbGlkIGBUcmFuc2Zlci1FbmNvZGluZ2AARGF0YSBhZnRlciBgQ29ubmVjdGlvbjogY2xvc2VgAFNXSVRDSF9QUk9YWQBVU0VfUFJPWFkATUtBQ1RJVklUWQBVTlBST0NFU1NBQkxFX0VOVElUWQBRVUVSWQBDT1BZAE1PVkVEX1BFUk1BTkVOVExZAFRPT19FQVJMWQBOT1RJRlkARkFJTEVEX0RFUEVOREVOQ1kAQkFEX0dBVEVXQVkAUExBWQBQVVQAQ0hFQ0tPVVQAR0FURVdBWV9USU1FT1VUAFJFUVVFU1RfVElNRU9VVABORVRXT1JLX0NPTk5FQ1RfVElNRU9VVABDT05ORUNUSU9OX1RJTUVPVVQATE9HSU5fVElNRU9VVABORVRXT1JLX1JFQURfVElNRU9VVABQT1NUAE1JU0RJUkVDVEVEX1JFUVVFU1QAQ0xJRU5UX0NMT1NFRF9SRVFVRVNUAENMSUVOVF9DTE9TRURfTE9BRF9CQUxBTkNFRF9SRVFVRVNUAEJBRF9SRVFVRVNUAEhUVFBfUkVRVUVTVF9TRU5UX1RPX0hUVFBTX1BPUlQAUkVQT1JUAElNX0FfVEVBUE9UAFJFU0VUX0NPTlRFTlQATk9fQ09OVEVOVABQQVJUSUFMX0NPTlRFTlQASFBFX0lOVkFMSURfQ09OU1RBTlQASFBFX0NCX1JFU0VUAEdFVABIUEVfU1RSSUNUAENPTkZMSUNUAFRFTVBPUkFSWV9SRURJUkVDVABQRVJNQU5FTlRfUkVESVJFQ1QAQ09OTkVDVABNVUxUSV9TVEFUVVMASFBFX0lOVkFMSURfU1RBVFVTAFRPT19NQU5ZX1JFUVVFU1RTAEVBUkxZX0hJTlRTAFVOQVZBSUxBQkxFX0ZPUl9MRUdBTF9SRUFTT05TAE9QVElPTlMAU1dJVENISU5HX1BST1RPQ09MUwBWQVJJQU5UX0FMU09fTkVHT1RJQVRFUwBNVUxUSVBMRV9DSE9JQ0VTAElOVEVSTkFMX1NFUlZFUl9FUlJPUgBXRUJfU0VSVkVSX1VOS05PV05fRVJST1IAUkFJTEdVTl9FUlJPUgBJREVOVElUWV9QUk9WSURFUl9BVVRIRU5USUNBVElPTl9FUlJPUgBTU0xfQ0VSVElGSUNBVEVfRVJST1IASU5WQUxJRF9YX0ZPUldBUkRFRF9GT1IAU0VUX1BBUkFNRVRFUgBHRVRfUEFSQU1FVEVSAEhQRV9VU0VSAFNFRV9PVEhFUgBIUEVfQ0JfQ0hVTktfSEVBREVSAEV4cGVjdGVkIExGIGFmdGVyIENSAE1LQ0FMRU5EQVIAU0VUVVAAV0VCX1NFUlZFUl9JU19ET1dOAFRFQVJET1dOAEhQRV9DTE9TRURfQ09OTkVDVElPTgBIRVVSSVNUSUNfRVhQSVJBVElPTgBESVNDT05ORUNURURfT1BFUkFUSU9OAE5PTl9BVVRIT1JJVEFUSVZFX0lORk9STUFUSU9OAEhQRV9JTlZBTElEX1ZFUlNJT04ASFBFX0NCX01FU1NBR0VfQkVHSU4AU0lURV9JU19GUk9aRU4ASFBFX0lOVkFMSURfSEVBREVSX1RPS0VOAElOVkFMSURfVE9LRU4ARk9SQklEREVOAEVOSEFOQ0VfWU9VUl9DQUxNAEhQRV9JTlZBTElEX1VSTABCTE9DS0VEX0JZX1BBUkVOVEFMX0NPTlRST0wATUtDT0wAQUNMAEhQRV9JTlRFUk5BTABSRVFVRVNUX0hFQURFUl9GSUVMRFNfVE9PX0xBUkdFX1VOT0ZGSUNJQUwASFBFX09LAFVOTElOSwBVTkxPQ0sAUFJJAFJFVFJZX1dJVEgASFBFX0lOVkFMSURfQ09OVEVOVF9MRU5HVEgASFBFX1VORVhQRUNURURfQ09OVEVOVF9MRU5HVEgARkxVU0gAUFJPUFBBVENIAE0tU0VBUkNIAFVSSV9UT09fTE9ORwBQUk9DRVNTSU5HAE1JU0NFTExBTkVPVVNfUEVSU0lTVEVOVF9XQVJOSU5HAE1JU0NFTExBTkVPVVNfV0FSTklORwBIUEVfSU5WQUxJRF9UUkFOU0ZFUl9FTkNPRElORwBFeHBlY3RlZCBDUkxGAEhQRV9JTlZBTElEX0NIVU5LX1NJWkUATU9WRQBDT05USU5VRQBIUEVfQ0JfU1RBVFVTX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJTX0NPTVBMRVRFAEhQRV9DQl9WRVJTSU9OX0NPTVBMRVRFAEhQRV9DQl9VUkxfQ09NUExFVEUASFBFX0NCX1BST1RPQ09MX0NPTVBMRVRFAEhQRV9DQl9DSFVOS19DT01QTEVURQBIUEVfQ0JfSEVBREVSX1ZBTFVFX0NPTVBMRVRFAEhQRV9DQl9DSFVOS19FWFRFTlNJT05fVkFMVUVfQ09NUExFVEUASFBFX0NCX0NIVU5LX0VYVEVOU0lPTl9OQU1FX0NPTVBMRVRFAEhQRV9DQl9NRVNTQUdFX0NPTVBMRVRFAEhQRV9DQl9NRVRIT0RfQ09NUExFVEUASFBFX0NCX0hFQURFUl9GSUVMRF9DT01QTEVURQBERUxFVEUASFBFX0lOVkFMSURfRU9GX1NUQVRFAElOVkFMSURfU1NMX0NFUlRJRklDQVRFAFBBVVNFAE5PX1JFU1BPTlNFAFVOU1VQUE9SVEVEX01FRElBX1RZUEUAR09ORQBOT1RfQUNDRVBUQUJMRQBTRVJWSUNFX1VOQVZBSUxBQkxFAFJBTkdFX05PVF9TQVRJU0ZJQUJMRQBPUklHSU5fSVNfVU5SRUFDSEFCTEUAUkVTUE9OU0VfSVNfU1RBTEUAUFVSR0UATUVSR0UAUkVRVUVTVF9IRUFERVJfRklFTERTX1RPT19MQVJHRQBSRVFVRVNUX0hFQURFUl9UT09fTEFSR0UAUEFZTE9BRF9UT09fTEFSR0UASU5TVUZGSUNJRU5UX1NUT1JBR0UASFBFX1BBVVNFRF9VUEdSQURFAEhQRV9QQVVTRURfSDJfVVBHUkFERQBTT1VSQ0UAQU5OT1VOQ0UAVFJBQ0UASFBFX1VORVhQRUNURURfU1BBQ0UAREVTQ1JJQkUAVU5TVUJTQ1JJQkUAUkVDT1JEAEhQRV9JTlZBTElEX01FVEhPRABOT1RfRk9VTkQAUFJPUEZJTkQAVU5CSU5EAFJFQklORABVTkFVVEhPUklaRUQATUVUSE9EX05PVF9BTExPV0VEAEhUVFBfVkVSU0lPTl9OT1RfU1VQUE9SVEVEAEFMUkVBRFlfUkVQT1JURUQAQUNDRVBURUQATk9UX0lNUExFTUVOVEVEAExPT1BfREVURUNURUQASFBFX0NSX0VYUEVDVEVEAEhQRV9MRl9FWFBFQ1RFRABDUkVBVEVEAElNX1VTRUQASFBFX1BBVVNFRABUSU1FT1VUX09DQ1VSRUQAUEFZTUVOVF9SRVFVSVJFRABQUkVDT05ESVRJT05fUkVRVUlSRUQAUFJPWFlfQVVUSEVOVElDQVRJT05fUkVRVUlSRUQATkVUV09SS19BVVRIRU5USUNBVElPTl9SRVFVSVJFRABMRU5HVEhfUkVRVUlSRUQAU1NMX0NFUlRJRklDQVRFX1JFUVVJUkVEAFVQR1JBREVfUkVRVUlSRUQAUEFHRV9FWFBJUkVEAFBSRUNPTkRJVElPTl9GQUlMRUQARVhQRUNUQVRJT05fRkFJTEVEAFJFVkFMSURBVElPTl9GQUlMRUQAU1NMX0hBTkRTSEFLRV9GQUlMRUQATE9DS0VEAFRSQU5TRk9STUFUSU9OX0FQUExJRUQATk9UX01PRElGSUVEAE5PVF9FWFRFTkRFRABCQU5EV0lEVEhfTElNSVRfRVhDRUVERUQAU0lURV9JU19PVkVSTE9BREVEAEhFQUQARXhwZWN0ZWQgSFRUUC8sIFJUU1AvIG9yIElDRS8A5xUAAK8VAACkEgAAkhoAACYWAACeFAAA2xkAAHkVAAB+EgAA/hQAADYVAAALFgAA2BYAAPMSAABCGAAArBYAABIVAAAUFwAA7xcAAEgUAABxFwAAshoAAGsZAAB+GQAANRQAAIIaAABEFwAA/RYAAB4YAACHFwAAqhkAAJMSAAAHGAAALBcAAMoXAACkFwAA5xUAAOcVAABYFwAAOxgAAKASAAAtHAAAwxEAAEgRAADeEgAAQhMAAKQZAAD9EAAA9xUAAKUVAADvFgAA+BkAAEoWAABWFgAA9RUAAAoaAAAIGgAAARoAAKsVAABCEgAA1xAAAEwRAAAFGQAAVBYAAB4RAADKGQAAyBkAAE4WAAD/GAAAcRQAAPAVAADuFQAAlBkAAPwVAAC/GQAAmxkAAHwUAABDEQAAcBgAAJUUAAAnFAAAGRQAANUSAADUGQAARBYAAPcQAEG5OwsBAQBB0DsL4AEBAQIBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQBBuj0LBAEAAAIAQdE9C14DBAMDAwMDAAADAwADAwADAwMDAwMDAwMDAAUAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAwADAEG6PwsEAQAAAgBB0T8LXgMAAwMDAwMAAAMDAAMDAAMDAwMDAwMDAwMABAAFAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwADAAMAQbDBAAsNbG9zZWVlcC1hbGl2ZQBBycEACwEBAEHgwQAL4AEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQBBycMACwEBAEHgwwAL5wEBAQEBAQEBAQEBAQECAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAWNodW5rZWQAQfHFAAteAQABAQEBAQAAAQEAAQEAAQEBAQEBAQEBAQAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEAAQBB0McACyFlY3Rpb25lbnQtbGVuZ3Rob25yb3h5LWNvbm5lY3Rpb24AQYDIAAsgcmFuc2Zlci1lbmNvZGluZ3BncmFkZQ0KDQpTTQ0KDQoAQanIAAsFAQIAAQMAQcDIAAtfBAUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUAQanKAAsFAQIAAQMAQcDKAAtfBAUFBgUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUAQanMAAsEAQAAAQBBwcwAC14CAgACAgICAgICAgICAgICAgICAgICAgICAgICAgIAAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAEGpzgALBQECAAEDAEHAzgALXwQFAAAFBQUFBQUFBQUFBQYFBQUFBQUFBQUFBQUABQAHCAUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQAFAAUABQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUAAAAFAEGp0AALBQEBAAEBAEHA0AALAQEAQdrQAAtBAgAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAQanSAAsFAQEAAQEAQcDSAAsBAQBBytIACwYCAAAAAAIAQeHSAAs6AwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwBBoNQAC50BTk9VTkNFRUNLT1VUTkVDVEVURUNSSUJFTFVTSEVURUFEU0VBUkNIUkdFQ1RJVklUWUxFTkRBUlZFT1RJRllQVElPTlNDSFNFQVlTVEFUQ0hHRVVFUllPUkRJUkVDVE9SVFJDSFBBUkFNRVRFUlVSQ0VCU0NSSUJFQVJET1dOQUNFSU5ETktDS1VCU0NSSUJFVFRQQ0VUU1BBRFRQLw==' - -let wasmBuffer + onRequestUpgrade (...args) { + assert(!this.#onCompleteCalled) + assert(!this.#onErrorCalled) -Object.defineProperty(module, 'exports', { - get: () => { - return wasmBuffer - ? wasmBuffer - : (wasmBuffer = Buffer.from(wasmBase64, 'base64')) + return this.#handler.onRequestUpgrade?.(...args) } -}) - - -/***/ }), - -/***/ 7361: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -"use strict"; -/* module decorator */ module = __nccwpck_require__.nmd(module); + onResponseStart (...args) { + assert(!this.#onCompleteCalled) + assert(!this.#onErrorCalled) + assert(!this.#onResponseStartCalled) -const { Buffer } = __nccwpck_require__(4573) + this.#onResponseStartCalled = true -const wasmBase64 = 'AGFzbQEAAAABJwdgAX8Bf2ADf39/AX9gAn9/AGABfwBgBH9/f38Bf2AAAGADf39/AALLAQgDZW52GHdhc21fb25faGVhZGVyc19jb21wbGV0ZQAEA2VudhV3YXNtX29uX21lc3NhZ2VfYmVnaW4AAANlbnYLd2FzbV9vbl91cmwAAQNlbnYOd2FzbV9vbl9zdGF0dXMAAQNlbnYUd2FzbV9vbl9oZWFkZXJfZmllbGQAAQNlbnYUd2FzbV9vbl9oZWFkZXJfdmFsdWUAAQNlbnYMd2FzbV9vbl9ib2R5AAEDZW52GHdhc21fb25fbWVzc2FnZV9jb21wbGV0ZQAAAzU0BQYAAAMAAAAAAAADAQMAAwMDAAACAAAAAAICAgICAgICAgIBAQEBAQEBAQEBAwAAAwAAAAQFAXABExMFAwEAAgYIAX8BQcDZBAsHxQcoBm1lbW9yeQIAC19pbml0aWFsaXplAAgZX19pbmRpcmVjdF9mdW5jdGlvbl90YWJsZQEAC2xsaHR0cF9pbml0AAkYbGxodHRwX3Nob3VsZF9rZWVwX2FsaXZlADcMbGxodHRwX2FsbG9jAAsGbWFsbG9jADkLbGxodHRwX2ZyZWUADARmcmVlAAwPbGxodHRwX2dldF90eXBlAA0VbGxodHRwX2dldF9odHRwX21ham9yAA4VbGxodHRwX2dldF9odHRwX21pbm9yAA8RbGxodHRwX2dldF9tZXRob2QAEBZsbGh0dHBfZ2V0X3N0YXR1c19jb2RlABESbGxodHRwX2dldF91cGdyYWRlABIMbGxodHRwX3Jlc2V0ABMObGxodHRwX2V4ZWN1dGUAFBRsbGh0dHBfc2V0dGluZ3NfaW5pdAAVDWxsaHR0cF9maW5pc2gAFgxsbGh0dHBfcGF1c2UAFw1sbGh0dHBfcmVzdW1lABgbbGxodHRwX3Jlc3VtZV9hZnRlcl91cGdyYWRlABkQbGxodHRwX2dldF9lcnJubwAaF2xsaHR0cF9nZXRfZXJyb3JfcmVhc29uABsXbGxodHRwX3NldF9lcnJvcl9yZWFzb24AHBRsbGh0dHBfZ2V0X2Vycm9yX3BvcwAdEWxsaHR0cF9lcnJub19uYW1lAB4SbGxodHRwX21ldGhvZF9uYW1lAB8SbGxodHRwX3N0YXR1c19uYW1lACAabGxodHRw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AXRrQT5qIQILIAEgAjYCHCABQgA3AhAgAkECdEH01wBqIQACQEHI1QAoAgAiA0EBIAJ0IgdxRQRAIAAgATYCAEHI1QAgAyAHcjYCACABIAA2AhggASABNgIIIAEgATYCDAwBCyAEQRkgAkEBdmtBACACQR9HG3QhAiAAKAIAIQACQANAIAAiAygCBEF4cSAERg0BIAJBHXYhACACQQF0IQIgAyAAQQRxakEQaiIHKAIAIgANAAsgByABNgIAIAEgAzYCGCABIAE2AgwgASABNgIIDAELIAMoAggiACABNgIMIAMgATYCCCABQQA2AhggASADNgIMIAEgADYCCAtB5NUAQeTVACgCAEEBayIAQX8gABs2AgALCwcAIAAtACgLBwAgAC0AKgsHACAALQArCwcAIAAtACkLBwAgAC8BNAsHACAALQAwC0ABBH8gACgCGCEBIAAvAS4hAiAALQAoIQMgACgCOCEEIAAQOCAAIAQ2AjggACADOgAoIAAgAjsBLiAAIAE2AhgLhocCAwd/A34BeyABIAJqIQQCQCAAIgMoAgwiAA0AIAMoAgQEQCADIAE2AgQLIwBBEGsiCSQAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAC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DAgLQeMBDAcLQdcBDAYLQdgBDAULQdkBDAQLQdoBDAMLQdsBDAILQd0BDAELQdwBCyECA0ACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIAMCfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACfwJAAkACQAJAAkACQAJAAn8CQAJAAkACfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgAwJ/AkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJ/AkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAC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A0EXNgIcIAMgADYCDCADIAFBAWo2AhQM+AILIABBFUYNI0EAIQIgA0EANgIcIAMgATYCFCADQdYMNgIQIANBIzYCDAz3AgsgAygCBCEAQQAhAiADQQA2AgQgAyAAIAEQNCIARQRAIAFBAWohAQwdCyADQRk2AhwgAyAANgIMIAMgAUEBajYCFAz2AgsgAygCBCEAQQAhAiADQQA2AgQgAyAAIAEQNCIARQRAIAFBAWohAQzvAgsgA0EaNgIcIAMgADYCDCADIAFBAWo2AhQM9QILIABBFUYNH0EAIQIgA0EANgIcIAMgATYCFCADQdAPNgIQIANBIjYCDAz0AgsgAygCBCEAIANBADYCBCADIAAgARAzIgBFBEAgAUEBaiEBDBsLIANBHDYCHCADIAA2AgwgAyABQQFqNgIUQQAhAgzzAgsgAygCBCEAIANBADYCBCADIAAgARAzIgBFBEAgAUEBaiEBDOsCCyADQR02AhwgAyAANgIMIAMgAUEBajYCFEEAIQIM8gILIABBO0cNASABQQFqIQELQSYhAgzXAgtBACECIANBADYCHCADIAE2AhQgA0GfFTYCECADQQw2AgwM7wILIAEgBEcEQANAIAEtAABBIEcNhAIgBCABQQFqIgFHDQALQSwhAgzvAgtBLCECDO4CCyABIARGBEBBNCECDO4CCwJAAkADQAJAIAEtAABBCmsOBAIAAAMACyAEIAFBAWoiAUcNAAtBNCECDO8CCyADKAIEIQAgA0EANgIEIAMgACABEDEiAEUNnwIgA0EyNgIcIAMgATYCFCADIAA2AgxBACECDO4CCyADKAIEIQAgA0EANgIEIAMgACABEDEiAEUEQCABQQFqIQEMnwILIANBMjYCHCADIAA2AgwgAyABQQFqNgIUQQAhAgztAgsgASAERwRAAkADQCABLQAAQTBrIgBB/wFxQQpPBEBBOiECDNcCCyADKQMgIgtCmbPmzJmz5swZVg0BIAMgC0IKfiIKNwMgIAogAK1C/wGDIgtCf4VWDQEgAyAKIAt8NwMgIAQgAUEBaiIBRw0AC0HAACECDO4CCyADKAIEIQAgA0EANgIEIAMgACABQQFqIgEQMSIADRcM4gILQcAAIQIM7AILIAEgBEYEQEHJACECDOwCCwJAA0ACQCABLQAAQQlrDhgAAqICogKpAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAgCiAgsgBCABQQFqIgFHDQALQckAIQIM7AILIAFBAWohASADQS9qLQAAQQFxDaUCIANBADYCHCADIAE2AhQgA0GXEDYCECADQQo2AgxBACECDOsCCyABIARHBEADQCABLQAAQSBHDRUgBCABQQFqIgFHDQALQfgAIQIM6wILQfgAIQIM6gILIANBAjoAKAw4C0EAIQIgA0EANgIcIANBvws2AhAgA0ECNgIMIAMgAUEBajYCFAzoAgtBACECDM4CC0ENIQIMzQILQRMhAgzMAgtBFSECDMsCC0EWIQIMygILQRghAgzJAgtBGSECDMgCC0EaIQIMxwILQRshAgzGAgtBHCECDMUCC0EdIQIMxAILQR4hAgzDAgtBHyECDMICC0EgIQIMwQILQSIhAgzAAgtBIyECDL8CC0ElIQIMvgILQeUAIQIMvQILIANBPTYCHCADIAE2AhQgAyAANgIMQQAhAgzVAgsgA0EbNgIcIAMgATYCFCADQaQcNgIQIANBFTYCDEEAIQIM1AILIANBIDYCHCADIAE2AhQgA0GYGjYCECADQRU2AgxBACECDNMCCyADQRM2AhwgAyABNgIUIANBmBo2AhAgA0EVNgIMQQAhAgzSAgsgA0ELNgIcIAMgATYCFCADQZgaNgIQIANBFTYCDEEAIQIM0QILIANBEDYCHCADIAE2AhQgA0GYGjYCECADQRU2AgxBACECDNACCyADQSA2AhwgAyABNgIUIANBpBw2AhAgA0EVNgIMQQAhAgzPAgsgA0ELNgIcIAMgATYCFCADQaQcNgIQIANBFTYCDEEAIQIMzgILIANBDDYCHCADIAE2AhQgA0GkHDYCECADQRU2AgxBACECDM0CC0EAIQIgA0EANgIcIAMgATYCFCADQd0ONgIQIANBEjYCDAzMAgsCQANAAkAgAS0AAEEKaw4EAAICAAILIAQgAUEBaiIBRw0AC0H9ASECDMwCCwJAAkAgAy0ANkEBRw0AQQAhAAJAIAMoAjgiAkUNACACKAJgIgJFDQAgAyACEQAAIQALIABFDQAgAEEVRw0BIANB/AE2AhwgAyABNgIUIANB3Bk2AhAgA0EVNgIMQQAhAgzNAgtB3AEhAgyzAgsgA0EANgIcIAMgATYCFCADQfkLNgIQIANBHzYCDEEAIQIMywILAkACQCADLQAoQQFrDgIEAQALQdsBIQIMsgILQdQBIQIMsQILIANBAjoAMUEAIQACQCADKAI4IgJFDQAgAigCACICRQ0AIAMgAhEAACEACyAARQRAQd0BIQIMsQILIABBFUcEQCADQQA2AhwgAyABNgIUIANBtAw2AhAgA0EQNgIMQQAhAgzKAgsgA0H7ATYCHCADIAE2AhQgA0GBGjYCECADQRU2AgxBACECDMkCCyABIARGBEBB+gEhAgzJAgsgAS0AAEHIAEYNASADQQE6ACgLQcABIQIMrgILQdoBIQIMrQILIAEgBEcEQCADQQw2AgggAyABNgIEQdkBIQIMrQILQfkBIQIMxQILIAEgBEYEQEH4ASECDMUCCyABLQAAQcgARw0EIAFBAWohAUHYASECDKsCCyABIARGBEBB9wEhAgzEAgsCQAJAIAEtAABBxQBrDhAABQUFBQUFBQUFBQUFBQUBBQsgAUEBaiEBQdYBIQIMqwILIAFBAWohAUHXASECDKoCC0H2ASECIAEgBEYNwgIgAygCACIAIAQgAWtqIQUgASAAa0ECaiEGAkADQCABLQAAIABButUAai0AAEcNAyAAQQJGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAMwwILIAMoAgQhACADQgA3AwAgAyAAIAZBAWoiARAuIgBFBEBB4wEhAgyqAgsgA0H1ATYCHCADIAE2AhQgAyAANgIMQQAhAgzCAgtB9AEhAiABIARGDcECIAMoAgAiACAEIAFraiEFIAEgAGtBAWohBgJAA0AgAS0AACAAQbjVAGotAABHDQIgAEEBRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADMICCyADQYEEOwEoIAMoAgQhACADQgA3AwAgAyAAIAZBAWoiARAuIgANAwwCCyADQQA2AgALQQAhAiADQQA2AhwgAyABNgIUIANB5R82AhAgA0EINgIMDL8CC0HVASECDKUCCyADQfMBNgIcIAMgATYCFCADIAA2AgxBACECDL0CC0EAIQACQCADKAI4IgJFDQAgAigCQCICRQ0AIAMgAhEAACEACyAARQ1uIABBFUcEQCADQQA2AhwgAyABNgIUIANBgg82AhAgA0EgNgIMQQAhAgy9AgsgA0GPATYCHCADIAE2AhQgA0HsGzYCECADQRU2AgxBACECDLwCCyABIARHBEAgA0ENNgIIIAMgATYCBEHTASECDKMCC0HyASECDLsCCyABIARGBEBB8QEhAgy7AgsCQAJAAkAgAS0AAEHIAGsOCwABCAgICAgICAgCCAsgAUEBaiEBQdABIQIMowILIAFBAWohAUHRASECDKICCyABQQFqIQFB0gEhAgyhAgtB8AEhAiABIARGDbkCIAMoAgAiACAEIAFraiEGIAEgAGtBAmohBQNAIAEtAAAgAEG11QBqLQAARw0EIABBAkYNAyAAQQFqIQAgBCABQQFqIgFHDQALIAMgBjYCAAy5AgtB7wEhAiABIARGDbgCIAMoAgAiACAEIAFraiEGIAEgAGtBAWohBQNAIAEtAAAgAEGz1QBqLQAARw0DIABBAUYNAiAAQQFqIQAgBCABQQFqIgFHDQALIAMgBjYCAAy4AgtB7gEhAiABIARGDbcCIAMoAgAiACAEIAFraiEGIAEgAGtBAmohBQNAIAEtAAAgAEGw1QBqLQAARw0CIABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBjYCAAy3AgsgAygCBCEAIANCADcDACADIAAgBUEBaiIBECsiAEUNAiADQewBNgIcIAMgATYCFCADIAA2AgxBACECDLYCCyADQQA2AgALIAMoAgQhACADQQA2AgQgAyAAIAEQKyIARQ2cAiADQe0BNgIcIAMgATYCFCADIAA2AgxBACECDLQCC0HPASECDJoCC0EAIQACQCADKAI4IgJFDQAgAigCNCICRQ0AIAMgAhEAACEACwJAIAAEQCAAQRVGDQEgA0EANgIcIAMgATYCFCADQeoNNgIQIANBJjYCDEEAIQIMtAILQc4BIQIMmgILIANB6wE2AhwgAyABNgIUIANBgBs2AhAgA0EVNgIMQQAhAgyyAgsgASAERgRAQesBIQIMsgILIAEtAABBL0YEQCABQQFqIQEMAQsgA0EANgIcIAMgATYCFCADQbI4NgIQIANBCDYCDEEAIQIMsQILQc0BIQIMlwILIAEgBEcEQCADQQ42AgggAyABNgIEQcwBIQIMlwILQeoBIQIMrwILIAEgBEYEQEHpASECDK8CCyABLQAAQTBrIgBB/wFxQQpJBEAgAyAAOgAqIAFBAWohAUHLASECDJYCCyADKAIEIQAgA0EANgIEIAMgACABEC8iAEUNlwIgA0HoATYCHCADIAE2AhQgAyAANgIMQQAhAgyuAgsgASAERgRAQecBIQIMrgILAkAgAS0AAEEuRgRAIAFBAWohAQwBCyADKAIEIQAgA0EANgIEIAMgACABEC8iAEUNmAIgA0HmATYCHCADIAE2AhQgAyAANgIMQQAhAgyuAgtBygEhAgyUAgsgASAERgRAQeUBIQIMrQILQQAhAEEBIQVBASEHQQAhAgJAAkACQAJAAkACfwJAAkACQAJAAkACQAJAIAEtAABBMGsOCgoJAAECAwQFBggLC0ECDAYLQQMMBQtBBAwEC0EFDAMLQQYMAgtBBwwBC0EICyECQQAhBUEAIQcMAgtBCSECQQEhAEEAIQVBACEHDAELQQAhBUEBIQILIAMgAjoAKyABQQFqIQECQAJAIAMtAC5BEHENAAJAAkACQCADLQAqDgMBAAIECyAHRQ0DDAILIAANAQwCCyAFRQ0BCyADKAIEIQAgA0EANgIEIAMgACABEC8iAEUNAiADQeIBNgIcIAMgATYCFCADIAA2AgxBACECDK8CCyADKAIEIQAgA0EANgIEIAMgACABEC8iAEUNmgIgA0HjATYCHCADIAE2AhQgAyAANgIMQQAhAgyuAgsgAygCBCEAIANBADYCBCADIAAgARAvIgBFDZgCIANB5AE2AhwgAyABNgIUIAMgADYCDAytAgtByQEhAgyTAgtBACEAAkAgAygCOCICRQ0AIAIoAkQiAkUNACADIAIRAAAhAAsCQCAABEAgAEEVRg0BIANBADYCHCADIAE2AhQgA0GkDTYCECADQSE2AgxBACECDK0CC0HIASECDJMCCyADQeEBNgIcIAMgATYCFCADQdAaNgIQIANBFTYCDEEAIQIMqwILIAEgBEYEQEHhASECDKsCCwJAIAEtAABBIEYEQCADQQA7ATQgAUEBaiEBDAELIANBADYCHCADIAE2AhQgA0GZETYCECADQQk2AgxBACECDKsCC0HHASECDJECCyABIARGBEBB4AEhAgyqAgsCQCABLQAAQTBrQf8BcSICQQpJBEAgAUEBaiEBAkAgAy8BNCIAQZkzSw0AIAMgAEEKbCIAOwE0IABB/v8DcSACQf//A3NLDQAgAyAAIAJqOwE0DAILQQAhAiADQQA2AhwgAyABNgIUIANBlR42AhAgA0ENNgIMDKsCCyADQQA2AhwgAyABNgIUIANBlR42AhAgA0ENNgIMQQAhAgyqAgtBxgEhAgyQAgsgASAERgRAQd8BIQIMqQILAkAgAS0AAEEwa0H/AXEiAkEKSQRAIAFBAWohAQJAIAMvATQiAEGZM0sNACADIABBCmwiADsBNCAAQf7/A3EgAkH//wNzSw0AIAMgACACajsBNAwCC0EAIQIgA0EANgIcIAMgATYCFCADQZUeNgIQIANBDTYCDAyqAgsgA0EANgIcIAMgATYCFCADQZUeNgIQIANBDTYCDEEAIQIMqQILQcUBIQIMjwILIAEgBEYEQEHeASECDKgCCwJAIAEtAABBMGtB/wFxIgJBCkkEQCABQQFqIQECQCADLwE0IgBBmTNLDQAgAyAAQQpsIgA7ATQgAEH+/wNxIAJB//8Dc0sNACADIAAgAmo7ATQMAgtBACECIANBADYCHCADIAE2AhQgA0GVHjYCECADQQ02AgwMqQILIANBADYCHCADIAE2AhQgA0GVHjYCECADQQ02AgxBACECDKgCC0HEASECDI4CCyABIARGBEBB3QEhAgynAgsCQAJAAkACQCABLQAAQQprDhcCAwMAAwMDAwMDAwMDAwMDAwMDAwMDAQMLIAFBAWoMBQsgAUEBaiEBQcMBIQIMjwILIAFBAWohASADQS9qLQAAQQFxDQggA0EANgIcIAMgATYCFCADQY0LNgIQIANBDTYCDEEAIQIMpwILIANBADYCHCADIAE2AhQgA0GNCzYCECADQQ02AgxBACECDKYCCyABIARHBEAgA0EPNgIIIAMgATYCBEEBIQIMjQILQdwBIQIMpQILAkACQANAAkAgAS0AAEEKaw4EAgAAAwALIAQgAUEBaiIBRw0AC0HbASECDKYCCyADKAIEIQAgA0EANgIEIAMgACABEC0iAEUEQCABQQFqIQEMBAsgA0HaATYCHCADIAA2AgwgAyABQQFqNgIUQQAhAgylAgsgAygCBCEAIANBADYCBCADIAAgARAtIgANASABQQFqCyEBQcEBIQIMigILIANB2QE2AhwgAyAANgIMIAMgAUEBajYCFEEAIQIMogILQcIBIQIMiAILIANBL2otAABBAXENASADQQA2AhwgAyABNgIUIANB5Bw2AhAgA0EZNgIMQQAhAgygAgsgASAERgRAQdkB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CyADIAU2AgAMkAILIANBADYCACAGQQFqIQFBGgw8C0HKASECIAEgBEYNjgIgAygCACIAIAQgAWtqIQUgASAAa0EDaiEGAkADQCABLQAAIABBjdUAai0AAEcNOyAAQQNGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAMjwILIANBADYCACAGQQFqIQFBIQw7CyABIARGBEBByQEhAgyOAgsCQAJAIAEtAABBwQBrDhQAPT09PT09PT09PT09PT09PT09AT0LIAFBAWohAUGtASECDPUBCyABQQFqIQFBsAEhAgz0AQsgASAERgRAQcgBIQIMjQILAkACQCABLQAAQdUAaw4LADw8PDw8PDw8PAE8CyABQQFqIQFBrgEhAgz0AQsgAUEBaiEBQa8BIQIM8wELQccBIQIgASAERg2LAiADKAIAIgAgBCABa2ohBSABIABrQQhqIQYCQANAIAEtAAAgAEGE1QBqLQAARw04IABBCEYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAyMAgsgA0EANgIAIAZBAWohAUEqDDgLIAEgBEYEQEHGASECDIsCCyABLQAAQdAARw04IAFBAWohAUElDDcLQcUBIQIgASAERg2JAiADKAIAIgAgBCABa2ohBSABIABrQQJqIQYCQANAIAEtAAAgAEGB1QBqLQAARw02IABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAyKAgsgA0EANgIAIAZBAWohAUEODDYLIAEgBEYEQEHEASECDIkCCyABLQAAQcUARw02IAFBAWohAUGrASECDO8BCyABIARGBEBBwwEhAgyIAgsCQAJAAkACQCABLQAAQcIAaw4PAAECOTk5OTk5OTk5OTkDOQsgAUEBaiEBQacBIQIM8QELIAFBAWohAUGoASECDPABCyABQQFqIQFBqQEhAgzvAQsgAUEBaiEBQaoBIQIM7gELQcIBIQIgASAERg2GAiADKAIAIgAgBCABa2ohBSABIABrQQJqIQYCQANAIAEtAAAgAEH+1ABqLQAARw0zIABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAyHAgsgA0EANgIAIAZBAWohAUEUDDMLQcEBIQIgASAERg2FAiADKAIAIgAgBCABa2ohBSABIABrQQRqIQYCQANAIAEtAAAgAEH51ABqLQAARw0yIABBBEYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAyGAgsgA0EANgIAIAZBAWohAUErDDILQcABIQIgASAERg2EAiADKAIAIgAgBCABa2ohBSABIABrQQJqIQYCQANAIAEtAAAgAEH21ABqLQAARw0xIABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAyFAgsgA0EANgIAIAZBAWohAUEsDDELQb8BIQIgASAERg2DAiADKAIAIgAgBCABa2ohBSABIABrQQJqIQYCQANAIAEtAAAgAEGh1QBqLQAARw0wIABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAyEAgsgA0EANgIAIAZBAWohAUERDDALQb4BIQIgASAERg2CAiADKAIAIgAgBCABa2ohBSABIABrQQNqIQYCQANAIAEtAAAgAEHy1ABqLQAARw0vIABBA0YNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAyDAgsgA0EANgIAIAZBAWohAUEuDC8LIAEgBEYEQEG9ASECDIICCwJAAkACQAJAAkAgAS0AAEHBAGsOFQA0NDQ0NDQ0NDQ0ATQ0AjQ0AzQ0BDQLIAFBAWohAUGbASECDOwBCyABQQFqIQFBnAEhAgzrAQsgAUEBaiEBQZ0BIQIM6gELIAFBAWohAUGiASECDOkBCyABQQFqIQFBpAEhAgzoAQsgASAERgRAQbwBIQIMgQILAkACQCABLQAAQdIAaw4DADABMAsgAUEBaiEBQaMBIQIM6AELIAFBAWohAUEEDC0LQbsBIQIgASAERg3/ASADKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEHw1ABqLQAARw0sIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAyAAgsgA0EANgIAIAZBAWohAUEdDCwLIAEgBEYEQEG6ASECDP8BCwJAAkAgAS0AAEHJAGsOBwEuLi4uLgAuCyABQQFqIQFBoQEhAgzmAQsgAUEBaiEBQSIMKwsgASAERgRAQbkBIQIM/gELIAEtAABB0ABHDSsgAUEBaiEBQaABIQIM5AELIAEgBEYEQEG4ASECDP0BCwJAAkAgAS0AAEHGAGsOCwAsLCwsLCwsLCwBLAsgAUEBaiEBQZ4BIQIM5AELIAFBAWohAUGfASECDOMBC0G3ASECIAEgBEYN+wEgAygCACIAIAQgAWtqIQUgASAAa0EDaiEGAkADQCABLQAAIABB7NQAai0AAEcNKCAAQQNGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM/AELIANBADYCACAGQQFqIQFBDQwoC0G2ASECIAEgBEYN+gEgAygCACIAIAQgAWtqIQUgASAAa0ECaiEGAkADQCABLQAAIABBodUAai0AAEcNJyAAQQJGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM+wELIANBADYCACAGQQFqIQFBDAwnC0G1ASECIAEgBEYN+QEgAygCACIAIAQgAWtqIQUgASAAa0EBaiEGAkADQCABLQAAIABB6tQAai0AAEcNJiAAQQFGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM+gELIANBADYCACAGQQFqIQFBAwwmC0G0ASECIAEgBEYN+AEgAygCACIAIAQgAWtqIQUgASAAa0EBaiEGAkADQCABLQAAIABB6NQAai0AAEcNJSAAQQFGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM+QELIANBADYCACAGQQFqIQFBJgwlCyABIARGBEBBswEhAgz4AQsCQAJAIAEtAABB1ABrDgIAAScLIAFBAWohAUGZASECDN8BCyABQQFqIQFBmgEhAgzeAQtBsgEhAiABIARGDfYBIAMoAgAiACAEIAFraiEFIAEgAGtBAWohBgJAA0AgAS0AACAAQebUAGotAABHDSMgAEEBRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADPcBCyADQQA2AgAgBkEBaiEBQScMIwtBsQEhAiABIARGDfUBIAMoAgAiACAEIAFraiEFIAEgAGtBAWohBgJAA0AgAS0AACAAQeTUAGotAABHDSIgAEEBRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADPYBCyADQQA2AgAgBkEBaiEBQRwMIgtBsAEhAiABIARGDfQBIAMoAgAiACAEIAFraiEFIAEgAGtBBWohBgJAA0AgAS0AACAAQd7UAGotAABHDSEgAEEFRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADPUBCyADQQA2AgAgBkEBaiEBQQYMIQtBrwEhAiABIARGDfMBIAMoAgAiACAEIAFraiEFIAEgAGtBBGohBgJAA0AgAS0AACAAQdnUAGotAABHDSAgAEEERg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADPQBCyADQQA2AgAgBkEBaiEBQRkMIAsgASAERgRAQa4BIQIM8wELAkACQAJAAkAgAS0AAEEtaw4jACQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkASQkJCQkAiQkJAMkCyABQQFqIQFBjgEhAgzcAQsgAUEBaiEBQY8BIQIM2wELIAFBAWohAUGUASECDNoBCyABQQFqIQFBlQEhAgzZAQtBrQEhAiABIARGDfEBIAMoAgAiACAEIAFraiEFIAEgAGtBAWohBgJAA0AgAS0AACAAQdfUAGotAABHDR4gAEEBRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADPIBCyADQQA2AgAgBkEBaiEBQQsMHgsgASAERgRAQawBIQIM8QELAkACQCABLQAAQcEAaw4DACABIAsgAUEBaiEBQZABIQIM2AELIAFBAWohAUGTASECDNcBCyABIARGBEBBqwEhAgzwAQsCQAJAIAEtAABBwQBrDg8AHx8fHx8fHx8fHx8fHwEfCyABQQFqIQFBkQEhAgzXAQsgAUEBaiEBQZIBIQIM1gELIAEgBEYEQEGqASECDO8BCyABLQAAQcwARw0cIAFBAWohAUEKDBsLQakBIQIgASAERg3tASADKAIAIgAgBCABa2ohBSABIABrQQVqIQYCQANAIAEtAAAgAEHR1ABqLQAARw0aIABBBUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzuAQsgA0EANgIAIAZBAWohAUEeDBoLQagBIQIgASAERg3sASADKAIAIgAgBCABa2ohBSABIABrQQZqIQYCQANAIAEtAAAgAEHK1ABqLQAARw0ZIABBBkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAztAQsgA0EANgIAIAZBAWohAUEVDBkLQacBIQIgASAERg3rASADKAIAIgAgBCABa2ohBSABIABrQQJqIQYCQANAIAEtAAAgAEHH1ABqLQAARw0YIABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzsAQsgA0EANgIAIAZBAWohAUEXDBgLQaYBIQIgASAERg3qASADKAIAIgAgBCABa2ohBSABIABrQQVqIQYCQANAIAEtAAAgAEHB1ABqLQAARw0XIABBBUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzrAQsgA0EANgIAIAZBAWohAUEYDBcLIAEgBEYEQEGlASECDOoBCwJAAkAgAS0AAEHJAGsOBwAZGRkZGQEZCyABQQFqIQFBiwEhAgzRAQsgAUEBaiEBQYwBIQIM0AELQaQBIQIgASAERg3oASADKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEGm1QBqLQAARw0VIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzpAQsgA0EANgIAIAZBAWohAUEJDBULQaMBIQIgASAERg3nASADKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEGk1QBqLQAARw0UIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzoAQsgA0EANgIAIAZBAWohAUEfDBQLQaIBIQIgASAERg3mASADKAIAIgAgBCABa2ohBSABIABrQQJqIQYCQANAIAEtAAAgAEG+1ABqLQAARw0TIABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAznAQsgA0EANgIAIAZBAWohAUECDBMLQaEBIQIgASAERg3lASADKAIAIgAgBCABa2ohBSABIABrQQFqIQYDQCABLQAAIABBvNQAai0AAEcNESAAQQFGDQIgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM5QELIAEgBEYEQEGgASECDOUBC0EBIAEtAABB3wBHDREaIAFBAWohAUGHASECDMsBCyADQQA2AgAgBkEBaiEBQYgBIQIMygELQZ8BIQIgASAERg3iASADKAIAIgAgBCABa2ohBSABIABrQQhqIQYCQANAIAEtAAAgAEGE1QBqLQAARw0PIABBCEYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzjAQsgA0EANgIAIAZBAWohAUEpDA8LQZ4BIQIgASAERg3hASADKAIAIgAgBCABa2ohBSABIABrQQNqIQYCQANAIAEtAAAgAEG41ABqLQAARw0OIABBA0YNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAziAQsgA0EANgIAIAZBAWohAUEtDA4LIAEgBEYEQEGdASECDOEBCyABLQAAQcUARw0OIAFBAWohAUGEASECDMcBCyABIARGBEBBnAEhAgzgAQsCQAJAIAEtAABBzABrDggADw8PDw8PAQ8LIAFBAWohAUGCASECDMcBCyABQQFqIQFBgwEhAgzGAQtBmwEhAiABIARGDd4BIAMoAgAiACAEIAFraiEFIAEgAGtBBGohBgJAA0AgAS0AACAAQbPUAGotAABHDQsgAEEERg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADN8BCyADQQA2AgAgBkEBaiEBQSMMCwtBmgEhAiABIARGDd0BIAMoAgAiACAEIAFraiEFIAEgAGtBAmohBgJAA0AgAS0AACAAQbDUAGotAABHDQogAEECRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADN4BCyADQQA2AgAgBkEBaiEBQQAMCgsgASAERgRAQZkBIQIM3QELAkACQCABLQAAQcgAaw4IAAwMDAwMDAEMCyABQQFqIQFB/QAhAgzEAQsgAUEBaiEBQYABIQIMwwELIAEgBEYEQEGYASECDNwBCwJAAkAgAS0AAEHOAGsOAwALAQsLIAFBAWohAUH+ACECDMMBCyABQQFqIQFB/wAhAgzCAQsgASAERgRAQZcBIQIM2wELIAEtAABB2QBHDQggAUEBaiEBQQgMBwtBlgEhAiABIARGDdkBIAMoAgAiACAEIAFraiEFIAEgAGtBA2ohBgJAA0AgAS0AACAAQazUAGotAABHDQYgAEEDRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADNoBCyADQQA2AgAgBkEBaiEBQQUMBgtBlQEhAiABIARGDdgBIAMoAgAiACAEIAFraiEFIAEgAGtBBWohBgJAA0AgAS0AACAAQabUAGotAABHDQUgAEEFRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADNkBCyADQQA2AgAgBkEBaiEBQRYMBQtBlAEhAiABIARGDdcBIAMoAgAiACAEIAFraiEFIAEgAGtBAmohBgJAA0AgAS0AACAAQaHVAGotAABHDQQgAEECRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADNgBCyADQQA2AgAgBkEBaiEBQRAMBAsgASAERgRAQZMBIQIM1wELAkACQCABLQAAQcMAaw4MAAYGBgYGBgYGBgYBBgsgAUEBaiEBQfkAIQIMvgELIAFBAWohAUH6ACECDL0BC0GSASECIAEgBEYN1QEgAygCACIAIAQgAWtqIQUgASAAa0EFaiEGAkADQCABLQAAIABBoNQAai0AAEcNAiAAQQVGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM1gELIANBADYCACAGQQFqIQFBJAwCCyADQQA2AgAMAgsgASAERgRAQZEBIQIM1AELIAEtAABBzABHDQEgAUEBaiEBQRMLOgApIAMoAgQhACADQQA2AgQgAyAAIAEQLiIADQIMAQtBACECIANBADYCHCADIAE2AhQgA0H+HzYCECADQQY2AgwM0QELQfgAIQIMtwELIANBkAE2AhwgAyABNgIUIAMgADYCDEEAIQIMzwELQQAhAAJAIAMoAjgiAkUNACACKAJAIgJFDQAgAyACEQAAIQALIABFDQAgAEEVRg0BIANBADYCHCADIAE2AhQgA0GCDzYCECADQSA2AgxBACECDM4BC0H3ACECDLQBCyADQY8BNgIcIAMgATYCFCADQewbNgIQIANBFTYCDEEAIQIMzAELIAEgBEYEQEGPASECDMwBCwJAIAEtAABBIEYEQCABQQFqIQEMAQsgA0EANgIcIAMgATYCFCADQZsfNgIQIANBBjYCDEEAIQIMzAELQQIhAgyyAQsDQCABLQAAQSBHDQIgBCABQQFqIgFHDQALQY4BIQIMygELIAEgBEYEQEGNASECDMoBCwJAIAEtAABBCWsOBEoAAEoAC0H1ACECDLABCyADLQApQQVGBEBB9gAhAgywAQtB9AAhAgyvAQsgASAERgRAQYwBIQIMyAELIANBEDYCCCADIAE2AgQMCgsgASAERgRAQYsBIQIMxwELAkAgAS0AAEEJaw4ERwAARwALQfMAIQIMrQELIAEgBEcEQCADQRA2AgggAyABNgIEQfEAIQIMrQELQYoBIQIMxQELAkAgASAERwRAA0AgAS0AAEGg0ABqLQAAIgBBA0cEQAJAIABBAWsOAkkABAtB8AAhAgyvAQsgBCABQQFqIgFHDQALQYgBIQIMxgELQYgBIQIMxQELIANBADYCHCADIAE2AhQgA0HbIDYCECADQQc2AgxBACECDMQBCyABIARGBEBBiQEhAgzEAQsCQAJAAkAgAS0AAEGg0gBqLQAAQQFrDgNGAgABC0HyACECDKwBCyADQQA2AhwgAyABNgIUIANBtBI2AhAgA0EHNgIMQQAhAgzEAQtB6gAhAgyqAQsgASAERwRAIAFBAWohAUHvACECDKoBC0GHASECDMIBCyAEIAEiAEYEQEGGASECDMIBCyAALQAAIgFBL0YEQCAAQQFqIQFB7gAhAgypAQsgAUEJayICQRdLDQEgACEBQQEgAnRBm4CABHENQQwBCyAEIAEiAEYEQEGFASECDMEBCyAALQAAQS9HDQAgAEEBaiEBDAMLQQAhAiADQQA2AhwgAyAANgIUIANB2yA2AhAgA0EHNgIMDL8BCwJAAkACQAJAAkADQCABLQAAQaDOAGotAAAiAEEFRwRAAkACQCAAQQFrDghHBQYHCAAEAQgLQesAIQIMrQELIAFBAWohAUHtACECDKwBCyAEIAFBAWoiAUcNAAtBhAEhAgzDAQsgAUEBagwUCyADKAIEIQAgA0EANgIEIAMgACABECwiAEUNHiADQdsANgIcIAMgATYCFCADIAA2AgxBACECDMEBCyADKAIEIQAgA0EANgIEIAMgACABECwiAEUNHiADQd0ANgIcIAMgATYCFCADIAA2AgxBACECDMABCyADKAIEIQAgA0EANgIEIAMgACABECwiAEUNHiADQfoANgIcIAMgATYCFCADIAA2AgxBACECDL8BCyADQQA2AhwgAyABNgIUIANB+Q82AhAgA0EHNgIMQQAhAgy+AQsgASAERgRAQYMBIQIMvgELAkAgAS0AAEGgzgBqLQAAQQFrDgg+BAUGAAgCAwcLIAFBAWohAQtBAyECDKMBCyABQQFqDA0LQQAhAiADQQA2AhwgA0HREjYCECADQQc2AgwgAyABQQFqNgIUDLoBCyADKAIEIQAgA0EANgIEIAMgACABECwiAEUNFiADQdsANgIcIAMgATYCFCADIAA2AgxBACECDLkBCyADKAIEIQAgA0EANgIEIAMgACABECwiAEUNFiADQd0ANgIcIAMgATYCFCADIAA2AgxBACECDLgBCyADKAIEIQAgA0EANgIEIAMgACABECwiAEUNFiADQfoANgIcIAMgATYCFCADIAA2AgxBACECDLcBCyADQQA2AhwgAyABNgIUIANB+Q82AhAgA0EHNgIMQQAhAgy2AQtB7AAhAgycAQsgASAERgRAQYIBIQIMtQELIAFBAWoMAgsgASAERgRAQYEBIQIMtAELIAFBAWoMAQsgASAERg0BIAFBAWoLIQFBBCECDJgBC0GAASECDLABCwNAIAEtAABBoMwAai0AACIAQQJHBEAgAEEBRwRAQekAIQIMmQELDDELIAQgAUEBaiIBRw0AC0H/ACECDK8BCyABIARGBEBB/gAhAgyvAQsCQCABLQAAQQlrDjcvAwYvBAYGBgYGBgYGBgYGBgYGBgYGBgUGBgIGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYABgsgAUEBagshAUEFIQIMlAELIAFBAWoMBgsgAygCBCEAIANBADYCBCADIAAgARAsIgBFDQggA0HbADYCHCADIAE2AhQgAyAANgIMQQAhAgyrAQsgAygCBCEAIANBADYCBCADIAAgARAsIgBFDQggA0HdADYCHCADIAE2AhQgAyAANgIMQQAhAgyqAQsgAygCBCEAIANBADYCBCADIAAgARAsIgBFDQggA0H6ADYCHCADIAE2AhQgAyAANgIMQQAhAgypAQsgA0EANgIcIAMgATYCFCADQY0UNgIQIANBBzYCDEEAIQIMqAELAkACQAJAAkADQCABLQAAQaDKAGotAAAiAEEFRwRAAkAgAEEBaw4GLgMEBQYABgtB6AAhAgyUAQsgBCABQQFqIgFHDQALQf0AIQIMqwELIAMoAgQhACADQQA2AgQgAyAAIAEQLCIARQ0HIANB2wA2AhwgAyABNgIUIAMgADYCDEEAIQIMqgELIAMoAgQhACADQQA2AgQgAyAAIAEQLCIARQ0HIANB3QA2AhwgAyABNgIUIAMgADYCDEEAIQIMqQELIAMoAgQhACADQQA2AgQgAyAAIAEQLCIARQ0HIANB+gA2AhwgAyABNgIUIAMgADYCDEEAIQIMqAELIANBADYCHCADIAE2AhQgA0HkCDYCECADQQc2AgxBACECDKcBCyABIARGDQEgAUEBagshAUEGIQIMjAELQfwAIQIMpAELAkACQAJAAkADQCABLQAAQaDIAGotAAAiAEEFRwRAIABBAWsOBCkCAwQFCyAEIAFBAWoiAUcNAAtB+wAhAgynAQsgAygCBCEAIANBADYCBCADIAAgARAsIgBFDQMgA0HbADYCHCADIAE2AhQgAyAANgIMQQAhAgymAQsgAygCBCEAIANBADYCBCADIAAgARAsIgBFDQMgA0HdADYCHCADIAE2AhQgAyAANgIMQQAhAgylAQsgAygCBCEAIANBADYCBCADIAAgARAsIgBFDQMgA0H6ADYCHCADIAE2AhQgAyAANgIMQQAhAgykAQsgA0EANgIcIAMgATYCFCADQbwKNgIQIANBBzYCDEEAIQIMowELQc8AIQIMiQELQdEAIQIMiAELQecAIQIMhwELIAEgBEYEQEH6ACECDKABCwJAIAEtAABBCWsOBCAAACAACyABQQFqIQFB5gAhAgyGAQsgASAERgRAQfkAIQIMnwELAkAgAS0AAEEJaw4EHwAAHwALQQAhAAJAIAMoAjgiAkUNACACKAI4IgJFDQAgAyACEQAAIQALIABFBEBB4gEhAgyGAQsgAEEVRwRAIANBADYCHCADIAE2AhQgA0HJDTYCECADQRo2AgxBACECDJ8BCyADQfgANgIcIAMgATYCFCADQeoaNgIQIANBFTYCDEEAIQIMngELIAEgBEcEQCADQQ02AgggAyABNgIEQeQAIQIMhQELQfcAIQIMnQELIAEgBEYEQEH2ACECDJ0BCwJAAkACQCABLQAAQcgAaw4LAAELCwsLCwsLCwILCyABQQFqIQFB3QAhAgyFAQsgAUEBaiEBQeAAIQIMhAELIAFBAWohAUHjACECDIMBC0H1ACECIAEgBEYNmwEgAygCACIAIAQgAWtqIQUgASAAa0ECaiEGAkADQCABLQAAIABBtdUAai0AAEcNCCAAQQJGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAMnAELIAMoAgQhACADQgA3AwAgAyAAIAZBAWoiARArIgAEQCADQfQANgIcIAMgATYCFCADIAA2AgxBACECDJwBC0HiACECDIIBC0EAIQACQCADKAI4IgJFDQAgAigCNCICRQ0AIAMgAhEAACEACwJAIAAEQCAAQRVGDQEgA0EANgIcIAMgATYCFCADQeoNNgIQIANBJjYCDEEAIQIMnAELQeEAIQIMggELIANB8wA2AhwgAyABNgIUIANBgBs2AhAgA0EVNgIMQQAhAgyaAQsgAy0AKSIAQSNrQQtJDQkCQCAAQQZLDQBBASAAdEHKAHFFDQAMCgtBACECIANBADYCHCADIAE2AhQgA0HtCTYCECADQQg2AgwMmQELQfIAIQIgASAERg2YASADKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEGz1QBqLQAARw0FIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAyZAQsgAygCBCEAIANCADcDACADIAAgBkEBaiIBECsiAARAIANB8QA2AhwgAyABNgIUIAMgADYCDEEAIQIMmQELQd8AIQIMfwtBACEAAkAgAygCOCICRQ0AIAIoAjQiAkUNACADIAIRAAAhAAsCQCAABEAgAEEVRg0BIANBADYCHCADIAE2AhQgA0HqDTYCECADQSY2AgxBACECDJkBC0HeACECDH8LIANB8AA2AhwgAyABNgIUIANBgBs2AhAgA0EVNgIMQQAhAgyXAQsgAy0AKUEhRg0GIANBADYCHCADIAE2AhQgA0GRCjYCECADQQg2AgxBACECDJYBC0HvACECIAEgBEYNlQEgAygCACIAIAQgAWtqIQUgASAAa0ECaiEGAkADQCABLQAAIABBsNUAai0AAEcNAiAAQQJGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAMlgELIAMoAgQhACADQgA3AwAgAyAAIAZBAWoiARArIgBFDQIgA0HtADYCHCADIAE2AhQgAyAANgIMQQAhAgyVAQsgA0EANgIACyADKAIEIQAgA0EANgIEIAMgACABECsiAEUNgAEgA0HuADYCHCADIAE2AhQgAyAANgIMQQAhAgyTAQtB3AAhAgx5C0EAIQACQCADKAI4IgJFDQAgAigCNCICRQ0AIAMgAhEAACEACwJAIAAEQCAAQRVGDQEgA0EANgIcIAMgATYCFCADQeoNNgIQIANBJjYCDEEAIQIMkwELQdsAIQIMeQsgA0HsADYCHCADIAE2AhQgA0GAGzYCECADQRU2AgxBACECDJEBCyADLQApIgBBI0kNACAAQS5GDQAgA0EANgIcIAMgATYCFCADQckJNgIQIANBCDYCDEEAIQIMkAELQdoAIQIMdgsgASAERgRAQesAIQIMjwELAkAgAS0AAEEvRgRAIAFBAWohAQwBCyAD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ciBIVFRQL3gueCByZXF1ZXN0AEludmFsaWQgbWV0aG9kIGZvciBSVFNQL3gueCByZXF1ZXN0AEV4cGVjdGVkIFNPVVJDRSBtZXRob2QgZm9yIElDRS94LnggcmVxdWVzdABJbnZhbGlkIGNoYXIgaW4gdXJsIGZyYWdtZW50IHN0YXJ0AEV4cGVjdGVkIGRvdABTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3N0YXR1cwBJbnZhbGlkIHJlc3BvbnNlIHN0YXR1cwBFeHBlY3RlZCBMRiBhZnRlciBoZWFkZXJzAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMAVXNlciBjYWxsYmFjayBlcnJvcgBgb25fcmVzZXRgIGNhbGxiYWNrIGVycm9yAGBvbl9jaHVua19oZWFkZXJgIGNhbGxiYWNrIGVycm9yAGBvbl9tZXNzYWdlX2JlZ2luYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlYCBjYWxsYmFjayBlcnJvcgBgb25fc3RhdHVzX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fdmVyc2lvbl9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX3VybF9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX3Byb3RvY29sX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9oZWFkZXJfdmFsdWVfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9tZXNzYWdlX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fbWV0aG9kX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25faGVhZGVyX2ZpZWxkX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfZXh0ZW5zaW9uX25hbWVgIGNhbGxiYWNrIGVycm9yAFVuZXhwZWN0ZWQgY2hhciBpbiB1cmwgc2VydmVyAEludmFsaWQgaGVhZGVyIHZhbHVlIGNoYXIASW52YWxpZCBoZWFkZXIgZmllbGQgY2hhcgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3ZlcnNpb24ASW52YWxpZCBtaW5vciB2ZXJzaW9uAEludmFsaWQgbWFqb3IgdmVyc2lvbgBFeHBlY3RlZCBzcGFjZSBhZnRlciB2ZXJzaW9uAEV4cGVjdGVkIENSTEYgYWZ0ZXIgdmVyc2lvbgBJbnZhbGlkIEhUVFAgdmVyc2lvbgBJbnZhbGlkIGhlYWRlciB0b2tlbgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3VybABJbnZhbGlkIGNoYXJhY3RlcnMgaW4gdXJsAFVuZXhwZWN0ZWQgc3RhcnQgY2hhciBpbiB1cmwARG91YmxlIEAgaW4gdXJsAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fcHJvdG9jb2wARW1wdHkgQ29udGVudC1MZW5ndGgASW52YWxpZCBjaGFyYWN0ZXIgaW4gQ29udGVudC1MZW5ndGgAVHJhbnNmZXItRW5jb2RpbmcgY2FuJ3QgYmUgcHJlc2VudCB3aXRoIENvbnRlbnQtTGVuZ3RoAER1cGxpY2F0ZSBDb250ZW50LUxlbmd0aABJbnZhbGlkIGNoYXIgaW4gdXJsIHBhdGgAQ29udGVudC1MZW5ndGggY2FuJ3QgYmUgcHJlc2VudCB3aXRoIFRyYW5zZmVyLUVuY29kaW5nAE1pc3NpbmcgZXhwZWN0ZWQgQ1IgYWZ0ZXIgY2h1bmsgc2l6ZQBFeHBlY3RlZCBMRiBhZnRlciBjaHVuayBzaXplAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIHNpemUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfdmFsdWUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9jaHVua19leHRlbnNpb25fdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyB2YWx1ZQBVbmV4cGVjdGVkIHdoaXRlc3BhY2UgYWZ0ZXIgaGVhZGVyIHZhbHVlAE1pc3NpbmcgZXhwZWN0ZWQgQ1IgYWZ0ZXIgaGVhZGVyIHZhbHVlAE1pc3NpbmcgZXhwZWN0ZWQgTEYgYWZ0ZXIgaGVhZGVyIHZhbHVlAEludmFsaWQgYFRyYW5zZmVyLUVuY29kaW5nYCBoZWFkZXIgdmFsdWUATWlzc2luZyBleHBlY3RlZCBDUiBhZnRlciBjaHVuayBleHRlbnNpb24gdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyBxdW90ZSB2YWx1ZQBJbnZhbGlkIHF1b3RlZC1wYWlyIGluIGNodW5rIGV4dGVuc2lvbnMgcXVvdGVkIHZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgcXVvdGVkIHZhbHVlAFBhdXNlZCBieSBvbl9oZWFkZXJzX2NvbXBsZXRlAEludmFsaWQgRU9GIHN0YXRlAG9uX3Jlc2V0IHBhdXNlAG9uX2NodW5rX2hlYWRlciBwYXVzZQBvbl9tZXNzYWdlX2JlZ2luIHBhdXNlAG9uX2NodW5rX2V4dGVuc2lvbl92YWx1ZSBwYXVzZQBvbl9zdGF0dXNfY29tcGxldGUgcGF1c2UAb25fdmVyc2lvbl9jb21wbGV0ZSBwYXVzZQBvbl91cmxfY29tcGxldGUgcGF1c2UAb25fcHJvdG9jb2xfY29tcGxldGUgcGF1c2UAb25fY2h1bmtfY29tcGxldGUgcGF1c2UAb25faGVhZGVyX3ZhbHVlX2NvbXBsZXRlIHBhdXNlAG9uX21lc3NhZ2VfY29tcGxldGUgcGF1c2UAb25fbWV0aG9kX2NvbXBsZXRlIHBhdXNlAG9uX2hlYWRlcl9maWVsZF9jb21wbGV0ZSBwYXVzZQBvbl9jaHVua19leHRlbnNpb25fbmFtZSBwYXVzZQBVbmV4cGVjdGVkIHNwYWNlIGFmdGVyIHN0YXJ0IGxpbmUATWlzc2luZyBleHBlY3RlZCBDUiBhZnRlciByZXNwb25zZSBsaW5lAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fY2h1bmtfZXh0ZW5zaW9uX25hbWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyBuYW1lAE1pc3NpbmcgZXhwZWN0ZWQgQ1IgYWZ0ZXIgY2h1bmsgZXh0ZW5zaW9uIG5hbWUASW52YWxpZCBzdGF0dXMgY29kZQBQYXVzZSBvbiBDT05ORUNUL1VwZ3JhZGUAUGF1c2Ugb24gUFJJL1VwZ3JhZGUARXhwZWN0ZWQgSFRUUC8yIENvbm5lY3Rpb24gUHJlZmFjZQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX21ldGhvZABFeHBlY3RlZCBzcGFjZSBhZnRlciBtZXRob2QAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfZmllbGQAUGF1c2VkAEludmFsaWQgd29yZCBlbmNvdW50ZXJlZABJbnZhbGlkIG1ldGhvZCBlbmNvdW50ZXJlZABNaXNzaW5nIGV4cGVjdGVkIENSIGFmdGVyIGNodW5rIGRhdGEARXhwZWN0ZWQgTEYgYWZ0ZXIgY2h1bmsgZGF0YQBVbmV4cGVjdGVkIGNoYXIgaW4gdXJsIHNjaGVtYQBSZXF1ZXN0IGhhcyBpbnZhbGlkIGBUcmFuc2Zlci1FbmNvZGluZ2AARGF0YSBhZnRlciBgQ29ubmVjdGlvbjogY2xvc2VgAFNXSVRDSF9QUk9YWQBVU0VfUFJPWFkATUtBQ1RJVklUWQBVTlBST0NFU1NBQkxFX0VOVElUWQBRVUVSWQBDT1BZAE1PVkVEX1BFUk1BTkVOVExZAFRPT19FQVJMWQBOT1RJRlkARkFJTEVEX0RFUEVOREVOQ1kAQkFEX0dBVEVXQVkAUExBWQBQVVQAQ0hFQ0tPVVQAR0FURVdBWV9USU1FT1VUAFJFUVVFU1RfVElNRU9VVABORVRXT1JLX0NPTk5FQ1RfVElNRU9VVABDT05ORUNUSU9OX1RJTUVPVVQATE9HSU5fVElNRU9VVABORVRXT1JLX1JFQURfVElNRU9VVABQT1NUAE1JU0RJUkVDVEVEX1JFUVVFU1QAQ0xJRU5UX0NMT1NFRF9SRVFVRVNUAENMSUVOVF9DTE9TRURfTE9BRF9CQUxBTkNFRF9SRVFVRVNUAEJBRF9SRVFVRVNUAEhUVFBfUkVRVUVTVF9TRU5UX1RPX0hUVFBTX1BPUlQAUkVQT1JUAElNX0FfVEVBUE9UAFJFU0VUX0NPTlRFTlQATk9fQ09OVEVOVABQQVJUSUFMX0NPTlRFTlQASFBFX0lOVkFMSURfQ09OU1RBTlQASFBFX0NCX1JFU0VUAEdFVABIUEVfU1RSSUNUAENPTkZMSUNUAFRFTVBPUkFSWV9SRURJUkVDVABQRVJNQU5FTlRfUkVESVJFQ1QAQ09OTkVDVABNVUxUSV9TVEFUVVMASFBFX0lOVkFMSURfU1RBVFVTAFRPT19NQU5ZX1JFUVVFU1RTAEVBUkxZX0hJTlRTAFVOQVZBSUxBQkxFX0ZPUl9MRUdBTF9SRUFTT05TAE9QVElPTlMAU1dJVENISU5HX1BST1RPQ09MUwBWQVJJQU5UX0FMU09fTkVHT1RJQVRFUwBNVUxUSVBMRV9DSE9JQ0VTAElOVEVSTkFMX1NFUlZFUl9FUlJPUgBXRUJfU0VSVkVSX1VOS05PV05fRVJST1IAUkFJTEdVTl9FUlJPUgBJREVOVElUWV9QUk9WSURFUl9BVVRIRU5USUNBVElPTl9FUlJPUgBTU0xfQ0VSVElGSUNBVEVfRVJST1IASU5WQUxJRF9YX0ZPUldBUkRFRF9GT1IAU0VUX1BBUkFNRVRFUgBHRVRfUEFSQU1FVEVSAEhQRV9VU0VSAFNFRV9PVEhFUgBIUEVfQ0JfQ0hVTktfSEVBREVSAEV4cGVjdGVkIExGIGFmdGVyIENSAE1LQ0FMRU5EQVIAU0VUVVAAV0VCX1NFUlZFUl9JU19ET1dOAFRFQVJET1dOAEhQRV9DTE9TRURfQ09OTkVDVElPTgBIRVVSSVNUSUNfRVhQSVJBVElPTgBESVNDT05ORUNURURfT1BFUkFUSU9OAE5PTl9BVVRIT1JJVEFUSVZFX0lORk9STUFUSU9OAEhQRV9JTlZBTElEX1ZFUlNJT04ASFBFX0NCX01FU1NBR0VfQkVHSU4AU0lURV9JU19GUk9aRU4ASFBFX0lOVkFMSURfSEVBREVSX1RPS0VOAElOVkFMSURfVE9LRU4ARk9SQklEREVOAEVOSEFOQ0VfWU9VUl9DQUxNAEhQRV9JTlZBTElEX1VSTABCTE9DS0VEX0JZX1BBUkVOVEFMX0NPTlRST0wATUtDT0wAQUNMAEhQRV9JTlRFUk5BTABSRVFVRVNUX0hFQURFUl9GSUVMRFNfVE9PX0xBUkdFX1VOT0ZGSUNJQUwASFBFX09LAFVOTElOSwBVTkxPQ0sAUFJJAFJFVFJZX1dJVEgASFBFX0lOVkFMSURfQ09OVEVOVF9MRU5HVEgASFBFX1VORVhQRUNURURfQ09OVEVOVF9MRU5HVEgARkxVU0gAUFJPUFBBVENIAE0tU0VBUkNIAFVSSV9UT09fTE9ORwBQUk9DRVNTSU5HAE1JU0NFTExBTkVPVVNfUEVSU0lTVEVOVF9XQVJOSU5HAE1JU0NFTExBTkVPVVNfV0FSTklORwBIUEVfSU5WQUxJRF9UUkFOU0ZFUl9FTkNPRElORwBFeHBlY3RlZCBDUkxGAEhQRV9JTlZBTElEX0NIVU5LX1NJWkUATU9WRQBDT05USU5VRQBIUEVfQ0JfU1RBVFVTX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJTX0NPTVBMRVRFAEhQRV9DQl9WRVJTSU9OX0NPTVBMRVRFAEhQRV9DQl9VUkxfQ09NUExFVEUASFBFX0NCX1BST1RPQ09MX0NPTVBMRVRFAEhQRV9DQl9DSFVOS19DT01QTEVURQBIUEVfQ0JfSEVBREVSX1ZBTFVFX0NPTVBMRVRFAEhQRV9DQl9DSFVOS19FWFRFTlNJT05fVkFMVUVfQ09NUExFVEUASFBFX0NCX0NIVU5LX0VYVEVOU0lPTl9OQU1FX0NPTVBMRVRFAEhQRV9DQl9NRVNTQUdFX0NPTVBMRVRFAEhQRV9DQl9NRVRIT0RfQ09NUExFVEUASFBFX0NCX0hFQURFUl9GSUVMRF9DT01QTEVURQBERUxFVEUASFBFX0lOVkFMSURfRU9GX1NUQVRFAElOVkFMSURfU1NMX0NFUlRJRklDQVRFAFBBVVNFAE5PX1JFU1BPTlNFAFVOU1VQUE9SVEVEX01FRElBX1RZUEUAR09ORQBOT1RfQUNDRVBUQUJMRQBTRVJWSUNFX1VOQVZBSUxBQkxFAFJBTkdFX05PVF9TQVRJU0ZJQUJMRQBPUklHSU5fSVNfVU5SRUFDSEFCTEUAUkVTUE9OU0VfSVNfU1RBTEUAUFVSR0UATUVSR0UAUkVRVUVTVF9IRUFERVJfRklFTERTX1RPT19MQVJHRQBSRVFVRVNUX0hFQURFUl9UT09fTEFSR0UAUEFZTE9BRF9UT09fTEFSR0UASU5TVUZGSUNJRU5UX1NUT1JBR0UASFBFX1BBVVNFRF9VUEdSQURFAEhQRV9QQVVTRURfSDJfVVBHUkFERQBTT1VSQ0UAQU5OT1VOQ0UAVFJBQ0UASFBFX1VORVhQRUNURURfU1BBQ0UAREVTQ1JJQkUAVU5TVUJTQ1JJQkUAUkVDT1JEAEhQRV9JTlZBTElEX01FVEhPRABOT1RfRk9VTkQAUFJPUEZJTkQAVU5CSU5EAFJFQklORABVTkFVVEhPUklaRUQATUVUSE9EX05PVF9BTExPV0VEAEhUVFBfVkVSU0lPTl9OT1RfU1VQUE9SVEVEAEFMUkVBRFlfUkVQT1JURUQAQUNDRVBURUQATk9UX0lNUExFTUVOVEVEAExPT1BfREVURUNURUQASFBFX0NSX0VYUEVDVEVEAEhQRV9MRl9FWFBFQ1RFRABDUkVBVEVEAElNX1VTRUQASFBFX1BBVVNFRABUSU1FT1VUX09DQ1VSRUQAUEFZTUVOVF9SRVFVSVJFRABQUkVDT05ESVRJT05fUkVRVUlSRUQAUFJPWFlfQVVUSEVOVElDQVRJT05fUkVRVUlSRUQATkVUV09SS19BVVRIRU5USUNBVElPTl9SRVFVSVJFRABMRU5HVEhfUkVRVUlSRUQAU1NMX0NFUlRJRklDQVRFX1JFUVVJUkVEAFVQR1JBREVfUkVRVUlSRUQAUEFHRV9FWFBJUkVEAFBSRUNPTkRJVElPTl9GQUlMRUQARVhQRUNUQVRJT05fRkFJTEVEAFJFVkFMSURBVElPTl9GQUlMRUQAU1NMX0hBTkRTSEFLRV9GQUlMRUQATE9DS0VEAFRSQU5TRk9STUFUSU9OX0FQUExJRUQATk9UX01PRElGSUVEAE5PVF9FWFRFTkRFRABCQU5EV0lEVEhfTElNSVRfRVhDRUVERUQAU0lURV9JU19PVkVSTE9BREVEAEhFQUQARXhwZWN0ZWQgSFRUUC8sIFJUU1AvIG9yIElDRS8A5xUAAK8VAACkEgAAkhoAACYWAACeFAAA2xkAAHkVAAB+EgAA/hQAADYVAAALFgAA2BYAAPMSAABCGAAArBYAABIVAAAUFwAA7xcAAEgUAABxFwAAshoAAGsZAAB+GQAANRQAAIIaAABEFwAA/RYAAB4YAACHFwAAqhkAAJMSAAAHGAAALBcAAMoXAACkFwAA5xUAAOcVAABYFwAAOxgAAKASAAAtHAAAwxEAAEgRAADeEgAAQhMAAKQZAAD9EAAA9xUAAKUVAADvFgAA+BkAAEoWAABWFgAA9RUAAAoaAAAIGgAAARoAAKsVAABCEgAA1xAAAEwRAAAFGQAAVBYAAB4RAADKGQAAyBkAAE4WAAD/GAAAcRQAAPAVAADuFQAAlBkAAPwVAAC/GQAAmxkAAHwUAABDEQAAcBgAAJUUAAAnFAAAGRQAANUSAADUGQAARBYAAPcQAEG5OwsBAQBB0DsL4AEBAQIBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQBBuj0LBAEAAAIAQdE9C14DBAMDAwMDAAADAwADAwADAwMDAwMDAwMDAAUAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAwADAEG6PwsEAQAAAgBB0T8LXgMAAwMDAwMAAAMDAAMDAAMDAwMDAwMDAwMABAAFAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwADAAMAQbDBAAsNbG9zZWVlcC1hbGl2ZQBBycEACwEBAEHgwQAL4AEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQBBycMACwEBAEHgwwAL5wEBAQEBAQEBAQEBAQECAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAWNodW5rZWQAQfHFAAteAQABAQEBAQAAAQEAAQEAAQEBAQEBAQEBAQAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEAAQBB0McACyFlY3Rpb25lbnQtbGVuZ3Rob25yb3h5LWNvbm5lY3Rpb24AQYDIAAsgcmFuc2Zlci1lbmNvZGluZ3BncmFkZQ0KDQpTTQ0KDQoAQanIAAsFAQIAAQMAQcDIAAtfBAUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUAQanKAAsFAQIAAQMAQcDKAAtfBAUFBgUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUAQanMAAsEAQAAAQBBwcwAC14CAgACAgICAgICAgICAgICAgICAgICAgICAgICAgIAAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAEGpzgALBQECAAEDAEHAzgALXwQFAAAFBQUFBQUFBQUFBQYFBQUFBQUFBQUFBQUABQAHCAUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQAFAAUABQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUAAAAFAEGp0AALBQEBAAEBAEHA0AALAQEAQdrQAAtBAgAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAQanSAAsFAQEAAQEAQcDSAAsBAQBBytIACwYCAAAAAAIAQeHSAAs6AwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwBBoNQAC50BTk9VTkNFRUNLT1VUTkVDVEVURUNSSUJFTFVTSEVURUFEU0VBUkNIUkdFQ1RJVklUWUxFTkRBUlZFT1RJRllQVElPTlNDSFNFQVlTVEFUQ0hHRVVFUllPUkRJUkVDVE9SVFJDSFBBUkFNRVRFUlVSQ0VCU0NSSUJFQVJET1dOQUNFSU5ETktDS1VCU0NSSUJFVFRQQ0VUU1BBRFRQLw==' + return this.#handler.onResponseStart?.(...args) + } -let wasmBuffer + onResponseData (...args) { + assert(!this.#onCompleteCalled) + assert(!this.#onErrorCalled) -Object.defineProperty(module, 'exports', { - get: () => { - return wasmBuffer - ? wasmBuffer - : (wasmBuffer = Buffer.from(wasmBase64, 'base64')) + return this.#handler.onResponseData?.(...args) } -}) + onResponseEnd (...args) { + assert(!this.#onCompleteCalled) + assert(!this.#onErrorCalled) -/***/ }), - -/***/ 8493: -/***/ ((__unused_webpack_module, exports) => { + this.#onCompleteCalled = true + return this.#handler.onResponseEnd?.(...args) + } -"use strict"; + onResponseError (...args) { + this.#onErrorCalled = true + return this.#handler.onResponseError?.(...args) + } -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.enumToMap = enumToMap; -function enumToMap(obj, filter = [], exceptions = []) { - const emptyFilter = (filter?.length ?? 0) === 0; - const emptyExceptions = (exceptions?.length ?? 0) === 0; - return Object.fromEntries(Object.entries(obj).filter(([, value]) => { - return (typeof value === 'number' && - (emptyFilter || filter.includes(value)) && - (emptyExceptions || !exceptions.includes(value))); - })); + /** + * @deprecated + */ + onBodySent () {} } /***/ }), -/***/ 3550: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -"use strict"; - - -const { kClients } = __nccwpck_require__(9562) -const Agent = __nccwpck_require__(2004) -const { - kAgent, - kMockAgentSet, - kMockAgentGet, - kDispatches, - kIsMockActive, - kNetConnect, - kGetNetConnect, - kOptions, - kFactory, - kMockAgentRegisterCallHistory, - kMockAgentIsCallHistoryEnabled, - kMockAgentAddCallHistoryLog, - kMockAgentMockCallHistoryInstance, - kMockAgentAcceptsNonStandardSearchParameters, - kMockCallHistoryAddLog, - kIgnoreTrailingSlash -} = __nccwpck_require__(45) -const MockClient = __nccwpck_require__(1024) -const MockPool = __nccwpck_require__(733) -const { matchValue, normalizeSearchParams, buildAndValidateMockOptions, normalizeOrigin } = __nccwpck_require__(4290) -const { InvalidArgumentError, UndiciError } = __nccwpck_require__(4928) -const Dispatcher = __nccwpck_require__(2096) -const PendingInterceptorsFormatter = __nccwpck_require__(6709) -const { MockCallHistory } = __nccwpck_require__(7686) - -class MockAgent extends Dispatcher { - constructor (opts = {}) { - super(opts) - - const mockOptions = buildAndValidateMockOptions(opts) - - this[kNetConnect] = true - this[kIsMockActive] = true - this[kMockAgentIsCallHistoryEnabled] = mockOptions.enableCallHistory ?? false - this[kMockAgentAcceptsNonStandardSearchParameters] = mockOptions.acceptNonStandardSearchParameters ?? false - this[kIgnoreTrailingSlash] = mockOptions.ignoreTrailingSlash ?? false - - // Instantiate Agent and encapsulate - if (opts?.agent && typeof opts.agent.dispatch !== 'function') { - throw new InvalidArgumentError('Argument opts.agent must implement Agent') - } - const agent = opts?.agent ? opts.agent : new Agent(opts) - this[kAgent] = agent - - this[kClients] = agent[kClients] - this[kOptions] = mockOptions - - if (this[kMockAgentIsCallHistoryEnabled]) { - this[kMockAgentRegisterCallHistory]() - } - } +/***/ 5485: +/***/ ((module) => { - get (origin) { - // Normalize origin to handle URL objects and case-insensitive hostnames - const normalizedOrigin = normalizeOrigin(origin) - const originKey = this[kIgnoreTrailingSlash] ? normalizedOrigin.replace(/\/$/, '') : normalizedOrigin - let dispatcher = this[kMockAgentGet](originKey) - if (!dispatcher) { - dispatcher = this[kFactory](originKey) - this[kMockAgentSet](originKey, dispatcher) - } - return dispatcher - } +/** + * @typedef {import('../../types/dispatcher.d.ts').default.DispatchHandler} DispatchHandler + */ - dispatch (opts, handler) { - opts.origin = normalizeOrigin(opts.origin) +/** + * Handler that buffers response data and notifies multiple waiting handlers. + * Used for request deduplication. + * + * @implements {DispatchHandler} + */ +class DeduplicationHandler { + /** + * @type {DispatchHandler} + */ + #primaryHandler - // Call MockAgent.get to perform additional setup before dispatching as normal - this.get(opts.origin) + /** + * @type {DispatchHandler[]} + */ + #waitingHandlers = [] - this[kMockAgentAddCallHistoryLog](opts) + /** + * @type {Buffer[]} + */ + #chunks = [] - const acceptNonStandardSearchParameters = this[kMockAgentAcceptsNonStandardSearchParameters] + /** + * @type {number} + */ + #statusCode = 0 - const dispatchOpts = { ...opts } + /** + * @type {Record} + */ + #headers = {} - if (acceptNonStandardSearchParameters && dispatchOpts.path) { - const [path, searchParams] = dispatchOpts.path.split('?') - const normalizedSearchParams = normalizeSearchParams(searchParams, acceptNonStandardSearchParameters) - dispatchOpts.path = `${path}?${normalizedSearchParams}` - } + /** + * @type {string} + */ + #statusMessage = '' - return this[kAgent].dispatch(dispatchOpts, handler) - } + /** + * @type {boolean} + */ + #aborted = false - async close () { - this.clearCallHistory() - await this[kAgent].close() - this[kClients].clear() - } + /** + * @type {import('../../types/dispatcher.d.ts').default.DispatchController | null} + */ + #controller = null - deactivate () { - this[kIsMockActive] = false - } + /** + * @type {(() => void) | null} + */ + #onComplete = null - activate () { - this[kIsMockActive] = true + /** + * @param {DispatchHandler} primaryHandler The primary handler + * @param {() => void} onComplete Callback when request completes + */ + constructor (primaryHandler, onComplete) { + this.#primaryHandler = primaryHandler + this.#onComplete = onComplete } - enableNetConnect (matcher) { - if (typeof matcher === 'string' || typeof matcher === 'function' || matcher instanceof RegExp) { - if (Array.isArray(this[kNetConnect])) { - this[kNetConnect].push(matcher) - } else { - this[kNetConnect] = [matcher] - } - } else if (typeof matcher === 'undefined') { - this[kNetConnect] = true - } else { - throw new InvalidArgumentError('Unsupported matcher. Must be one of String|Function|RegExp.') - } + /** + * Add a waiting handler that will receive the buffered response + * @param {DispatchHandler} handler + */ + addWaitingHandler (handler) { + this.#waitingHandlers.push(handler) } - disableNetConnect () { - this[kNetConnect] = false + /** + * @param {() => void} abort + * @param {any} context + */ + onRequestStart (controller, context) { + this.#controller = controller + this.#primaryHandler.onRequestStart?.(controller, context) } - enableCallHistory () { - this[kMockAgentIsCallHistoryEnabled] = true - - return this + /** + * @param {import('../../types/dispatcher.d.ts').default.DispatchController} controller + * @param {number} statusCode + * @param {import('../../types/header.d.ts').IncomingHttpHeaders} headers + * @param {Socket} socket + */ + onRequestUpgrade (controller, statusCode, headers, socket) { + this.#primaryHandler.onRequestUpgrade?.(controller, statusCode, headers, socket) } - disableCallHistory () { - this[kMockAgentIsCallHistoryEnabled] = false - - return this + /** + * @param {import('../../types/dispatcher.d.ts').default.DispatchController} controller + * @param {number} statusCode + * @param {Record} headers + * @param {string} statusMessage + */ + onResponseStart (controller, statusCode, headers, statusMessage) { + this.#statusCode = statusCode + this.#headers = headers + this.#statusMessage = statusMessage + this.#primaryHandler.onResponseStart?.(controller, statusCode, headers, statusMessage) } - getCallHistory () { - return this[kMockAgentMockCallHistoryInstance] + /** + * @param {import('../../types/dispatcher.d.ts').default.DispatchController} controller + * @param {Buffer} chunk + */ + onResponseData (controller, chunk) { + // Buffer the chunk for waiting handlers + this.#chunks.push(Buffer.from(chunk)) + this.#primaryHandler.onResponseData?.(controller, chunk) } - clearCallHistory () { - if (this[kMockAgentMockCallHistoryInstance] !== undefined) { - this[kMockAgentMockCallHistoryInstance].clear() - } + /** + * @param {import('../../types/dispatcher.d.ts').default.DispatchController} controller + * @param {object} trailers + */ + onResponseEnd (controller, trailers) { + this.#primaryHandler.onResponseEnd?.(controller, trailers) + this.#notifyWaitingHandlers() + this.#onComplete?.() } - // This is required to bypass issues caused by using global symbols - see: - // https://github.com/nodejs/undici/issues/1447 - get isMockActive () { - return this[kIsMockActive] + /** + * @param {import('../../types/dispatcher.d.ts').default.DispatchController} controller + * @param {Error} err + */ + onResponseError (controller, err) { + this.#aborted = true + this.#primaryHandler.onResponseError?.(controller, err) + this.#notifyWaitingHandlersError(err) + this.#onComplete?.() } - [kMockAgentRegisterCallHistory] () { - if (this[kMockAgentMockCallHistoryInstance] === undefined) { - this[kMockAgentMockCallHistoryInstance] = new MockCallHistory() - } - } + /** + * Notify all waiting handlers with the buffered response + */ + #notifyWaitingHandlers () { + const body = Buffer.concat(this.#chunks) - [kMockAgentAddCallHistoryLog] (opts) { - if (this[kMockAgentIsCallHistoryEnabled]) { - // additional setup when enableCallHistory class method is used after mockAgent instantiation - this[kMockAgentRegisterCallHistory]() + for (const handler of this.#waitingHandlers) { + // Create a simple controller for each waiting handler + const waitingController = { + resume () {}, + pause () {}, + get paused () { return false }, + get aborted () { return false }, + get reason () { return null }, + abort () {} + } - // add call history log on every call (intercepted or not) - this[kMockAgentMockCallHistoryInstance][kMockCallHistoryAddLog](opts) - } - } + try { + handler.onRequestStart?.(waitingController, null) - [kMockAgentSet] (origin, dispatcher) { - this[kClients].set(origin, { count: 0, dispatcher }) - } + if (waitingController.aborted) { + continue + } - [kFactory] (origin) { - const mockOptions = Object.assign({ agent: this }, this[kOptions]) - return this[kOptions] && this[kOptions].connections === 1 - ? new MockClient(origin, mockOptions) - : new MockPool(origin, mockOptions) - } + handler.onResponseStart?.( + waitingController, + this.#statusCode, + this.#headers, + this.#statusMessage + ) - [kMockAgentGet] (origin) { - // First check if we can immediately find it - const result = this[kClients].get(origin) - if (result?.dispatcher) { - return result.dispatcher - } + if (waitingController.aborted) { + continue + } - // If the origin is not a string create a dummy parent pool and return to user - if (typeof origin !== 'string') { - const dispatcher = this[kFactory]('http://localhost:9999') - this[kMockAgentSet](origin, dispatcher) - return dispatcher - } + if (body.length > 0) { + handler.onResponseData?.(waitingController, body) + } - // If we match, create a pool and assign the same dispatches - for (const [keyMatcher, result] of Array.from(this[kClients])) { - if (result && typeof keyMatcher !== 'string' && matchValue(keyMatcher, origin)) { - const dispatcher = this[kFactory](origin) - this[kMockAgentSet](origin, dispatcher) - dispatcher[kDispatches] = result.dispatcher[kDispatches] - return dispatcher + handler.onResponseEnd?.(waitingController, {}) + } catch { + // Ignore errors from waiting handlers } } - } - - [kGetNetConnect] () { - return this[kNetConnect] - } - pendingInterceptors () { - const mockAgentClients = this[kClients] - - return Array.from(mockAgentClients.entries()) - .flatMap(([origin, result]) => result.dispatcher[kDispatches].map(dispatch => ({ ...dispatch, origin }))) - .filter(({ pending }) => pending) + this.#waitingHandlers = [] + this.#chunks = [] } - assertNoPendingInterceptors ({ pendingInterceptorsFormatter = new PendingInterceptorsFormatter() } = {}) { - const pending = this.pendingInterceptors() + /** + * Notify all waiting handlers of an error + * @param {Error} err + */ + #notifyWaitingHandlersError (err) { + for (const handler of this.#waitingHandlers) { + const waitingController = { + resume () {}, + pause () {}, + get paused () { return false }, + get aborted () { return true }, + get reason () { return err }, + abort () {} + } - if (pending.length === 0) { - return + try { + handler.onRequestStart?.(waitingController, null) + handler.onResponseError?.(waitingController, err) + } catch { + // Ignore errors from waiting handlers + } } - throw new UndiciError( - pending.length === 1 - ? `1 interceptor is pending:\n\n${pendingInterceptorsFormatter.format(pending)}`.trim() - : `${pending.length} interceptors are pending:\n\n${pendingInterceptorsFormatter.format(pending)}`.trim() - ) + this.#waitingHandlers = [] + this.#chunks = [] } } -module.exports = MockAgent +module.exports = DeduplicationHandler /***/ }), -/***/ 7686: +/***/ 4628: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; - -const { kMockCallHistoryAddLog } = __nccwpck_require__(45) -const { InvalidArgumentError } = __nccwpck_require__(4928) -function handleFilterCallsWithOptions (criteria, options, handler, store) { - switch (options.operator) { - case 'OR': - store.push(...handler(criteria)) +const util = __nccwpck_require__(2550) +const { kBodyUsed } = __nccwpck_require__(8261) +const assert = __nccwpck_require__(4589) +const { InvalidArgumentError } = __nccwpck_require__(5093) +const EE = __nccwpck_require__(8474) - return store - case 'AND': - return handler.call({ logs: store }, criteria) - default: - // guard -- should never happens because buildAndValidateFilterCallsOptions is called before - throw new InvalidArgumentError('options.operator must to be a case insensitive string equal to \'OR\' or \'AND\'') - } -} +const redirectableStatusCodes = [300, 301, 302, 303, 307, 308] -function buildAndValidateFilterCallsOptions (options = {}) { - const finalOptions = {} +const kBody = Symbol('body') - if ('operator' in options) { - if (typeof options.operator !== 'string' || (options.operator.toUpperCase() !== 'OR' && options.operator.toUpperCase() !== 'AND')) { - throw new InvalidArgumentError('options.operator must to be a case insensitive string equal to \'OR\' or \'AND\'') - } +const noop = () => {} - return { - ...finalOptions, - operator: options.operator.toUpperCase() - } +class BodyAsyncIterable { + constructor (body) { + this[kBody] = body + this[kBodyUsed] = false } - return finalOptions + async * [Symbol.asyncIterator] () { + assert(!this[kBodyUsed], 'disturbed') + this[kBodyUsed] = true + yield * this[kBody] + } } -function makeFilterCalls (parameterName) { - return (parameterValue) => { - if (typeof parameterValue === 'string' || parameterValue == null) { - return this.logs.filter((log) => { - return log[parameterName] === parameterValue - }) - } - if (parameterValue instanceof RegExp) { - return this.logs.filter((log) => { - return parameterValue.test(log[parameterName]) - }) +class RedirectHandler { + static buildDispatch (dispatcher, maxRedirections) { + if (maxRedirections != null && (!Number.isInteger(maxRedirections) || maxRedirections < 0)) { + throw new InvalidArgumentError('maxRedirections must be a positive number') } - throw new InvalidArgumentError(`${parameterName} parameter should be one of string, regexp, undefined or null`) + const dispatch = dispatcher.dispatch.bind(dispatcher) + return (opts, originalHandler) => dispatch(opts, new RedirectHandler(dispatch, maxRedirections, opts, originalHandler)) } -} -function computeUrlWithMaybeSearchParameters (requestInit) { - // path can contains query url parameters - // or query can contains query url parameters - try { - const url = new URL(requestInit.path, requestInit.origin) - // requestInit.path contains query url parameters - // requestInit.query is then undefined - if (url.search.length !== 0) { - return url + constructor (dispatch, maxRedirections, opts, handler) { + if (maxRedirections != null && (!Number.isInteger(maxRedirections) || maxRedirections < 0)) { + throw new InvalidArgumentError('maxRedirections must be a positive number') } - // requestInit.query can be populated here - url.search = new URLSearchParams(requestInit.query).toString() + this.dispatch = dispatch + this.location = null + const { maxRedirections: _, ...cleanOpts } = opts + this.opts = cleanOpts // opts must be a copy, exclude maxRedirections + this.maxRedirections = maxRedirections + this.handler = handler + this.history = [] - return url - } catch (error) { - throw new InvalidArgumentError('An error occurred when computing MockCallHistoryLog.url', { cause: error }) - } -} + if (util.isStream(this.opts.body)) { + // TODO (fix): Provide some way for the user to cache the file to e.g. /tmp + // so that it can be dispatched again? + // TODO (fix): Do we need 100-expect support to provide a way to do this properly? + if (util.bodyLength(this.opts.body) === 0) { + this.opts.body + .on('data', function () { + assert(false) + }) + } -class MockCallHistoryLog { - constructor (requestInit = {}) { - this.body = requestInit.body - this.headers = requestInit.headers - this.method = requestInit.method - - const url = computeUrlWithMaybeSearchParameters(requestInit) - - this.fullUrl = url.toString() - this.origin = url.origin - this.path = url.pathname - this.searchParams = Object.fromEntries(url.searchParams) - this.protocol = url.protocol - this.host = url.host - this.port = url.port - this.hash = url.hash - } - - toMap () { - return new Map([ - ['protocol', this.protocol], - ['host', this.host], - ['port', this.port], - ['origin', this.origin], - ['path', this.path], - ['hash', this.hash], - ['searchParams', this.searchParams], - ['fullUrl', this.fullUrl], - ['method', this.method], - ['body', this.body], - ['headers', this.headers]] - ) - } - - toString () { - const options = { betweenKeyValueSeparator: '->', betweenPairSeparator: '|' } - let result = '' - - this.toMap().forEach((value, key) => { - if (typeof value === 'string' || value === undefined || value === null) { - result = `${result}${key}${options.betweenKeyValueSeparator}${value}${options.betweenPairSeparator}` - } - if ((typeof value === 'object' && value !== null) || Array.isArray(value)) { - result = `${result}${key}${options.betweenKeyValueSeparator}${JSON.stringify(value)}${options.betweenPairSeparator}` + if (typeof this.opts.body.readableDidRead !== 'boolean') { + this.opts.body[kBodyUsed] = false + EE.prototype.on.call(this.opts.body, 'data', function () { + this[kBodyUsed] = true + }) } - // maybe miss something for non Record / Array headers and searchParams here - }) - - // delete last betweenPairSeparator - return result.slice(0, -1) - } -} - -class MockCallHistory { - logs = [] - - calls () { - return this.logs + } else if (this.opts.body && typeof this.opts.body.pipeTo === 'function') { + // TODO (fix): We can't access ReadableStream internal state + // to determine whether or not it has been disturbed. This is just + // a workaround. + this.opts.body = new BodyAsyncIterable(this.opts.body) + } else if ( + this.opts.body && + typeof this.opts.body !== 'string' && + !ArrayBuffer.isView(this.opts.body) && + util.isIterable(this.opts.body) && + !util.isFormDataLike(this.opts.body) + ) { + // TODO: Should we allow re-using iterable if !this.opts.idempotent + // or through some other flag? + this.opts.body = new BodyAsyncIterable(this.opts.body) + } } - firstCall () { - return this.logs.at(0) + onRequestStart (controller, context) { + this.handler.onRequestStart?.(controller, { ...context, history: this.history }) } - lastCall () { - return this.logs.at(-1) + onRequestUpgrade (controller, statusCode, headers, socket) { + this.handler.onRequestUpgrade?.(controller, statusCode, headers, socket) } - nthCall (number) { - if (typeof number !== 'number') { - throw new InvalidArgumentError('nthCall must be called with a number') + onResponseStart (controller, statusCode, headers, statusMessage) { + if (this.opts.throwOnMaxRedirect && this.history.length >= this.maxRedirections) { + throw new Error('max redirects') } - if (!Number.isInteger(number)) { - throw new InvalidArgumentError('nthCall must be called with an integer') + + // https://tools.ietf.org/html/rfc7231#section-6.4.2 + // https://fetch.spec.whatwg.org/#http-redirect-fetch + // In case of HTTP 301 or 302 with POST, change the method to GET + if ((statusCode === 301 || statusCode === 302) && this.opts.method === 'POST') { + this.opts.method = 'GET' + if (util.isStream(this.opts.body)) { + util.destroy(this.opts.body.on('error', noop)) + } + this.opts.body = null } - if (Math.sign(number) !== 1) { - throw new InvalidArgumentError('nthCall must be called with a positive value. use firstCall or lastCall instead') + + // https://tools.ietf.org/html/rfc7231#section-6.4.4 + // In case of HTTP 303, always replace method to be either HEAD or GET + if (statusCode === 303 && this.opts.method !== 'HEAD') { + this.opts.method = 'GET' + if (util.isStream(this.opts.body)) { + util.destroy(this.opts.body.on('error', noop)) + } + this.opts.body = null } - // non zero based index. this is more human readable - return this.logs.at(number - 1) - } + this.location = this.history.length >= this.maxRedirections || util.isDisturbed(this.opts.body) || redirectableStatusCodes.indexOf(statusCode) === -1 + ? null + : headers.location - filterCalls (criteria, options) { - // perf - if (this.logs.length === 0) { - return this.logs - } - if (typeof criteria === 'function') { - return this.logs.filter(criteria) + if (this.opts.origin) { + this.history.push(new URL(this.opts.path, this.opts.origin)) } - if (criteria instanceof RegExp) { - return this.logs.filter((log) => { - return criteria.test(log.toString()) - }) + + if (!this.location) { + this.handler.onResponseStart?.(controller, statusCode, headers, statusMessage) + return } - if (typeof criteria === 'object' && criteria !== null) { - // no criteria - returning all logs - if (Object.keys(criteria).length === 0) { - return this.logs - } - const finalOptions = { operator: 'OR', ...buildAndValidateFilterCallsOptions(options) } + const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin))) + const path = search ? `${pathname}${search}` : pathname - let maybeDuplicatedLogsFiltered = [] - if ('protocol' in criteria) { - maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.protocol, finalOptions, this.filterCallsByProtocol, maybeDuplicatedLogsFiltered) - } - if ('host' in criteria) { - maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.host, finalOptions, this.filterCallsByHost, maybeDuplicatedLogsFiltered) - } - if ('port' in criteria) { - maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.port, finalOptions, this.filterCallsByPort, maybeDuplicatedLogsFiltered) - } - if ('origin' in criteria) { - maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.origin, finalOptions, this.filterCallsByOrigin, maybeDuplicatedLogsFiltered) - } - if ('path' in criteria) { - maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.path, finalOptions, this.filterCallsByPath, maybeDuplicatedLogsFiltered) - } - if ('hash' in criteria) { - maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.hash, finalOptions, this.filterCallsByHash, maybeDuplicatedLogsFiltered) - } - if ('fullUrl' in criteria) { - maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.fullUrl, finalOptions, this.filterCallsByFullUrl, maybeDuplicatedLogsFiltered) - } - if ('method' in criteria) { - maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.method, finalOptions, this.filterCallsByMethod, maybeDuplicatedLogsFiltered) + // Check for redirect loops by seeing if we've already visited this URL in our history + // This catches the case where Client/Pool try to handle cross-origin redirects but fail + // and keep redirecting to the same URL in an infinite loop + const redirectUrlString = `${origin}${path}` + for (const historyUrl of this.history) { + if (historyUrl.toString() === redirectUrlString) { + throw new InvalidArgumentError(`Redirect loop detected. Cannot redirect to ${origin}. This typically happens when using a Client or Pool with cross-origin redirects. Use an Agent for cross-origin redirects.`) } - - const uniqLogsFiltered = [...new Set(maybeDuplicatedLogsFiltered)] - - return uniqLogsFiltered } - throw new InvalidArgumentError('criteria parameter should be one of function, regexp, or object') + // Remove headers referring to the original URL. + // By default it is Host only, unless it's a 303 (see below), which removes also all Content-* headers. + // https://tools.ietf.org/html/rfc7231#section-6.4 + this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin) + this.opts.path = path + this.opts.origin = origin + this.opts.query = null } - filterCallsByProtocol = makeFilterCalls.call(this, 'protocol') - - filterCallsByHost = makeFilterCalls.call(this, 'host') + onResponseData (controller, chunk) { + if (this.location) { + /* + https://tools.ietf.org/html/rfc7231#section-6.4 - filterCallsByPort = makeFilterCalls.call(this, 'port') + TLDR: undici always ignores 3xx response bodies. - filterCallsByOrigin = makeFilterCalls.call(this, 'origin') + Redirection is used to serve the requested resource from another URL, so it assumes that + no body is generated (and thus can be ignored). Even though generating a body is not prohibited. - filterCallsByPath = makeFilterCalls.call(this, 'path') + For status 301, 302, 303, 307 and 308 (the latter from RFC 7238), the specs mention that the body usually + (which means it's optional and not mandated) contain just an hyperlink to the value of + the Location response header, so the body can be ignored safely. - filterCallsByHash = makeFilterCalls.call(this, 'hash') + For status 300, which is "Multiple Choices", the spec mentions both generating a Location + response header AND a response body with the other possible location to follow. + Since the spec explicitly chooses not to specify a format for such body and leave it to + servers and browsers implementors, we ignore the body as there is no specified way to eventually parse it. + */ + } else { + this.handler.onResponseData?.(controller, chunk) + } + } - filterCallsByFullUrl = makeFilterCalls.call(this, 'fullUrl') + onResponseEnd (controller, trailers) { + if (this.location) { + /* + https://tools.ietf.org/html/rfc7231#section-6.4 - filterCallsByMethod = makeFilterCalls.call(this, 'method') + TLDR: undici always ignores 3xx response trailers as they are not expected in case of redirections + and neither are useful if present. - clear () { - this.logs = [] + See comment on onData method above for more detailed information. + */ + this.dispatch(this.opts, this) + } else { + this.handler.onResponseEnd(controller, trailers) + } } - [kMockCallHistoryAddLog] (requestInit) { - const log = new MockCallHistoryLog(requestInit) - - this.logs.push(log) + onResponseError (controller, error) { + this.handler.onResponseError?.(controller, error) + } +} - return log +// https://tools.ietf.org/html/rfc7231#section-6.4.4 +function shouldRemoveHeader (header, removeContent, unknownOrigin) { + if (header.length === 4) { + return util.headerNameToString(header) === 'host' + } + if (removeContent && util.headerNameToString(header).startsWith('content-')) { + return true + } + if (unknownOrigin && (header.length === 13 || header.length === 6 || header.length === 19)) { + const name = util.headerNameToString(header) + return name === 'authorization' || name === 'cookie' || name === 'proxy-authorization' } + return false +} - * [Symbol.iterator] () { - for (const log of this.calls()) { - yield log +// https://tools.ietf.org/html/rfc7231#section-6.4 +function cleanRequestHeaders (headers, removeContent, unknownOrigin) { + const ret = [] + if (Array.isArray(headers)) { + for (let i = 0; i < headers.length; i += 2) { + if (!shouldRemoveHeader(headers[i], removeContent, unknownOrigin)) { + ret.push(headers[i], headers[i + 1]) + } + } + } else if (headers && typeof headers === 'object') { + const entries = typeof headers[Symbol.iterator] === 'function' ? headers : Object.entries(headers) + for (const [key, value] of entries) { + if (!shouldRemoveHeader(key, removeContent, unknownOrigin)) { + ret.push(key, value) + } } + } else { + assert(headers == null, 'headers must be an object or an array') } + return ret } -module.exports.MockCallHistory = MockCallHistory -module.exports.MockCallHistoryLog = MockCallHistoryLog +module.exports = RedirectHandler /***/ }), -/***/ 1024: +/***/ 1557: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; +const assert = __nccwpck_require__(4589) -const { promisify } = __nccwpck_require__(7975) -const Client = __nccwpck_require__(226) -const { buildMockDispatch } = __nccwpck_require__(4290) +const { kRetryHandlerDefaultRetry } = __nccwpck_require__(8261) +const { RequestRetryError } = __nccwpck_require__(5093) +const WrapHandler = __nccwpck_require__(6444) const { - kDispatches, - kMockAgent, - kClose, - kOriginalClose, - kOrigin, - kOriginalDispatch, - kConnected, - kIgnoreTrailingSlash -} = __nccwpck_require__(45) -const { MockInterceptor } = __nccwpck_require__(2156) -const Symbols = __nccwpck_require__(9562) -const { InvalidArgumentError } = __nccwpck_require__(4928) + isDisturbed, + parseRangeHeader, + wrapRequestBody +} = __nccwpck_require__(2550) -/** - * MockClient provides an API that extends the Client to influence the mockDispatches. - */ -class MockClient extends Client { - constructor (origin, opts) { - if (!opts || !opts.agent || typeof opts.agent.dispatch !== 'function') { - throw new InvalidArgumentError('Argument opts.agent must implement Agent') - } +function calculateRetryAfterHeader (retryAfter) { + const retryTime = new Date(retryAfter).getTime() + return isNaN(retryTime) ? 0 : retryTime - Date.now() +} - super(origin, opts) +class RetryHandler { + constructor (opts, { dispatch, handler }) { + const { retryOptions, ...dispatchOpts } = opts + const { + // Retry scoped + retry: retryFn, + maxRetries, + maxTimeout, + minTimeout, + timeoutFactor, + // Response scoped + methods, + errorCodes, + retryAfter, + statusCodes, + throwOnError + } = retryOptions ?? {} - this[kMockAgent] = opts.agent - this[kOrigin] = origin - this[kIgnoreTrailingSlash] = opts.ignoreTrailingSlash ?? false - this[kDispatches] = [] - this[kConnected] = 1 - this[kOriginalDispatch] = this.dispatch - this[kOriginalClose] = this.close.bind(this) + this.error = null + this.dispatch = dispatch + this.handler = WrapHandler.wrap(handler) + this.opts = { ...dispatchOpts, body: wrapRequestBody(opts.body) } + this.retryOpts = { + throwOnError: throwOnError ?? true, + retry: retryFn ?? RetryHandler[kRetryHandlerDefaultRetry], + retryAfter: retryAfter ?? true, + maxTimeout: maxTimeout ?? 30 * 1000, // 30s, + minTimeout: minTimeout ?? 500, // .5s + timeoutFactor: timeoutFactor ?? 2, + maxRetries: maxRetries ?? 5, + // What errors we should retry + methods: methods ?? ['GET', 'HEAD', 'OPTIONS', 'PUT', 'DELETE', 'TRACE'], + // Indicates which errors to retry + statusCodes: statusCodes ?? [500, 502, 503, 504, 429], + // List of errors to retry + errorCodes: errorCodes ?? [ + 'ECONNRESET', + 'ECONNREFUSED', + 'ENOTFOUND', + 'ENETDOWN', + 'ENETUNREACH', + 'EHOSTDOWN', + 'EHOSTUNREACH', + 'EPIPE', + 'UND_ERR_SOCKET' + ] + } - this.dispatch = buildMockDispatch.call(this) - this.close = this[kClose] + this.retryCount = 0 + this.retryCountCheckpoint = 0 + this.headersSent = false + this.start = 0 + this.end = null + this.etag = null } - get [Symbols.kConnected] () { - return this[kConnected] - } + onResponseStartWithRetry (controller, statusCode, headers, statusMessage, err) { + if (this.retryOpts.throwOnError) { + // Preserve old behavior for status codes that are not eligible for retry + if (this.retryOpts.statusCodes.includes(statusCode) === false) { + this.headersSent = true + this.handler.onResponseStart?.(controller, statusCode, headers, statusMessage) + } else { + this.error = err + } - /** - * Sets up the base interceptor for mocking replies from undici. - */ - intercept (opts) { - return new MockInterceptor( - opts && { ignoreTrailingSlash: this[kIgnoreTrailingSlash], ...opts }, - this[kDispatches] + return + } + + if (isDisturbed(this.opts.body)) { + this.headersSent = true + this.handler.onResponseStart?.(controller, statusCode, headers, statusMessage) + return + } + + function shouldRetry (passedErr) { + if (passedErr) { + this.headersSent = true + this.handler.onResponseStart?.(controller, statusCode, headers, statusMessage) + controller.resume() + return + } + + this.error = err + controller.resume() + } + + controller.pause() + this.retryOpts.retry( + err, + { + state: { counter: this.retryCount }, + opts: { retryOptions: this.retryOpts, ...this.opts } + }, + shouldRetry.bind(this) ) } - cleanMocks () { - this[kDispatches] = [] + onRequestStart (controller, context) { + if (!this.headersSent) { + this.handler.onRequestStart?.(controller, context) + } } - async [kClose] () { - await promisify(this[kOriginalClose])() - this[kConnected] = 0 - this[kMockAgent][Symbols.kClients].delete(this[kOrigin]) + onRequestUpgrade (controller, statusCode, headers, socket) { + this.handler.onRequestUpgrade?.(controller, statusCode, headers, socket) } -} - -module.exports = MockClient - - -/***/ }), -/***/ 9664: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + static [kRetryHandlerDefaultRetry] (err, { state, opts }, cb) { + const { statusCode, code, headers } = err + const { method, retryOptions } = opts + const { + maxRetries, + minTimeout, + maxTimeout, + timeoutFactor, + statusCodes, + errorCodes, + methods + } = retryOptions + const { counter } = state -"use strict"; + // Any code that is not a Undici's originated and allowed to retry + if (code && code !== 'UND_ERR_REQ_RETRY' && !errorCodes.includes(code)) { + cb(err) + return + } + // If a set of method are provided and the current method is not in the list + if (Array.isArray(methods) && !methods.includes(method)) { + cb(err) + return + } -const { UndiciError } = __nccwpck_require__(4928) + // If a set of status code are provided and the current status code is not in the list + if ( + statusCode != null && + Array.isArray(statusCodes) && + !statusCodes.includes(statusCode) + ) { + cb(err) + return + } -const kMockNotMatchedError = Symbol.for('undici.error.UND_MOCK_ERR_MOCK_NOT_MATCHED') + // If we reached the max number of retries + if (counter > maxRetries) { + cb(err) + return + } -/** - * The request does not match any registered mock dispatches. - */ -class MockNotMatchedError extends UndiciError { - constructor (message) { - super(message) - this.name = 'MockNotMatchedError' - this.message = message || 'The request does not match any registered mock dispatches' - this.code = 'UND_MOCK_ERR_MOCK_NOT_MATCHED' - } + let retryAfterHeader = headers?.['retry-after'] + if (retryAfterHeader) { + retryAfterHeader = Number(retryAfterHeader) + retryAfterHeader = Number.isNaN(retryAfterHeader) + ? calculateRetryAfterHeader(headers['retry-after']) + : retryAfterHeader * 1e3 // Retry-After is in seconds + } - static [Symbol.hasInstance] (instance) { - return instance && instance[kMockNotMatchedError] === true - } + const retryTimeout = + retryAfterHeader > 0 + ? Math.min(retryAfterHeader, maxTimeout) + : Math.min(minTimeout * timeoutFactor ** (counter - 1), maxTimeout) - get [kMockNotMatchedError] () { - return true + setTimeout(() => cb(null), retryTimeout) } -} -module.exports = { - MockNotMatchedError -} + onResponseStart (controller, statusCode, headers, statusMessage) { + this.error = null + this.retryCount += 1 + if (statusCode >= 300) { + const err = new RequestRetryError('Request failed', statusCode, { + headers, + data: { + count: this.retryCount + } + }) -/***/ }), + this.onResponseStartWithRetry(controller, statusCode, headers, statusMessage, err) + return + } -/***/ 2156: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // Checkpoint for resume from where we left it + if (this.headersSent) { + // Only Partial Content 206 supposed to provide Content-Range, + // any other status code that partially consumed the payload + // should not be retried because it would result in downstream + // wrongly concatenate multiple responses. + if (statusCode !== 206 && (this.start > 0 || statusCode !== 200)) { + throw new RequestRetryError('server does not support the range header and the payload was partially consumed', statusCode, { + headers, + data: { count: this.retryCount } + }) + } -"use strict"; + const contentRange = parseRangeHeader(headers['content-range']) + // If no content range + if (!contentRange) { + // We always throw here as we want to indicate that we entred unexpected path + throw new RequestRetryError('Content-Range mismatch', statusCode, { + headers, + data: { count: this.retryCount } + }) + } + // Let's start with a weak etag check + if (this.etag != null && this.etag !== headers.etag) { + // We always throw here as we want to indicate that we entred unexpected path + throw new RequestRetryError('ETag mismatch', statusCode, { + headers, + data: { count: this.retryCount } + }) + } -const { getResponseData, buildKey, addMockDispatch } = __nccwpck_require__(4290) -const { - kDispatches, - kDispatchKey, - kDefaultHeaders, - kDefaultTrailers, - kContentLength, - kMockDispatch, - kIgnoreTrailingSlash -} = __nccwpck_require__(45) -const { InvalidArgumentError } = __nccwpck_require__(4928) -const { serializePathWithQuery } = __nccwpck_require__(983) + const { start, size, end = size ? size - 1 : null } = contentRange -/** - * Defines the scope API for an interceptor reply - */ -class MockScope { - constructor (mockDispatch) { - this[kMockDispatch] = mockDispatch - } + assert(this.start === start, 'content-range mismatch') + assert(this.end == null || this.end === end, 'content-range mismatch') - /** - * Delay a reply by a set amount in ms. - */ - delay (waitInMs) { - if (typeof waitInMs !== 'number' || !Number.isInteger(waitInMs) || waitInMs <= 0) { - throw new InvalidArgumentError('waitInMs must be a valid integer > 0') + return } - this[kMockDispatch].delay = waitInMs - return this - } + if (this.end == null) { + if (statusCode === 206) { + // First time we receive 206 + const range = parseRangeHeader(headers['content-range']) - /** - * For a defined reply, never mark as consumed. - */ - persist () { - this[kMockDispatch].persist = true - return this - } + if (range == null) { + this.headersSent = true + this.handler.onResponseStart?.( + controller, + statusCode, + headers, + statusMessage + ) + return + } - /** - * Allow one to define a reply for a set amount of matching requests. - */ - times (repeatTimes) { - if (typeof repeatTimes !== 'number' || !Number.isInteger(repeatTimes) || repeatTimes <= 0) { - throw new InvalidArgumentError('repeatTimes must be a valid integer > 0') - } + const { start, size, end = size ? size - 1 : null } = range + assert( + start != null && Number.isFinite(start), + 'content-range mismatch' + ) + assert(end != null && Number.isFinite(end), 'invalid content-length') - this[kMockDispatch].times = repeatTimes - return this - } -} + this.start = start + this.end = end + } -/** - * Defines an interceptor for a Mock - */ -class MockInterceptor { - constructor (opts, mockDispatches) { - if (typeof opts !== 'object') { - throw new InvalidArgumentError('opts must be an object') - } - if (typeof opts.path === 'undefined') { - throw new InvalidArgumentError('opts.path must be defined') - } - if (typeof opts.method === 'undefined') { - opts.method = 'GET' - } - // See https://github.com/nodejs/undici/issues/1245 - // As per RFC 3986, clients are not supposed to send URI - // fragments to servers when they retrieve a document, - if (typeof opts.path === 'string') { - if (opts.query) { - opts.path = serializePathWithQuery(opts.path, opts.query) - } else { - // Matches https://github.com/nodejs/undici/blob/main/lib/web/fetch/index.js#L1811 - const parsedURL = new URL(opts.path, 'data://') - opts.path = parsedURL.pathname + parsedURL.search + // We make our best to checkpoint the body for further range headers + if (this.end == null) { + const contentLength = headers['content-length'] + this.end = contentLength != null ? Number(contentLength) - 1 : null } - } - if (typeof opts.method === 'string') { - opts.method = opts.method.toUpperCase() - } - this[kDispatchKey] = buildKey(opts) - this[kDispatches] = mockDispatches - this[kIgnoreTrailingSlash] = opts.ignoreTrailingSlash ?? false - this[kDefaultHeaders] = {} - this[kDefaultTrailers] = {} - this[kContentLength] = false - } + assert(Number.isFinite(this.start)) + assert( + this.end == null || Number.isFinite(this.end), + 'invalid content-length' + ) - createMockScopeDispatchData ({ statusCode, data, responseOptions }) { - const responseData = getResponseData(data) - const contentLength = this[kContentLength] ? { 'content-length': responseData.length } : {} - const headers = { ...this[kDefaultHeaders], ...contentLength, ...responseOptions.headers } - const trailers = { ...this[kDefaultTrailers], ...responseOptions.trailers } + this.resume = true + this.etag = headers.etag != null ? headers.etag : null - return { statusCode, data, headers, trailers } - } + // Weak etags are not useful for comparison nor cache + // for instance not safe to assume if the response is byte-per-byte + // equal + if ( + this.etag != null && + this.etag[0] === 'W' && + this.etag[1] === '/' + ) { + this.etag = null + } - validateReplyParameters (replyParameters) { - if (typeof replyParameters.statusCode === 'undefined') { - throw new InvalidArgumentError('statusCode must be defined') - } - if (typeof replyParameters.responseOptions !== 'object' || replyParameters.responseOptions === null) { - throw new InvalidArgumentError('responseOptions must be an object') + this.headersSent = true + this.handler.onResponseStart?.( + controller, + statusCode, + headers, + statusMessage + ) + } else { + throw new RequestRetryError('Request failed', statusCode, { + headers, + data: { count: this.retryCount } + }) } } - /** - * Mock an undici request with a defined reply. - */ - reply (replyOptionsCallbackOrStatusCode) { - // Values of reply aren't available right now as they - // can only be available when the reply callback is invoked. - if (typeof replyOptionsCallbackOrStatusCode === 'function') { - // We'll first wrap the provided callback in another function, - // this function will properly resolve the data from the callback - // when invoked. - const wrappedDefaultsCallback = (opts) => { - // Our reply options callback contains the parameter for statusCode, data and options. - const resolvedData = replyOptionsCallbackOrStatusCode(opts) + onResponseData (controller, chunk) { + if (this.error) { + return + } - // Check if it is in the right format - if (typeof resolvedData !== 'object' || resolvedData === null) { - throw new InvalidArgumentError('reply options callback must return an object') - } + this.start += chunk.length - const replyParameters = { data: '', responseOptions: {}, ...resolvedData } - this.validateReplyParameters(replyParameters) - // Since the values can be obtained immediately we return them - // from this higher order function that will be resolved later. - return { - ...this.createMockScopeDispatchData(replyParameters) - } - } + this.handler.onResponseData?.(controller, chunk) + } - // Add usual dispatch data, but this time set the data parameter to function that will eventually provide data. - const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], wrappedDefaultsCallback, { ignoreTrailingSlash: this[kIgnoreTrailingSlash] }) - return new MockScope(newMockDispatch) + onResponseEnd (controller, trailers) { + if (this.error && this.retryOpts.throwOnError) { + throw this.error } - // We can have either one or three parameters, if we get here, - // we should have 1-3 parameters. So we spread the arguments of - // this function to obtain the parameters, since replyData will always - // just be the statusCode. - const replyParameters = { - statusCode: replyOptionsCallbackOrStatusCode, - data: arguments[1] === undefined ? '' : arguments[1], - responseOptions: arguments[2] === undefined ? {} : arguments[2] + if (!this.error) { + this.retryCount = 0 + return this.handler.onResponseEnd?.(controller, trailers) } - this.validateReplyParameters(replyParameters) - // Send in-already provided data like usual - const dispatchData = this.createMockScopeDispatchData(replyParameters) - const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], dispatchData, { ignoreTrailingSlash: this[kIgnoreTrailingSlash] }) - return new MockScope(newMockDispatch) + this.retry(controller) } - /** - * Mock an undici request with a defined error. - */ - replyWithError (error) { - if (typeof error === 'undefined') { - throw new InvalidArgumentError('error must be defined') + retry (controller) { + if (this.start !== 0) { + const headers = { range: `bytes=${this.start}-${this.end ?? ''}` } + + // Weak etag check - weak etags will make comparison algorithms never match + if (this.etag != null) { + headers['if-match'] = this.etag + } + + this.opts = { + ...this.opts, + headers: { + ...this.opts.headers, + ...headers + } + } } - const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], { error }, { ignoreTrailingSlash: this[kIgnoreTrailingSlash] }) - return new MockScope(newMockDispatch) + try { + this.retryCountCheckpoint = this.retryCount + this.dispatch(this.opts, this) + } catch (err) { + this.handler.onResponseError?.(controller, err) + } } - /** - * Set default reply headers on the interceptor for subsequent replies - */ - defaultReplyHeaders (headers) { - if (typeof headers === 'undefined') { - throw new InvalidArgumentError('headers must be defined') + onResponseError (controller, err) { + if (controller?.aborted || isDisturbed(this.opts.body)) { + this.handler.onResponseError?.(controller, err) + return } - this[kDefaultHeaders] = headers - return this - } + function shouldRetry (returnedErr) { + if (!returnedErr) { + this.retry(controller) + return + } - /** - * Set default reply trailers on the interceptor for subsequent replies - */ - defaultReplyTrailers (trailers) { - if (typeof trailers === 'undefined') { - throw new InvalidArgumentError('trailers must be defined') + this.handler?.onResponseError?.(controller, returnedErr) } - this[kDefaultTrailers] = trailers - return this - } + // We reconcile in case of a mix between network errors + // and server error response + if (this.retryCount - this.retryCountCheckpoint > 0) { + // We count the difference between the last checkpoint and the current retry count + this.retryCount = + this.retryCountCheckpoint + + (this.retryCount - this.retryCountCheckpoint) + } else { + this.retryCount += 1 + } - /** - * Set reply content length header for replies on the interceptor - */ - replyContentLength () { - this[kContentLength] = true - return this + this.retryOpts.retry( + err, + { + state: { counter: this.retryCount }, + opts: { retryOptions: this.retryOpts, ...this.opts } + }, + shouldRetry.bind(this) + ) } } -module.exports.MockInterceptor = MockInterceptor -module.exports.MockScope = MockScope +module.exports = RetryHandler /***/ }), -/***/ 733: +/***/ 2791: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -const { promisify } = __nccwpck_require__(7975) -const Pool = __nccwpck_require__(8767) -const { buildMockDispatch } = __nccwpck_require__(4290) -const { - kDispatches, - kMockAgent, - kClose, - kOriginalClose, - kOrigin, - kOriginalDispatch, - kConnected, - kIgnoreTrailingSlash -} = __nccwpck_require__(45) -const { MockInterceptor } = __nccwpck_require__(2156) -const Symbols = __nccwpck_require__(9562) -const { InvalidArgumentError } = __nccwpck_require__(4928) +const { parseHeaders } = __nccwpck_require__(2550) +const { InvalidArgumentError } = __nccwpck_require__(5093) -/** - * MockPool provides an API that extends the Pool to influence the mockDispatches. - */ -class MockPool extends Pool { - constructor (origin, opts) { - if (!opts || !opts.agent || typeof opts.agent.dispatch !== 'function') { - throw new InvalidArgumentError('Argument opts.agent must implement Agent') - } +const kResume = Symbol('resume') - super(origin, opts) +class UnwrapController { + #paused = false + #reason = null + #aborted = false + #abort - this[kMockAgent] = opts.agent - this[kOrigin] = origin - this[kIgnoreTrailingSlash] = opts.ignoreTrailingSlash ?? false - this[kDispatches] = [] - this[kConnected] = 1 - this[kOriginalDispatch] = this.dispatch - this[kOriginalClose] = this.close.bind(this) + [kResume] = null - this.dispatch = buildMockDispatch.call(this) - this.close = this[kClose] + constructor (abort) { + this.#abort = abort } - get [Symbols.kConnected] () { - return this[kConnected] + pause () { + this.#paused = true } - /** - * Sets up the base interceptor for mocking replies from undici. - */ - intercept (opts) { - return new MockInterceptor( - opts && { ignoreTrailingSlash: this[kIgnoreTrailingSlash], ...opts }, - this[kDispatches] - ) + resume () { + if (this.#paused) { + this.#paused = false + this[kResume]?.() + } } - cleanMocks () { - this[kDispatches] = [] + abort (reason) { + if (!this.#aborted) { + this.#aborted = true + this.#reason = reason + this.#abort(reason) + } } - async [kClose] () { - await promisify(this[kOriginalClose])() - this[kConnected] = 0 - this[kMockAgent][Symbols.kClients].delete(this[kOrigin]) + get aborted () { + return this.#aborted + } + + get reason () { + return this.#reason + } + + get paused () { + return this.#paused } } -module.exports = MockPool +module.exports = class UnwrapHandler { + #handler + #controller + constructor (handler) { + this.#handler = handler + } -/***/ }), + static unwrap (handler) { + // TODO (fix): More checks... + return !handler.onRequestStart ? handler : new UnwrapHandler(handler) + } -/***/ 45: -/***/ ((module) => { + onConnect (abort, context) { + this.#controller = new UnwrapController(abort) + this.#handler.onRequestStart?.(this.#controller, context) + } -"use strict"; + onUpgrade (statusCode, rawHeaders, socket) { + this.#handler.onRequestUpgrade?.(this.#controller, statusCode, parseHeaders(rawHeaders), socket) + } + onHeaders (statusCode, rawHeaders, resume, statusMessage) { + this.#controller[kResume] = resume + this.#handler.onResponseStart?.(this.#controller, statusCode, parseHeaders(rawHeaders), statusMessage) + return !this.#controller.paused + } -module.exports = { - kAgent: Symbol('agent'), - kOptions: Symbol('options'), - kFactory: Symbol('factory'), - kDispatches: Symbol('dispatches'), - kDispatchKey: Symbol('dispatch key'), - kDefaultHeaders: Symbol('default headers'), - kDefaultTrailers: Symbol('default trailers'), - kContentLength: Symbol('content length'), - kMockAgent: Symbol('mock agent'), - kMockAgentSet: Symbol('mock agent set'), - kMockAgentGet: Symbol('mock agent get'), - kMockDispatch: Symbol('mock dispatch'), - kClose: Symbol('close'), - kOriginalClose: Symbol('original agent close'), - kOriginalDispatch: Symbol('original dispatch'), - kOrigin: Symbol('origin'), - kIsMockActive: Symbol('is mock active'), - kNetConnect: Symbol('net connect'), - kGetNetConnect: Symbol('get net connect'), - kConnected: Symbol('connected'), - kIgnoreTrailingSlash: Symbol('ignore trailing slash'), - kMockAgentMockCallHistoryInstance: Symbol('mock agent mock call history name'), - kMockAgentRegisterCallHistory: Symbol('mock agent register mock call history'), - kMockAgentAddCallHistoryLog: Symbol('mock agent add call history log'), - kMockAgentIsCallHistoryEnabled: Symbol('mock agent is call history enabled'), - kMockAgentAcceptsNonStandardSearchParameters: Symbol('mock agent accepts non standard search parameters'), - kMockCallHistoryAddLog: Symbol('mock call history add log') + onData (data) { + this.#handler.onResponseData?.(this.#controller, data) + return !this.#controller.paused + } + + onComplete (rawTrailers) { + this.#handler.onResponseEnd?.(this.#controller, parseHeaders(rawTrailers)) + } + + onError (err) { + if (!this.#handler.onResponseError) { + throw new InvalidArgumentError('invalid onError method') + } + + this.#handler.onResponseError?.(this.#controller, err) + } } /***/ }), -/***/ 4290: +/***/ 6444: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -const { MockNotMatchedError } = __nccwpck_require__(9664) -const { - kDispatches, - kMockAgent, - kOriginalDispatch, - kOrigin, - kGetNetConnect -} = __nccwpck_require__(45) -const { serializePathWithQuery } = __nccwpck_require__(983) -const { STATUS_CODES } = __nccwpck_require__(7067) -const { - types: { - isPromise +const { InvalidArgumentError } = __nccwpck_require__(5093) + +module.exports = class WrapHandler { + #handler + + constructor (handler) { + this.#handler = handler } -} = __nccwpck_require__(7975) -const { InvalidArgumentError } = __nccwpck_require__(4928) -function matchValue (match, value) { - if (typeof match === 'string') { - return match === value + static wrap (handler) { + // TODO (fix): More checks... + return handler.onRequestStart ? handler : new WrapHandler(handler) } - if (match instanceof RegExp) { - return match.test(value) + + // Unwrap Interface + + onConnect (abort, context) { + return this.#handler.onConnect?.(abort, context) } - if (typeof match === 'function') { - return match(value) === true + + onHeaders (statusCode, rawHeaders, resume, statusMessage) { + return this.#handler.onHeaders?.(statusCode, rawHeaders, resume, statusMessage) } - return false -} -function lowerCaseEntries (headers) { - return Object.fromEntries( - Object.entries(headers).map(([headerName, headerValue]) => { - return [headerName.toLocaleLowerCase(), headerValue] - }) - ) -} + onUpgrade (statusCode, rawHeaders, socket) { + return this.#handler.onUpgrade?.(statusCode, rawHeaders, socket) + } -/** - * @param {import('../../index').Headers|string[]|Record} headers - * @param {string} key - */ -function getHeaderByName (headers, key) { - if (Array.isArray(headers)) { - for (let i = 0; i < headers.length; i += 2) { - if (headers[i].toLocaleLowerCase() === key.toLocaleLowerCase()) { - return headers[i + 1] - } - } - - return undefined - } else if (typeof headers.get === 'function') { - return headers.get(key) - } else { - return lowerCaseEntries(headers)[key.toLocaleLowerCase()] + onData (data) { + return this.#handler.onData?.(data) } -} -/** @param {string[]} headers */ -function buildHeadersFromArray (headers) { // fetch HeadersList - const clone = headers.slice() - const entries = [] - for (let index = 0; index < clone.length; index += 2) { - entries.push([clone[index], clone[index + 1]]) + onComplete (trailers) { + return this.#handler.onComplete?.(trailers) } - return Object.fromEntries(entries) -} -function matchHeaders (mockDispatch, headers) { - if (typeof mockDispatch.headers === 'function') { - if (Array.isArray(headers)) { // fetch HeadersList - headers = buildHeadersFromArray(headers) + onError (err) { + if (!this.#handler.onError) { + throw err } - return mockDispatch.headers(headers ? lowerCaseEntries(headers) : {}) - } - if (typeof mockDispatch.headers === 'undefined') { - return true - } - if (typeof headers !== 'object' || typeof mockDispatch.headers !== 'object') { - return false + + return this.#handler.onError?.(err) } - for (const [matchHeaderName, matchHeaderValue] of Object.entries(mockDispatch.headers)) { - const headerValue = getHeaderByName(headers, matchHeaderName) + // Wrap Interface - if (!matchValue(matchHeaderValue, headerValue)) { - return false - } + onRequestStart (controller, context) { + this.#handler.onConnect?.((reason) => controller.abort(reason), context) } - return true -} -function normalizeSearchParams (query) { - if (typeof query !== 'string') { - return query + onRequestUpgrade (controller, statusCode, headers, socket) { + const rawHeaders = [] + for (const [key, val] of Object.entries(headers)) { + rawHeaders.push(Buffer.from(key), Array.isArray(val) ? val.map(v => Buffer.from(v)) : Buffer.from(val)) + } + + this.#handler.onUpgrade?.(statusCode, rawHeaders, socket) } - const originalQp = new URLSearchParams(query) - const normalizedQp = new URLSearchParams() + onResponseStart (controller, statusCode, headers, statusMessage) { + const rawHeaders = [] + for (const [key, val] of Object.entries(headers)) { + rawHeaders.push(Buffer.from(key), Array.isArray(val) ? val.map(v => Buffer.from(v)) : Buffer.from(val)) + } - for (let [key, value] of originalQp.entries()) { - key = key.replace('[]', '') + if (this.#handler.onHeaders?.(statusCode, rawHeaders, () => controller.resume(), statusMessage) === false) { + controller.pause() + } + } - const valueRepresentsString = /^(['"]).*\1$/.test(value) - if (valueRepresentsString) { - normalizedQp.append(key, value) - continue + onResponseData (controller, data) { + if (this.#handler.onData?.(data) === false) { + controller.pause() } + } - if (value.includes(',')) { - const values = value.split(',') - for (const v of values) { - normalizedQp.append(key, v) - } - continue + onResponseEnd (controller, trailers) { + const rawTrailers = [] + for (const [key, val] of Object.entries(trailers)) { + rawTrailers.push(Buffer.from(key), Array.isArray(val) ? val.map(v => Buffer.from(v)) : Buffer.from(val)) } - normalizedQp.append(key, value) + this.#handler.onComplete?.(rawTrailers) } - return normalizedQp -} + onResponseError (controller, err) { + if (!this.#handler.onError) { + throw new InvalidArgumentError('invalid onError method') + } -function safeUrl (path) { - if (typeof path !== 'string') { - return path - } - const pathSegments = path.split('?', 3) - if (pathSegments.length !== 2) { - return path + this.#handler.onError?.(err) } - - const qp = new URLSearchParams(pathSegments.pop()) - qp.sort() - return [...pathSegments, qp.toString()].join('?') } -function matchKey (mockDispatch, { path, method, body, headers }) { - const pathMatch = matchValue(mockDispatch.path, path) - const methodMatch = matchValue(mockDispatch.method, method) - const bodyMatch = typeof mockDispatch.body !== 'undefined' ? matchValue(mockDispatch.body, body) : true - const headersMatch = matchHeaders(mockDispatch, headers) - return pathMatch && methodMatch && bodyMatch && headersMatch -} -function getResponseData (data) { - if (Buffer.isBuffer(data)) { - return data - } else if (data instanceof Uint8Array) { - return data - } else if (data instanceof ArrayBuffer) { - return data - } else if (typeof data === 'object') { - return JSON.stringify(data) - } else if (data) { - return data.toString() - } else { - return '' - } -} +/***/ }), -function getMockDispatch (mockDispatches, key) { - const basePath = key.query ? serializePathWithQuery(key.path, key.query) : key.path - const resolvedPath = typeof basePath === 'string' ? safeUrl(basePath) : basePath +/***/ 5668: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - const resolvedPathWithoutTrailingSlash = removeTrailingSlash(resolvedPath) - // Match path - let matchedMockDispatches = mockDispatches - .filter(({ consumed }) => !consumed) - .filter(({ path, ignoreTrailingSlash }) => { - return ignoreTrailingSlash - ? matchValue(removeTrailingSlash(safeUrl(path)), resolvedPathWithoutTrailingSlash) - : matchValue(safeUrl(path), resolvedPath) - }) - if (matchedMockDispatches.length === 0) { - throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`) - } - // Match method - matchedMockDispatches = matchedMockDispatches.filter(({ method }) => matchValue(method, key.method)) - if (matchedMockDispatches.length === 0) { - throw new MockNotMatchedError(`Mock dispatch not matched for method '${key.method}' on path '${resolvedPath}'`) - } +const assert = __nccwpck_require__(4589) +const { Readable } = __nccwpck_require__(7075) +const util = __nccwpck_require__(2550) +const CacheHandler = __nccwpck_require__(1322) +const MemoryCacheStore = __nccwpck_require__(2947) +const CacheRevalidationHandler = __nccwpck_require__(6795) +const { assertCacheStore, assertCacheMethods, makeCacheKey, normalizeHeaders, parseCacheControlHeader } = __nccwpck_require__(4649) +const { AbortError } = __nccwpck_require__(5093) - // Match body - matchedMockDispatches = matchedMockDispatches.filter(({ body }) => typeof body !== 'undefined' ? matchValue(body, key.body) : true) - if (matchedMockDispatches.length === 0) { - throw new MockNotMatchedError(`Mock dispatch not matched for body '${key.body}' on path '${resolvedPath}'`) +/** + * @param {(string | RegExp)[] | undefined} origins + * @param {string} name + */ +function assertCacheOrigins (origins, name) { + if (origins === undefined) return + if (!Array.isArray(origins)) { + throw new TypeError(`expected ${name} to be an array or undefined, got ${typeof origins}`) } - - // Match headers - matchedMockDispatches = matchedMockDispatches.filter((mockDispatch) => matchHeaders(mockDispatch, key.headers)) - if (matchedMockDispatches.length === 0) { - const headers = typeof key.headers === 'object' ? JSON.stringify(key.headers) : key.headers - throw new MockNotMatchedError(`Mock dispatch not matched for headers '${headers}' on path '${resolvedPath}'`) + for (let i = 0; i < origins.length; i++) { + const origin = origins[i] + if (typeof origin !== 'string' && !(origin instanceof RegExp)) { + throw new TypeError(`expected ${name}[${i}] to be a string or RegExp, got ${typeof origin}`) + } } - - return matchedMockDispatches[0] } -function addMockDispatch (mockDispatches, key, data, opts) { - const baseData = { timesInvoked: 0, times: 1, persist: false, consumed: false, ...opts } - const replyData = typeof data === 'function' ? { callback: data } : { ...data } - const newMockDispatch = { ...baseData, ...key, pending: true, data: { error: null, ...replyData } } - mockDispatches.push(newMockDispatch) - return newMockDispatch -} +const nop = () => {} -function deleteMockDispatch (mockDispatches, key) { - const index = mockDispatches.findIndex(dispatch => { - if (!dispatch.consumed) { - return false - } - return matchKey(dispatch, key) - }) - if (index !== -1) { - mockDispatches.splice(index, 1) - } -} +/** + * @typedef {(options: import('../../types/dispatcher.d.ts').default.DispatchOptions, handler: import('../../types/dispatcher.d.ts').default.DispatchHandler) => void} DispatchFn + */ /** - * @param {string} path Path to remove trailing slash from + * @param {import('../../types/cache-interceptor.d.ts').default.GetResult} result + * @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives | undefined} cacheControlDirectives + * @param {import('../../types/dispatcher.d.ts').default.RequestOptions} opts + * @returns {boolean} */ -function removeTrailingSlash (path) { - while (path.endsWith('/')) { - path = path.slice(0, -1) +function needsRevalidation (result, cacheControlDirectives, { headers = {} }) { + // Always revalidate requests with the no-cache request directive. + if (cacheControlDirectives?.['no-cache']) { + return true } - if (path.length === 0) { - path = '/' + // Always revalidate requests with unqualified no-cache response directive. + if (result.cacheControlDirectives?.['no-cache'] && !Array.isArray(result.cacheControlDirectives['no-cache'])) { + return true } - return path + // Always revalidate requests with conditional headers. + if (headers['if-modified-since'] || headers['if-none-match']) { + return true + } + + return false } -function buildKey (opts) { - const { path, method, body, headers, query } = opts +/** + * @param {import('../../types/cache-interceptor.d.ts').default.GetResult} result + * @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives | undefined} cacheControlDirectives + * @returns {boolean} + */ +function isStale (result, cacheControlDirectives) { + const now = Date.now() + if (now > result.staleAt) { + // Response is stale + if (cacheControlDirectives?.['max-stale']) { + // There's a threshold where we can serve stale responses, let's see if + // we're in it + // https://www.rfc-editor.org/rfc/rfc9111.html#name-max-stale + const gracePeriod = result.staleAt + (cacheControlDirectives['max-stale'] * 1000) + return now > gracePeriod + } - return { - path, - method, - body, - headers, - query + return true } -} -function generateKeyValues (data) { - const keys = Object.keys(data) - const result = [] - for (let i = 0; i < keys.length; ++i) { - const key = keys[i] - const value = data[key] - const name = Buffer.from(`${key}`) - if (Array.isArray(value)) { - for (let j = 0; j < value.length; ++j) { - result.push(name, Buffer.from(`${value[j]}`)) - } - } else { - result.push(name, Buffer.from(`${value}`)) - } + if (cacheControlDirectives?.['min-fresh']) { + // https://www.rfc-editor.org/rfc/rfc9111.html#section-5.2.1.3 + + // At this point, staleAt is always > now + const timeLeftTillStale = result.staleAt - now + const threshold = cacheControlDirectives['min-fresh'] * 1000 + + return timeLeftTillStale <= threshold } - return result + + return false } /** - * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Status - * @param {number} statusCode + * Check if we're within the stale-while-revalidate window for a stale response + * @param {import('../../types/cache-interceptor.d.ts').default.GetResult} result + * @returns {boolean} */ -function getStatusText (statusCode) { - return STATUS_CODES[statusCode] || 'unknown' -} - -async function getResponse (body) { - const buffers = [] - for await (const data of body) { - buffers.push(data) +function withinStaleWhileRevalidateWindow (result) { + const staleWhileRevalidate = result.cacheControlDirectives?.['stale-while-revalidate'] + if (!staleWhileRevalidate) { + return false } - return Buffer.concat(buffers).toString('utf8') + + const now = Date.now() + const staleWhileRevalidateExpiry = result.staleAt + (staleWhileRevalidate * 1000) + return now <= staleWhileRevalidateExpiry } /** - * Mock dispatch function used to simulate undici dispatches + * @param {DispatchFn} dispatch + * @param {import('../../types/cache-interceptor.d.ts').default.CacheHandlerOptions} globalOpts + * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} cacheKey + * @param {import('../../types/dispatcher.d.ts').default.DispatchHandler} handler + * @param {import('../../types/dispatcher.d.ts').default.RequestOptions} opts + * @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives | undefined} reqCacheControl */ -function mockDispatch (opts, handler) { - // Get mock dispatch from built key - const key = buildKey(opts) - const mockDispatch = getMockDispatch(this[kDispatches], key) - - mockDispatch.timesInvoked++ +function handleUncachedResponse ( + dispatch, + globalOpts, + cacheKey, + handler, + opts, + reqCacheControl +) { + if (reqCacheControl?.['only-if-cached']) { + let aborted = false + try { + if (typeof handler.onConnect === 'function') { + handler.onConnect(() => { + aborted = true + }) - // Here's where we resolve a callback if a callback is present for the dispatch data. - if (mockDispatch.data.callback) { - mockDispatch.data = { ...mockDispatch.data, ...mockDispatch.data.callback(opts) } - } + if (aborted) { + return + } + } - // Parse mockDispatch data - const { data: { statusCode, data, headers, trailers, error }, delay, persist } = mockDispatch - const { timesInvoked, times } = mockDispatch + if (typeof handler.onHeaders === 'function') { + handler.onHeaders(504, [], nop, 'Gateway Timeout') + if (aborted) { + return + } + } - // If it's used up and not persistent, mark as consumed - mockDispatch.consumed = !persist && timesInvoked >= times - mockDispatch.pending = timesInvoked < times + if (typeof handler.onComplete === 'function') { + handler.onComplete([]) + } + } catch (err) { + if (typeof handler.onError === 'function') { + handler.onError(err) + } + } - // If specified, trigger dispatch error - if (error !== null) { - deleteMockDispatch(this[kDispatches], key) - handler.onError(error) return true } - // Handle the request with a delay if necessary - if (typeof delay === 'number' && delay > 0) { - setTimeout(() => { - handleReply(this[kDispatches]) - }, delay) - } else { - handleReply(this[kDispatches]) - } - - function handleReply (mockDispatches, _data = data) { - // fetch's HeadersList is a 1D string array - const optsHeaders = Array.isArray(opts.headers) - ? buildHeadersFromArray(opts.headers) - : opts.headers - const body = typeof _data === 'function' - ? _data({ ...opts, headers: optsHeaders }) - : _data + return dispatch(opts, new CacheHandler(globalOpts, cacheKey, handler)) +} - // util.types.isPromise is likely needed for jest. - if (isPromise(body)) { - // If handleReply is asynchronous, throwing an error - // in the callback will reject the promise, rather than - // synchronously throw the error, which breaks some tests. - // Rather, we wait for the callback to resolve if it is a - // promise, and then re-run handleReply with the new body. - return body.then((newData) => handleReply(mockDispatches, newData)) - } +/** + * @param {import('../../types/dispatcher.d.ts').default.DispatchHandler} handler + * @param {import('../../types/dispatcher.d.ts').default.RequestOptions} opts + * @param {import('../../types/cache-interceptor.d.ts').default.GetResult} result + * @param {number} age + * @param {any} context + * @param {boolean} isStale + */ +function sendCachedValue (handler, opts, result, age, context, isStale) { + // TODO (perf): Readable.from path can be optimized... + const stream = util.isStream(result.body) + ? result.body + : Readable.from(result.body ?? []) - const responseData = getResponseData(body) - const responseHeaders = generateKeyValues(headers) - const responseTrailers = generateKeyValues(trailers) + assert(!stream.destroyed, 'stream should not be destroyed') + assert(!stream.readableDidRead, 'stream should not be readableDidRead') - handler.onConnect?.(err => handler.onError(err), null) - handler.onHeaders?.(statusCode, responseHeaders, resume, getStatusText(statusCode)) - handler.onData?.(Buffer.from(responseData)) - handler.onComplete?.(responseTrailers) - deleteMockDispatch(mockDispatches, key) + const controller = { + resume () { + stream.resume() + }, + pause () { + stream.pause() + }, + get paused () { + return stream.isPaused() + }, + get aborted () { + return stream.destroyed + }, + get reason () { + return stream.errored + }, + abort (reason) { + stream.destroy(reason ?? new AbortError()) + } } - function resume () {} - - return true -} - -function buildMockDispatch () { - const agent = this[kMockAgent] - const origin = this[kOrigin] - const originalDispatch = this[kOriginalDispatch] - - return function dispatch (opts, handler) { - if (agent.isMockActive) { - try { - mockDispatch.call(this, opts, handler) - } catch (error) { - if (error.code === 'UND_MOCK_ERR_MOCK_NOT_MATCHED') { - const netConnect = agent[kGetNetConnect]() - if (netConnect === false) { - throw new MockNotMatchedError(`${error.message}: subsequent request to origin ${origin} was not allowed (net.connect disabled)`) - } - if (checkNetConnect(netConnect, origin)) { - originalDispatch.call(this, opts, handler) - } else { - throw new MockNotMatchedError(`${error.message}: subsequent request to origin ${origin} was not allowed (net.connect is not enabled for this origin)`) - } + stream + .on('error', function (err) { + if (!this.readableEnded) { + if (typeof handler.onResponseError === 'function') { + handler.onResponseError(controller, err) } else { - throw error + throw err } } - } else { - originalDispatch.call(this, opts, handler) - } - } -} + }) + .on('close', function () { + if (!this.errored) { + handler.onResponseEnd?.(controller, {}) + } + }) -function checkNetConnect (netConnect, origin) { - const url = new URL(origin) - if (netConnect === true) { - return true - } else if (Array.isArray(netConnect) && netConnect.some((matcher) => matchValue(matcher, url.host))) { - return true - } - return false -} + handler.onRequestStart?.(controller, context) -function normalizeOrigin (origin) { - if (typeof origin !== 'string' && !(origin instanceof URL)) { - return origin + if (stream.destroyed) { + return } - if (origin instanceof URL) { - return origin.origin - } + // Add the age header + // https://www.rfc-editor.org/rfc/rfc9111.html#name-age + const headers = { ...result.headers, age: String(age) } - return origin.toLowerCase() -} + if (isStale) { + // Add warning header + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Warning + headers.warning = '110 - "response is stale"' + } -function buildAndValidateMockOptions (opts) { - const { agent, ...mockOptions } = opts + handler.onResponseStart?.(controller, result.statusCode, headers, result.statusMessage) - if ('enableCallHistory' in mockOptions && typeof mockOptions.enableCallHistory !== 'boolean') { - throw new InvalidArgumentError('options.enableCallHistory must to be a boolean') + if (opts.method === 'HEAD') { + stream.destroy() + } else { + stream.on('data', function (chunk) { + handler.onResponseData?.(controller, chunk) + }) } +} - if ('acceptNonStandardSearchParameters' in mockOptions && typeof mockOptions.acceptNonStandardSearchParameters !== 'boolean') { - throw new InvalidArgumentError('options.acceptNonStandardSearchParameters must to be a boolean') +/** + * @param {DispatchFn} dispatch + * @param {import('../../types/cache-interceptor.d.ts').default.CacheHandlerOptions} globalOpts + * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} cacheKey + * @param {import('../../types/dispatcher.d.ts').default.DispatchHandler} handler + * @param {import('../../types/dispatcher.d.ts').default.RequestOptions} opts + * @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives | undefined} reqCacheControl + * @param {import('../../types/cache-interceptor.d.ts').default.GetResult | undefined} result + */ +function handleResult ( + dispatch, + globalOpts, + cacheKey, + handler, + opts, + reqCacheControl, + result +) { + if (!result) { + return handleUncachedResponse(dispatch, globalOpts, cacheKey, handler, opts, reqCacheControl) } - if ('ignoreTrailingSlash' in mockOptions && typeof mockOptions.ignoreTrailingSlash !== 'boolean') { - throw new InvalidArgumentError('options.ignoreTrailingSlash must to be a boolean') + const now = Date.now() + if (now > result.deleteAt) { + // Response is expired, cache store shouldn't have given this to us + return dispatch(opts, new CacheHandler(globalOpts, cacheKey, handler)) } - return mockOptions -} + const age = Math.round((now - result.cachedAt) / 1000) + if (reqCacheControl?.['max-age'] && age >= reqCacheControl['max-age']) { + // Response is considered expired for this specific request + // https://www.rfc-editor.org/rfc/rfc9111.html#section-5.2.1.1 + return dispatch(opts, handler) + } -module.exports = { - getResponseData, - getMockDispatch, - addMockDispatch, - deleteMockDispatch, - buildKey, - generateKeyValues, - matchValue, - getResponse, - getStatusText, - mockDispatch, - buildMockDispatch, - checkNetConnect, - buildAndValidateMockOptions, - getHeaderByName, - buildHeadersFromArray, - normalizeSearchParams, - normalizeOrigin -} + const stale = isStale(result, reqCacheControl) + const revalidate = needsRevalidation(result, reqCacheControl, opts) + // Check if the response is stale + if (stale || revalidate) { + if (util.isStream(opts.body) && util.bodyLength(opts.body) !== 0) { + // If body is a stream we can't revalidate... + // TODO (fix): This could be less strict... + return dispatch(opts, new CacheHandler(globalOpts, cacheKey, handler)) + } -/***/ }), + // RFC 5861: If we're within stale-while-revalidate window, serve stale immediately + // and revalidate in background, unless immediate revalidation is necessary + if (!revalidate && withinStaleWhileRevalidateWindow(result)) { + // Serve stale response immediately + sendCachedValue(handler, opts, result, age, null, true) -/***/ 6709: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // Start background revalidation (fire-and-forget) + queueMicrotask(() => { + let headers = { + ...opts.headers, + 'if-modified-since': new Date(result.cachedAt).toUTCString() + } -"use strict"; + if (result.etag) { + headers['if-none-match'] = result.etag + } + if (result.vary) { + headers = { + ...headers, + ...result.vary + } + } -const { Transform } = __nccwpck_require__(7075) -const { Console } = __nccwpck_require__(7540) + // Background revalidation - update cache if we get new data + dispatch( + { + ...opts, + headers + }, + new CacheHandler(globalOpts, cacheKey, { + // Silent handler that just updates the cache + onRequestStart () {}, + onRequestUpgrade () {}, + onResponseStart () {}, + onResponseData () {}, + onResponseEnd () {}, + onResponseError () {} + }) + ) + }) -const PERSISTENT = process.versions.icu ? '✅' : 'Y ' -const NOT_PERSISTENT = process.versions.icu ? '❌' : 'N ' + return true + } + + let withinStaleIfErrorThreshold = false + const staleIfErrorExpiry = result.cacheControlDirectives['stale-if-error'] ?? reqCacheControl?.['stale-if-error'] + if (staleIfErrorExpiry) { + withinStaleIfErrorThreshold = now < (result.staleAt + (staleIfErrorExpiry * 1000)) + } + + let headers = { + ...opts.headers, + 'if-modified-since': new Date(result.cachedAt).toUTCString() + } + + if (result.etag) { + headers['if-none-match'] = result.etag + } + + if (result.vary) { + headers = { + ...headers, + ...result.vary + } + } + + // We need to revalidate the response + return dispatch( + { + ...opts, + headers + }, + new CacheRevalidationHandler( + (success, context) => { + if (success) { + // TODO: successful revalidation should be considered fresh (not give stale warning). + sendCachedValue(handler, opts, result, age, context, stale) + } else if (util.isStream(result.body)) { + result.body.on('error', nop).destroy() + } + }, + new CacheHandler(globalOpts, cacheKey, handler), + withinStaleIfErrorThreshold + ) + ) + } + + // Dump request body. + if (util.isStream(opts.body)) { + opts.body.on('error', nop).destroy() + } + + sendCachedValue(handler, opts, result, age, null, false) +} /** - * Gets the output of `console.table(…)` as a string. + * @param {import('../../types/cache-interceptor.d.ts').default.CacheOptions} [opts] + * @returns {import('../../types/dispatcher.d.ts').default.DispatcherComposeInterceptor} */ -module.exports = class PendingInterceptorsFormatter { - constructor ({ disableColors } = {}) { - this.transform = new Transform({ - transform (chunk, _enc, cb) { - cb(null, chunk) - } - }) +module.exports = (opts = {}) => { + const { + store = new MemoryCacheStore(), + methods = ['GET'], + cacheByDefault = undefined, + type = 'shared', + origins = undefined + } = opts - this.logger = new Console({ - stdout: this.transform, - inspectOptions: { - colors: !disableColors && !process.env.CI - } - }) + if (typeof opts !== 'object' || opts === null) { + throw new TypeError(`expected type of opts to be an Object, got ${opts === null ? 'null' : typeof opts}`) } - format (pendingInterceptors) { - const withPrettyHeaders = pendingInterceptors.map( - ({ method, path, data: { statusCode }, persist, times, timesInvoked, origin }) => ({ - Method: method, - Origin: origin, - Path: path, - 'Status code': statusCode, - Persistent: persist ? PERSISTENT : NOT_PERSISTENT, - Invocations: timesInvoked, - Remaining: persist ? Infinity : times - timesInvoked - })) + assertCacheStore(store, 'opts.store') + assertCacheMethods(methods, 'opts.methods') + assertCacheOrigins(origins, 'opts.origins') - this.logger.table(withPrettyHeaders) - return this.transform.read().toString() + if (typeof cacheByDefault !== 'undefined' && typeof cacheByDefault !== 'number') { + throw new TypeError(`expected opts.cacheByDefault to be number or undefined, got ${typeof cacheByDefault}`) } -} + if (typeof type !== 'undefined' && type !== 'shared' && type !== 'private') { + throw new TypeError(`expected opts.type to be shared, private, or undefined, got ${typeof type}`) + } -/***/ }), + const globalOpts = { + store, + methods, + cacheByDefault, + type + } -/***/ 8784: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + const safeMethodsToNotCache = util.safeHTTPMethods.filter(method => methods.includes(method) === false) -"use strict"; + return dispatch => { + return (opts, handler) => { + if (!opts.origin || safeMethodsToNotCache.includes(opts.method)) { + // Not a method we want to cache or we don't have the origin, skip + return dispatch(opts, handler) + } + // Check if origin is in whitelist + if (origins !== undefined) { + const requestOrigin = opts.origin.toString().toLowerCase() + let isAllowed = false -const Agent = __nccwpck_require__(2004) -const MockAgent = __nccwpck_require__(3550) -const { SnapshotRecorder } = __nccwpck_require__(9647) -const WrapHandler = __nccwpck_require__(3195) -const { InvalidArgumentError, UndiciError } = __nccwpck_require__(4928) -const { validateSnapshotMode } = __nccwpck_require__(1998) + for (let i = 0; i < origins.length; i++) { + const allowed = origins[i] + if (typeof allowed === 'string') { + if (allowed.toLowerCase() === requestOrigin) { + isAllowed = true + break + } + } else if (allowed.test(requestOrigin)) { + isAllowed = true + break + } + } -const kSnapshotRecorder = Symbol('kSnapshotRecorder') -const kSnapshotMode = Symbol('kSnapshotMode') -const kSnapshotPath = Symbol('kSnapshotPath') -const kSnapshotLoaded = Symbol('kSnapshotLoaded') -const kRealAgent = Symbol('kRealAgent') + if (!isAllowed) { + return dispatch(opts, handler) + } + } -// Static flag to ensure warning is only emitted once per process -let warningEmitted = false + opts = { + ...opts, + headers: normalizeHeaders(opts) + } -class SnapshotAgent extends MockAgent { - constructor (opts = {}) { - // Emit experimental warning only once - if (!warningEmitted) { - process.emitWarning( - 'SnapshotAgent is experimental and subject to change', - 'ExperimentalWarning' - ) - warningEmitted = true + const reqCacheControl = opts.headers?.['cache-control'] + ? parseCacheControlHeader(opts.headers['cache-control']) + : undefined + + if (reqCacheControl?.['no-store']) { + return dispatch(opts, handler) + } + + /** + * @type {import('../../types/cache-interceptor.d.ts').default.CacheKey} + */ + const cacheKey = makeCacheKey(opts) + const result = store.get(cacheKey) + + if (result && typeof result.then === 'function') { + return result + .then(result => handleResult(dispatch, + globalOpts, + cacheKey, + handler, + opts, + reqCacheControl, + result + )) + } else { + return handleResult( + dispatch, + globalOpts, + cacheKey, + handler, + opts, + reqCacheControl, + result + ) + } } + } +} - const { - mode = 'record', - snapshotPath = null, - ...mockAgentOpts - } = opts - super(mockAgentOpts) +/***/ }), - validateSnapshotMode(mode) +/***/ 7355: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - // Validate snapshotPath is provided when required - if ((mode === 'playback' || mode === 'update') && !snapshotPath) { - throw new InvalidArgumentError(`snapshotPath is required when mode is '${mode}'`) - } - this[kSnapshotMode] = mode - this[kSnapshotPath] = snapshotPath - this[kSnapshotRecorder] = new SnapshotRecorder({ - snapshotPath: this[kSnapshotPath], - mode: this[kSnapshotMode], - maxSnapshots: opts.maxSnapshots, - autoFlush: opts.autoFlush, - flushInterval: opts.flushInterval, - matchHeaders: opts.matchHeaders, - ignoreHeaders: opts.ignoreHeaders, - excludeHeaders: opts.excludeHeaders, - matchBody: opts.matchBody, - matchQuery: opts.matchQuery, - caseSensitive: opts.caseSensitive, - shouldRecord: opts.shouldRecord, - shouldPlayback: opts.shouldPlayback, - excludeUrls: opts.excludeUrls - }) - this[kSnapshotLoaded] = false +const { createInflate, createGunzip, createBrotliDecompress, createZstdDecompress } = __nccwpck_require__(8522) +const { pipeline } = __nccwpck_require__(7075) +const DecoratorHandler = __nccwpck_require__(169) +const { runtimeFeatures } = __nccwpck_require__(3895) - // For recording/update mode, we need a real agent to make actual requests - // For playback mode, we need a real agent if there are excluded URLs - if (this[kSnapshotMode] === 'record' || this[kSnapshotMode] === 'update' || - (this[kSnapshotMode] === 'playback' && opts.excludeUrls && opts.excludeUrls.length > 0)) { - this[kRealAgent] = new Agent(opts) - } +/** @typedef {import('node:stream').Transform} Transform */ +/** @typedef {import('node:stream').Transform} Controller */ +/** @typedef {Transform&import('node:zlib').Zlib} DecompressorStream */ - // Auto-load snapshots in playback/update mode - if ((this[kSnapshotMode] === 'playback' || this[kSnapshotMode] === 'update') && this[kSnapshotPath]) { - this.loadSnapshots().catch(() => { - // Ignore load errors - file might not exist yet - }) - } - } +/** @type {Record DecompressorStream>} */ +const supportedEncodings = { + gzip: createGunzip, + 'x-gzip': createGunzip, + br: createBrotliDecompress, + deflate: createInflate, + compress: createInflate, + 'x-compress': createInflate, + ...(runtimeFeatures.has('zstd') ? { zstd: createZstdDecompress } : {}) +} - dispatch (opts, handler) { - handler = WrapHandler.wrap(handler) - const mode = this[kSnapshotMode] +const defaultSkipStatusCodes = /** @type {const} */ ([204, 304]) - // Check if URL should be excluded (pass through without mocking/recording) - if (this[kSnapshotRecorder].isUrlExcluded(opts)) { - // Real agent is guaranteed by constructor when excludeUrls is configured - return this[kRealAgent].dispatch(opts, handler) - } +let warningEmitted = /** @type {boolean} */ (false) - if (mode === 'playback' || mode === 'update') { - // Ensure snapshots are loaded - if (!this[kSnapshotLoaded]) { - // Need to load asynchronously, delegate to async version - return this.#asyncDispatch(opts, handler) - } +/** + * @typedef {Object} DecompressHandlerOptions + * @property {number[]|Readonly} [skipStatusCodes=[204, 304]] - List of status codes to skip decompression for + * @property {boolean} [skipErrorResponses] - Whether to skip decompression for error responses (status codes >= 400) + */ - // Try to find existing snapshot (synchronous) - const snapshot = this[kSnapshotRecorder].findSnapshot(opts) +class DecompressHandler extends DecoratorHandler { + /** @type {Transform[]} */ + #decompressors = [] + /** @type {Readonly} */ + #skipStatusCodes + /** @type {boolean} */ + #skipErrorResponses - if (snapshot) { - // Use recorded response (synchronous) - return this.#replaySnapshot(snapshot, handler) - } else if (mode === 'update') { - // Make real request and record it (async required) - return this.#recordAndReplay(opts, handler) - } else { - // Playback mode but no snapshot found - const error = new UndiciError(`No snapshot found for ${opts.method || 'GET'} ${opts.path}`) - if (handler.onError) { - handler.onError(error) - return - } - throw error - } - } else if (mode === 'record') { - // Record mode - make real request and save response (async required) - return this.#recordAndReplay(opts, handler) - } + constructor (handler, { skipStatusCodes = defaultSkipStatusCodes, skipErrorResponses = true } = {}) { + super(handler) + this.#skipStatusCodes = skipStatusCodes + this.#skipErrorResponses = skipErrorResponses } /** - * Async version of dispatch for when we need to load snapshots first + * Determines if decompression should be skipped based on encoding and status code + * @param {string} contentEncoding - Content-Encoding header value + * @param {number} statusCode - HTTP status code of the response + * @returns {boolean} - True if decompression should be skipped */ - async #asyncDispatch (opts, handler) { - await this.loadSnapshots() - return this.dispatch(opts, handler) + #shouldSkipDecompression (contentEncoding, statusCode) { + if (!contentEncoding || statusCode < 200) return true + if (this.#skipStatusCodes.includes(statusCode)) return true + if (this.#skipErrorResponses && statusCode >= 400) return true + return false } /** - * Records a real request and replays the response + * Creates a chain of decompressors for multiple content encodings + * + * @param {string} encodings - Comma-separated list of content encodings + * @returns {Array} - Array of decompressor streams + * @throws {Error} - If the number of content-encodings exceeds the maximum allowed */ - #recordAndReplay (opts, handler) { - const responseData = { - statusCode: null, - headers: {}, - trailers: {}, - body: [] - } - - const self = this // Capture 'this' context for use within nested handler callbacks - - const recordingHandler = { - onRequestStart (controller, context) { - return handler.onRequestStart(controller, { ...context, history: this.history }) - }, - - onRequestUpgrade (controller, statusCode, headers, socket) { - return handler.onRequestUpgrade(controller, statusCode, headers, socket) - }, + #createDecompressionChain (encodings) { + const parts = encodings.split(',') - onResponseStart (controller, statusCode, headers, statusMessage) { - responseData.statusCode = statusCode - responseData.headers = headers - return handler.onResponseStart(controller, statusCode, headers, statusMessage) - }, + // Limit the number of content-encodings to prevent resource exhaustion. + // CVE fix similar to urllib3 (GHSA-gm62-xv2j-4w53) and curl (CVE-2022-32206). + const maxContentEncodings = 5 + if (parts.length > maxContentEncodings) { + throw new Error(`too many content-encodings in response: ${parts.length}, maximum allowed is ${maxContentEncodings}`) + } - onResponseData (controller, chunk) { - responseData.body.push(chunk) - return handler.onResponseData(controller, chunk) - }, + /** @type {DecompressorStream[]} */ + const decompressors = [] - onResponseEnd (controller, trailers) { - responseData.trailers = trailers + for (let i = parts.length - 1; i >= 0; i--) { + const encoding = parts[i].trim() + if (!encoding) continue - // Record the interaction using captured 'self' context (fire and forget) - const responseBody = Buffer.concat(responseData.body) - self[kSnapshotRecorder].record(opts, { - statusCode: responseData.statusCode, - headers: responseData.headers, - body: responseBody, - trailers: responseData.trailers - }) - .then(() => handler.onResponseEnd(controller, trailers)) - .catch((error) => handler.onResponseError(controller, error)) + if (!supportedEncodings[encoding]) { + decompressors.length = 0 // Clear if unsupported encoding + return decompressors // Unsupported encoding } + + decompressors.push(supportedEncodings[encoding]()) } - // Use composed agent if available (includes interceptors), otherwise use real agent - const agent = this[kRealAgent] - return agent.dispatch(opts, recordingHandler) + return decompressors } /** - * Replays a recorded response - * - * @param {Object} snapshot - The recorded snapshot to replay. - * @param {Object} handler - The handler to call with the response data. + * Sets up event handlers for a decompressor stream using readable events + * @param {DecompressorStream} decompressor - The decompressor stream + * @param {Controller} controller - The controller to coordinate with * @returns {void} */ - #replaySnapshot (snapshot, handler) { - try { - const { response } = snapshot - - const controller = { - pause () { }, - resume () { }, - abort (reason) { - this.aborted = true - this.reason = reason - }, - - aborted: false, - paused: false + #setupDecompressorEvents (decompressor, controller) { + decompressor.on('readable', () => { + let chunk + while ((chunk = decompressor.read()) !== null) { + const result = super.onResponseData(controller, chunk) + if (result === false) { + break + } } + }) - handler.onRequestStart(controller) - - handler.onResponseStart(controller, response.statusCode, response.headers) + decompressor.on('error', (error) => { + super.onResponseError(controller, error) + }) + } - // Body is always stored as base64 string - const body = Buffer.from(response.body, 'base64') - handler.onResponseData(controller, body) + /** + * Sets up event handling for a single decompressor + * @param {Controller} controller - The controller to handle events + * @returns {void} + */ + #setupSingleDecompressor (controller) { + const decompressor = this.#decompressors[0] + this.#setupDecompressorEvents(decompressor, controller) - handler.onResponseEnd(controller, response.trailers) - } catch (error) { - handler.onError?.(error) - } + decompressor.on('end', () => { + super.onResponseEnd(controller, {}) + }) } /** - * Loads snapshots from file - * - * @param {string} [filePath] - Optional file path to load snapshots from. - * @returns {Promise} - Resolves when snapshots are loaded. + * Sets up event handling for multiple chained decompressors using pipeline + * @param {Controller} controller - The controller to handle events + * @returns {void} */ - async loadSnapshots (filePath) { - await this[kSnapshotRecorder].loadSnapshots(filePath || this[kSnapshotPath]) - this[kSnapshotLoaded] = true + #setupMultipleDecompressors (controller) { + const lastDecompressor = this.#decompressors[this.#decompressors.length - 1] + this.#setupDecompressorEvents(lastDecompressor, controller) - // In playback mode, set up MockAgent interceptors for all snapshots - if (this[kSnapshotMode] === 'playback') { - this.#setupMockInterceptors() - } + pipeline(this.#decompressors, (err) => { + if (err) { + super.onResponseError(controller, err) + return + } + super.onResponseEnd(controller, {}) + }) } /** - * Saves snapshots to file - * - * @param {string} [filePath] - Optional file path to save snapshots to. - * @returns {Promise} - Resolves when snapshots are saved. + * Cleans up decompressor references to prevent memory leaks + * @returns {void} */ - async saveSnapshots (filePath) { - return this[kSnapshotRecorder].saveSnapshots(filePath || this[kSnapshotPath]) + #cleanupDecompressors () { + this.#decompressors.length = 0 } /** - * Sets up MockAgent interceptors based on recorded snapshots. - * - * This method creates MockAgent interceptors for each recorded snapshot, - * allowing the SnapshotAgent to fall back to MockAgent's standard intercept - * mechanism in playback mode. Each interceptor is configured to persist - * (remain active for multiple requests) and responds with the recorded - * response data. - * - * Called automatically when loading snapshots in playback mode. - * + * @param {Controller} controller + * @param {number} statusCode + * @param {Record} headers + * @param {string} statusMessage * @returns {void} */ - #setupMockInterceptors () { - for (const snapshot of this[kSnapshotRecorder].getSnapshots()) { - const { request, responses, response } = snapshot - const url = new URL(request.url) + onResponseStart (controller, statusCode, headers, statusMessage) { + const contentEncoding = headers['content-encoding'] - const mockPool = this.get(url.origin) + // If content encoding is not supported or status code is in skip list + if (this.#shouldSkipDecompression(contentEncoding, statusCode)) { + return super.onResponseStart(controller, statusCode, headers, statusMessage) + } - // Handle both new format (responses array) and legacy format (response object) - const responseData = responses ? responses[0] : response - if (!responseData) continue + const decompressors = this.#createDecompressionChain(contentEncoding.toLowerCase()) - mockPool.intercept({ - path: url.pathname + url.search, - method: request.method, - headers: request.headers, - body: request.body - }).reply(responseData.statusCode, responseData.body, { - headers: responseData.headers, - trailers: responseData.trailers - }).persist() + if (decompressors.length === 0) { + this.#cleanupDecompressors() + return super.onResponseStart(controller, statusCode, headers, statusMessage) } - } - /** - * Gets the snapshot recorder - * @return {SnapshotRecorder} - The snapshot recorder instance - */ - getRecorder () { - return this[kSnapshotRecorder] - } + this.#decompressors = decompressors - /** - * Gets the current mode - * @return {import('./snapshot-utils').SnapshotMode} - The current snapshot mode - */ - getMode () { - return this[kSnapshotMode] - } + // Remove compression headers since we're decompressing + const { 'content-encoding': _, 'content-length': __, ...newHeaders } = headers - /** - * Clears all snapshots - * @returns {void} - */ - clearSnapshots () { - this[kSnapshotRecorder].clear() + if (this.#decompressors.length === 1) { + this.#setupSingleDecompressor(controller) + } else { + this.#setupMultipleDecompressors(controller) + } + + return super.onResponseStart(controller, statusCode, newHeaders, statusMessage) } /** - * Resets call counts for all snapshots (useful for test cleanup) + * @param {Controller} controller + * @param {Buffer} chunk * @returns {void} */ - resetCallCounts () { - this[kSnapshotRecorder].resetCallCounts() + onResponseData (controller, chunk) { + if (this.#decompressors.length > 0) { + this.#decompressors[0].write(chunk) + return + } + super.onResponseData(controller, chunk) } /** - * Deletes a specific snapshot by request options - * @param {import('./snapshot-recorder').SnapshotRequestOptions} requestOpts - Request options to identify the snapshot - * @return {Promise} - Returns true if the snapshot was deleted, false if not found + * @param {Controller} controller + * @param {Record | undefined} trailers + * @returns {void} */ - deleteSnapshot (requestOpts) { - return this[kSnapshotRecorder].deleteSnapshot(requestOpts) + onResponseEnd (controller, trailers) { + if (this.#decompressors.length > 0) { + this.#decompressors[0].end() + this.#cleanupDecompressors() + return + } + super.onResponseEnd(controller, trailers) } /** - * Gets information about a specific snapshot - * @returns {import('./snapshot-recorder').SnapshotInfo|null} - Snapshot information or null if not found + * @param {Controller} controller + * @param {Error} err + * @returns {void} */ - getSnapshotInfo (requestOpts) { - return this[kSnapshotRecorder].getSnapshotInfo(requestOpts) + onResponseError (controller, err) { + if (this.#decompressors.length > 0) { + for (const decompressor of this.#decompressors) { + decompressor.destroy(err) + } + this.#cleanupDecompressors() + } + super.onResponseError(controller, err) } +} - /** - * Replaces all snapshots with new data (full replacement) - * @param {Array<{hash: string; snapshot: import('./snapshot-recorder').SnapshotEntryshotEntry}>|Record} snapshotData - New snapshot data to replace existing snapshots - * @returns {void} - */ - replaceSnapshots (snapshotData) { - this[kSnapshotRecorder].replaceSnapshots(snapshotData) +/** + * Creates a decompression interceptor for HTTP responses + * @param {DecompressHandlerOptions} [options] - Options for the interceptor + * @returns {Function} - Interceptor function + */ +function createDecompressInterceptor (options = {}) { + // Emit experimental warning only once + if (!warningEmitted) { + process.emitWarning( + 'DecompressInterceptor is experimental and subject to change', + 'ExperimentalWarning' + ) + warningEmitted = true } - /** - * Closes the agent, saving snapshots and cleaning up resources. - * - * @returns {Promise} - */ - async close () { - await this[kSnapshotRecorder].close() - await this[kRealAgent]?.close() - await super.close() + return (dispatch) => { + return (opts, handler) => { + const decompressHandler = new DecompressHandler(handler, options) + return dispatch(opts, decompressHandler) + } } } -module.exports = SnapshotAgent +module.exports = createDecompressInterceptor /***/ }), -/***/ 9647: +/***/ 2010: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -const { writeFile, readFile, mkdir } = __nccwpck_require__(1455) -const { dirname, resolve } = __nccwpck_require__(4379) -const { setTimeout, clearTimeout } = __nccwpck_require__(7997) -const { InvalidArgumentError, UndiciError } = __nccwpck_require__(4928) -const { hashId, isUrlExcludedFactory, normalizeHeaders, createHeaderFilters } = __nccwpck_require__(1998) +const diagnosticsChannel = __nccwpck_require__(3053) +const util = __nccwpck_require__(2550) +const DeduplicationHandler = __nccwpck_require__(5485) +const { normalizeHeaders, makeCacheKey, makeDeduplicationKey } = __nccwpck_require__(4649) -/** - * @typedef {Object} SnapshotRequestOptions - * @property {string} method - HTTP method (e.g. 'GET', 'POST', etc.) - * @property {string} path - Request path - * @property {string} origin - Request origin (base URL) - * @property {import('./snapshot-utils').Headers|import('./snapshot-utils').UndiciHeaders} headers - Request headers - * @property {import('./snapshot-utils').NormalizedHeaders} _normalizedHeaders - Request headers as a lowercase object - * @property {string|Buffer} [body] - Request body (optional) - */ +const pendingRequestsChannel = diagnosticsChannel.channel('undici:request:pending-requests') /** - * @typedef {Object} SnapshotEntryRequest - * @property {string} method - HTTP method (e.g. 'GET', 'POST', etc.) - * @property {string} url - Full URL of the request - * @property {import('./snapshot-utils').NormalizedHeaders} headers - Normalized headers as a lowercase object - * @property {string|Buffer} [body] - Request body (optional) + * @param {import('../../types/interceptors.d.ts').default.DeduplicateInterceptorOpts} [opts] + * @returns {import('../../types/dispatcher.d.ts').default.DispatcherComposeInterceptor} */ +module.exports = (opts = {}) => { + const { + methods = ['GET'], + skipHeaderNames = [], + excludeHeaderNames = [] + } = opts -/** - * @typedef {Object} SnapshotEntryResponse - * @property {number} statusCode - HTTP status code of the response - * @property {import('./snapshot-utils').NormalizedHeaders} headers - Normalized response headers as a lowercase object - * @property {string} body - Response body as a base64url encoded string - * @property {Object} [trailers] - Optional response trailers - */ + if (typeof opts !== 'object' || opts === null) { + throw new TypeError(`expected type of opts to be an Object, got ${opts === null ? 'null' : typeof opts}`) + } -/** - * @typedef {Object} SnapshotEntry - * @property {SnapshotEntryRequest} request - The request object - * @property {Array} responses - Array of response objects - * @property {number} callCount - Number of times this snapshot has been called - * @property {string} timestamp - ISO timestamp of when the snapshot was created - */ + if (!Array.isArray(methods)) { + throw new TypeError(`expected opts.methods to be an array, got ${typeof methods}`) + } -/** - * @typedef {Object} SnapshotRecorderMatchOptions - * @property {Array} [matchHeaders=[]] - Headers to match (empty array means match all headers) - * @property {Array} [ignoreHeaders=[]] - Headers to ignore for matching - * @property {Array} [excludeHeaders=[]] - Headers to exclude from matching - * @property {boolean} [matchBody=true] - Whether to match request body - * @property {boolean} [matchQuery=true] - Whether to match query properties - * @property {boolean} [caseSensitive=false] - Whether header matching is case-sensitive - */ + for (const method of methods) { + if (!util.safeHTTPMethods.includes(method)) { + throw new TypeError(`expected opts.methods to only contain safe HTTP methods, got ${method}`) + } + } -/** - * @typedef {Object} SnapshotRecorderOptions - * @property {string} [snapshotPath] - Path to save/load snapshots - * @property {import('./snapshot-utils').SnapshotMode} [mode='record'] - Mode: 'record' or 'playback' - * @property {number} [maxSnapshots=Infinity] - Maximum number of snapshots to keep - * @property {boolean} [autoFlush=false] - Whether to automatically flush snapshots to disk - * @property {number} [flushInterval=30000] - Auto-flush interval in milliseconds (default: 30 seconds) - * @property {Array} [excludeUrls=[]] - URLs to exclude from recording - * @property {function} [shouldRecord=null] - Function to filter requests for recording - * @property {function} [shouldPlayback=null] - Function to filter requests - */ + if (!Array.isArray(skipHeaderNames)) { + throw new TypeError(`expected opts.skipHeaderNames to be an array, got ${typeof skipHeaderNames}`) + } -/** - * @typedef {Object} SnapshotFormattedRequest - * @property {string} method - HTTP method (e.g. 'GET', 'POST', etc.) - * @property {string} url - Full URL of the request (with query parameters if matchQuery is true) - * @property {import('./snapshot-utils').NormalizedHeaders} headers - Normalized headers as a lowercase object - * @property {string} body - Request body (optional, only if matchBody is true) - */ + if (!Array.isArray(excludeHeaderNames)) { + throw new TypeError(`expected opts.excludeHeaderNames to be an array, got ${typeof excludeHeaderNames}`) + } -/** - * @typedef {Object} SnapshotInfo - * @property {string} hash - Hash key for the snapshot - * @property {SnapshotEntryRequest} request - The request object - * @property {number} responseCount - Number of responses recorded for this request - * @property {number} callCount - Number of times this snapshot has been called - * @property {string} timestamp - ISO timestamp of when the snapshot was created - */ + // Convert to lowercase Set for case-insensitive header matching + const skipHeaderNamesSet = new Set(skipHeaderNames.map(name => name.toLowerCase())) -/** - * Formats a request for consistent snapshot storage - * Caches normalized headers to avoid repeated processing - * - * @param {SnapshotRequestOptions} opts - Request options - * @param {import('./snapshot-utils').HeaderFilters} headerFilters - Cached header sets for performance - * @param {SnapshotRecorderMatchOptions} [matchOptions] - Matching options for headers and body - * @returns {SnapshotFormattedRequest} - Formatted request object - */ -function formatRequestKey (opts, headerFilters, matchOptions = {}) { - const url = new URL(opts.path, opts.origin) + // Convert to lowercase Set for case-insensitive header exclusion from deduplication key + const excludeHeaderNamesSet = new Set(excludeHeaderNames.map(name => name.toLowerCase())) - // Cache normalized headers if not already done - const normalized = opts._normalizedHeaders || normalizeHeaders(opts.headers) - if (!opts._normalizedHeaders) { - opts._normalizedHeaders = normalized - } + const safeMethodsToNotDeduplicate = util.safeHTTPMethods.filter(method => methods.includes(method) === false) - return { - method: opts.method || 'GET', - url: matchOptions.matchQuery !== false ? url.toString() : `${url.origin}${url.pathname}`, - headers: filterHeadersForMatching(normalized, headerFilters, matchOptions), - body: matchOptions.matchBody !== false && opts.body ? String(opts.body) : '' - } -} + /** + * Map of pending requests for deduplication + * @type {Map} + */ + const pendingRequests = new Map() -/** - * Filters headers based on matching configuration - * - * @param {import('./snapshot-utils').Headers} headers - Headers to filter - * @param {import('./snapshot-utils').HeaderFilters} headerFilters - Cached sets for ignore, exclude, and match headers - * @param {SnapshotRecorderMatchOptions} [matchOptions] - Matching options for headers - */ -function filterHeadersForMatching (headers, headerFilters, matchOptions = {}) { - if (!headers || typeof headers !== 'object') return {} + return dispatch => { + return (opts, handler) => { + if (!opts.origin || safeMethodsToNotDeduplicate.includes(opts.method)) { + return dispatch(opts, handler) + } - const { - caseSensitive = false - } = matchOptions + opts = { + ...opts, + headers: normalizeHeaders(opts) + } - const filtered = {} - const { ignore, exclude, match } = headerFilters + // Skip deduplication if request contains any of the specified headers + if (skipHeaderNamesSet.size > 0) { + for (const headerName of Object.keys(opts.headers)) { + if (skipHeaderNamesSet.has(headerName.toLowerCase())) { + return dispatch(opts, handler) + } + } + } - for (const [key, value] of Object.entries(headers)) { - const headerKey = caseSensitive ? key : key.toLowerCase() + const cacheKey = makeCacheKey(opts) + const dedupeKey = makeDeduplicationKey(cacheKey, excludeHeaderNamesSet) - // Skip if in exclude list (for security) - if (exclude.has(headerKey)) continue + // Check if there's already a pending request for this key + const pendingHandler = pendingRequests.get(dedupeKey) + if (pendingHandler) { + // Add this handler to the waiting list + pendingHandler.addWaitingHandler(handler) + return true + } - // Skip if in ignore list (for matching) - if (ignore.has(headerKey)) continue + // Create a new deduplication handler + const deduplicationHandler = new DeduplicationHandler( + handler, + () => { + // Clean up when request completes + pendingRequests.delete(dedupeKey) + if (pendingRequestsChannel.hasSubscribers) { + pendingRequestsChannel.publish({ size: pendingRequests.size, key: dedupeKey, type: 'removed' }) + } + } + ) - // If matchHeaders is specified, only include those headers - if (match.size !== 0) { - if (!match.has(headerKey)) continue - } + // Register the pending request + pendingRequests.set(dedupeKey, deduplicationHandler) + if (pendingRequestsChannel.hasSubscribers) { + pendingRequestsChannel.publish({ size: pendingRequests.size, key: dedupeKey, type: 'added' }) + } - filtered[headerKey] = value + return dispatch(opts, deduplicationHandler) + } } - - return filtered } -/** - * Filters headers for storage (only excludes sensitive headers) - * - * @param {import('./snapshot-utils').Headers} headers - Headers to filter - * @param {import('./snapshot-utils').HeaderFilters} headerFilters - Cached sets for ignore, exclude, and match headers - * @param {SnapshotRecorderMatchOptions} [matchOptions] - Matching options for headers - */ -function filterHeadersForStorage (headers, headerFilters, matchOptions = {}) { - if (!headers || typeof headers !== 'object') return {} - - const { - caseSensitive = false - } = matchOptions - - const filtered = {} - const { exclude: excludeSet } = headerFilters - for (const [key, value] of Object.entries(headers)) { - const headerKey = caseSensitive ? key : key.toLowerCase() +/***/ }), - // Skip if in exclude list (for security) - if (excludeSet.has(headerKey)) continue +/***/ 3014: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - filtered[headerKey] = value - } - return filtered -} +const { isIP } = __nccwpck_require__(7030) +const { lookup } = __nccwpck_require__(610) +const DecoratorHandler = __nccwpck_require__(169) +const { InvalidArgumentError, InformationalError } = __nccwpck_require__(5093) +const maxInt = Math.pow(2, 31) - 1 -/** - * Creates a hash key for request matching - * Properly orders headers to avoid conflicts and uses crypto hashing when available - * - * @param {SnapshotFormattedRequest} formattedRequest - Request object - * @returns {string} - Base64url encoded hash of the request - */ -function createRequestHash (formattedRequest) { - const parts = [ - formattedRequest.method, - formattedRequest.url - ] +class DNSStorage { + #maxItems = 0 + #records = new Map() - // Process headers in a deterministic way to avoid conflicts - if (formattedRequest.headers && typeof formattedRequest.headers === 'object') { - const headerKeys = Object.keys(formattedRequest.headers).sort() - for (const key of headerKeys) { - const values = Array.isArray(formattedRequest.headers[key]) - ? formattedRequest.headers[key] - : [formattedRequest.headers[key]] + constructor (opts) { + this.#maxItems = opts.maxItems + } - // Add header name - parts.push(key) + get size () { + return this.#records.size + } - // Add all values for this header, sorted for consistency - for (const value of values.sort()) { - parts.push(String(value)) - } - } + get (hostname) { + return this.#records.get(hostname) ?? null } - // Add body - parts.push(formattedRequest.body) + set (hostname, records) { + this.#records.set(hostname, records) + } - const content = parts.join('|') + delete (hostname) { + this.#records.delete(hostname) + } - return hashId(content) + // Delegate to storage decide can we do more lookups or not + full () { + return this.size >= this.#maxItems + } } -class SnapshotRecorder { - /** @type {NodeJS.Timeout | null} */ - #flushTimeout - - /** @type {import('./snapshot-utils').IsUrlExcluded} */ - #isUrlExcluded - - /** @type {Map} */ - #snapshots = new Map() - - /** @type {string|undefined} */ - #snapshotPath - - /** @type {number} */ - #maxSnapshots = Infinity +class DNSInstance { + #maxTTL = 0 + #maxItems = 0 + dualStack = true + affinity = null + lookup = null + pick = null + storage = null - /** @type {boolean} */ - #autoFlush = false + constructor (opts) { + this.#maxTTL = opts.maxTTL + this.#maxItems = opts.maxItems + this.dualStack = opts.dualStack + this.affinity = opts.affinity + this.lookup = opts.lookup ?? this.#defaultLookup + this.pick = opts.pick ?? this.#defaultPick + this.storage = opts.storage ?? new DNSStorage(opts) + } - /** @type {import('./snapshot-utils').HeaderFilters} */ - #headerFilters + runLookup (origin, opts, cb) { + const ips = this.storage.get(origin.hostname) - /** - * Creates a new SnapshotRecorder instance - * @param {SnapshotRecorderOptions&SnapshotRecorderMatchOptions} [options={}] - Configuration options for the recorder - */ - constructor (options = {}) { - this.#snapshotPath = options.snapshotPath - this.#maxSnapshots = options.maxSnapshots || Infinity - this.#autoFlush = options.autoFlush || false - this.flushInterval = options.flushInterval || 30000 // 30 seconds default - this._flushTimer = null + // If full, we just return the origin + if (ips == null && this.storage.full()) { + cb(null, origin) + return + } - // Matching configuration - /** @type {Required} */ - this.matchOptions = { - matchHeaders: options.matchHeaders || [], // empty means match all headers - ignoreHeaders: options.ignoreHeaders || [], - excludeHeaders: options.excludeHeaders || [], - matchBody: options.matchBody !== false, // default: true - matchQuery: options.matchQuery !== false, // default: true - caseSensitive: options.caseSensitive || false + const newOpts = { + affinity: this.affinity, + dualStack: this.dualStack, + lookup: this.lookup, + pick: this.pick, + ...opts.dns, + maxTTL: this.#maxTTL, + maxItems: this.#maxItems } - // Cache processed header sets to avoid recreating them on every request - this.#headerFilters = createHeaderFilters(this.matchOptions) + // If no IPs we lookup + if (ips == null) { + this.lookup(origin, newOpts, (err, addresses) => { + if (err || addresses == null || addresses.length === 0) { + cb(err ?? new InformationalError('No DNS entries found')) + return + } - // Request filtering callbacks - this.shouldRecord = options.shouldRecord || (() => true) // function(requestOpts) -> boolean - this.shouldPlayback = options.shouldPlayback || (() => true) // function(requestOpts) -> boolean + this.setRecords(origin, addresses) + const records = this.storage.get(origin.hostname) - // URL pattern filtering - this.#isUrlExcluded = isUrlExcludedFactory(options.excludeUrls) // Array of regex patterns or strings + const ip = this.pick( + origin, + records, + newOpts.affinity + ) - // Start auto-flush timer if enabled - if (this.#autoFlush && this.#snapshotPath) { - this.#startAutoFlush() + let port + if (typeof ip.port === 'number') { + port = `:${ip.port}` + } else if (origin.port !== '') { + port = `:${origin.port}` + } else { + port = '' + } + + cb( + null, + new URL(`${origin.protocol}//${ + ip.family === 6 ? `[${ip.address}]` : ip.address + }${port}`) + ) + }) + } else { + // If there's IPs we pick + const ip = this.pick( + origin, + ips, + newOpts.affinity + ) + + // If no IPs we lookup - deleting old records + if (ip == null) { + this.storage.delete(origin.hostname) + this.runLookup(origin, opts, cb) + return + } + + let port + if (typeof ip.port === 'number') { + port = `:${ip.port}` + } else if (origin.port !== '') { + port = `:${origin.port}` + } else { + port = '' + } + + cb( + null, + new URL(`${origin.protocol}//${ + ip.family === 6 ? `[${ip.address}]` : ip.address + }${port}`) + ) } } - /** - * Records a request-response interaction - * @param {SnapshotRequestOptions} requestOpts - Request options - * @param {SnapshotEntryResponse} response - Response data to record - * @return {Promise} - Resolves when the recording is complete - */ - async record (requestOpts, response) { - // Check if recording should be filtered out - if (!this.shouldRecord(requestOpts)) { - return // Skip recording - } + #defaultLookup (origin, opts, cb) { + lookup( + origin.hostname, + { + all: true, + family: this.dualStack === false ? this.affinity : 0, + order: 'ipv4first' + }, + (err, addresses) => { + if (err) { + return cb(err) + } - // Check URL exclusion patterns - if (this.isUrlExcluded(requestOpts)) { - return // Skip recording - } + const results = new Map() - const request = formatRequestKey(requestOpts, this.#headerFilters, this.matchOptions) - const hash = createRequestHash(request) + for (const addr of addresses) { + // On linux we found duplicates, we attempt to remove them with + // the latest record + results.set(`${addr.address}:${addr.family}`, addr) + } - // Extract response data - always store body as base64 - const normalizedHeaders = normalizeHeaders(response.headers) + cb(null, results.values()) + } + ) + } - /** @type {SnapshotEntryResponse} */ - const responseData = { - statusCode: response.statusCode, - headers: filterHeadersForStorage(normalizedHeaders, this.#headerFilters, this.matchOptions), - body: Buffer.isBuffer(response.body) - ? response.body.toString('base64') - : Buffer.from(String(response.body || '')).toString('base64'), - trailers: response.trailers - } + #defaultPick (origin, hostnameRecords, affinity) { + let ip = null + const { records, offset } = hostnameRecords - // Remove oldest snapshot if we exceed maxSnapshots limit - if (this.#snapshots.size >= this.#maxSnapshots && !this.#snapshots.has(hash)) { - const oldestKey = this.#snapshots.keys().next().value - this.#snapshots.delete(oldestKey) - } + let family + if (this.dualStack) { + if (affinity == null) { + // Balance between ip families + if (offset == null || offset === maxInt) { + hostnameRecords.offset = 0 + affinity = 4 + } else { + hostnameRecords.offset++ + affinity = (hostnameRecords.offset & 1) === 1 ? 6 : 4 + } + } - // Support sequential responses - if snapshot exists, add to responses array - const existingSnapshot = this.#snapshots.get(hash) - if (existingSnapshot && existingSnapshot.responses) { - existingSnapshot.responses.push(responseData) - existingSnapshot.timestamp = new Date().toISOString() + if (records[affinity] != null && records[affinity].ips.length > 0) { + family = records[affinity] + } else { + family = records[affinity === 4 ? 6 : 4] + } } else { - this.#snapshots.set(hash, { - request, - responses: [responseData], // Always store as array for consistency - callCount: 0, - timestamp: new Date().toISOString() - }) + family = records[affinity] } - // Auto-flush if enabled - if (this.#autoFlush && this.#snapshotPath) { - this.#scheduleFlush() + // If no IPs we return null + if (family == null || family.ips.length === 0) { + return ip } - } - /** - * Checks if a URL should be excluded from recording/playback - * @param {SnapshotRequestOptions} requestOpts - Request options to check - * @returns {boolean} - True if URL is excluded - */ - isUrlExcluded (requestOpts) { - const url = new URL(requestOpts.path, requestOpts.origin).toString() - return this.#isUrlExcluded(url) - } - - /** - * Finds a matching snapshot for the given request - * Returns the appropriate response based on call count for sequential responses - * - * @param {SnapshotRequestOptions} requestOpts - Request options to match - * @returns {SnapshotEntry&Record<'response', SnapshotEntryResponse>|undefined} - Matching snapshot response or undefined if not found - */ - findSnapshot (requestOpts) { - // Check if playback should be filtered out - if (!this.shouldPlayback(requestOpts)) { - return undefined // Skip playback + if (family.offset == null || family.offset === maxInt) { + family.offset = 0 + } else { + family.offset++ } - // Check URL exclusion patterns - if (this.isUrlExcluded(requestOpts)) { - return undefined // Skip playback - } + const position = family.offset % family.ips.length + ip = family.ips[position] ?? null - const request = formatRequestKey(requestOpts, this.#headerFilters, this.matchOptions) - const hash = createRequestHash(request) - const snapshot = this.#snapshots.get(hash) + if (ip == null) { + return ip + } - if (!snapshot) return undefined + if (Date.now() - ip.timestamp > ip.ttl) { // record TTL is already in ms + // We delete expired records + // It is possible that they have different TTL, so we manage them individually + family.ips.splice(position, 1) + return this.pick(origin, hostnameRecords, affinity) + } - // Handle sequential responses - const currentCallCount = snapshot.callCount || 0 - const responseIndex = Math.min(currentCallCount, snapshot.responses.length - 1) - snapshot.callCount = currentCallCount + 1 + return ip + } - return { - ...snapshot, - response: snapshot.responses[responseIndex] + pickFamily (origin, ipFamily) { + const records = this.storage.get(origin.hostname)?.records + if (!records) { + return null } - } - /** - * Loads snapshots from file - * @param {string} [filePath] - Optional file path to load snapshots from - * @return {Promise} - Resolves when snapshots are loaded - */ - async loadSnapshots (filePath) { - const path = filePath || this.#snapshotPath - if (!path) { - throw new InvalidArgumentError('Snapshot path is required') + const family = records[ipFamily] + if (!family) { + return null } - try { - const data = await readFile(resolve(path), 'utf8') - const parsed = JSON.parse(data) + if (family.offset == null || family.offset === maxInt) { + family.offset = 0 + } else { + family.offset++ + } - // Convert array format back to Map - if (Array.isArray(parsed)) { - this.#snapshots.clear() - for (const { hash, snapshot } of parsed) { - this.#snapshots.set(hash, snapshot) - } - } else { - // Legacy object format - this.#snapshots = new Map(Object.entries(parsed)) - } - } catch (error) { - if (error.code === 'ENOENT') { - // File doesn't exist yet - that's ok for recording mode - this.#snapshots.clear() - } else { - throw new UndiciError(`Failed to load snapshots from ${path}`, { cause: error }) - } + const position = family.offset % family.ips.length + const ip = family.ips[position] ?? null + if (ip == null) { + return ip } - } - /** - * Saves snapshots to file - * - * @param {string} [filePath] - Optional file path to save snapshots - * @returns {Promise} - Resolves when snapshots are saved - */ - async saveSnapshots (filePath) { - const path = filePath || this.#snapshotPath - if (!path) { - throw new InvalidArgumentError('Snapshot path is required') + if (Date.now() - ip.timestamp > ip.ttl) { // record TTL is already in ms + // We delete expired records + // It is possible that they have different TTL, so we manage them individually + family.ips.splice(position, 1) } - const resolvedPath = resolve(path) + return ip + } - // Ensure directory exists - await mkdir(dirname(resolvedPath), { recursive: true }) + setRecords (origin, addresses) { + const timestamp = Date.now() + const records = { records: { 4: null, 6: null } } + let minTTL = this.#maxTTL + for (const record of addresses) { + record.timestamp = timestamp + if (typeof record.ttl === 'number') { + // The record TTL is expected to be in ms + record.ttl = Math.min(record.ttl, this.#maxTTL) + minTTL = Math.min(minTTL, record.ttl) + } else { + record.ttl = this.#maxTTL + } - // Convert Map to serializable format - const data = Array.from(this.#snapshots.entries()).map(([hash, snapshot]) => ({ - hash, - snapshot - })) + const familyRecords = records.records[record.family] ?? { ips: [] } - await writeFile(resolvedPath, JSON.stringify(data, null, 2), { flush: true }) - } + familyRecords.ips.push(record) + records.records[record.family] = familyRecords + } - /** - * Clears all recorded snapshots - * @returns {void} - */ - clear () { - this.#snapshots.clear() + // We provide a default TTL if external storage will be used without TTL per record-level support + this.storage.set(origin.hostname, records, { ttl: minTTL }) } - /** - * Gets all recorded snapshots - * @return {Array} - Array of all recorded snapshots - */ - getSnapshots () { - return Array.from(this.#snapshots.values()) + deleteRecords (origin) { + this.storage.delete(origin.hostname) } - /** - * Gets snapshot count - * @return {number} - Number of recorded snapshots - */ - size () { - return this.#snapshots.size + getHandler (meta, opts) { + return new DNSDispatchHandler(this, meta, opts) } +} - /** - * Resets call counts for all snapshots (useful for test cleanup) - * @returns {void} - */ - resetCallCounts () { - for (const snapshot of this.#snapshots.values()) { - snapshot.callCount = 0 - } - } +class DNSDispatchHandler extends DecoratorHandler { + #state = null + #opts = null + #dispatch = null + #origin = null + #controller = null + #newOrigin = null + #firstTry = true - /** - * Deletes a specific snapshot by request options - * @param {SnapshotRequestOptions} requestOpts - Request options to match - * @returns {boolean} - True if snapshot was deleted, false if not found - */ - deleteSnapshot (requestOpts) { - const request = formatRequestKey(requestOpts, this.#headerFilters, this.matchOptions) - const hash = createRequestHash(request) - return this.#snapshots.delete(hash) + constructor (state, { origin, handler, dispatch, newOrigin }, opts) { + super(handler) + this.#origin = origin + this.#newOrigin = newOrigin + this.#opts = { ...opts } + this.#state = state + this.#dispatch = dispatch } - /** - * Gets information about a specific snapshot - * @param {SnapshotRequestOptions} requestOpts - Request options to match - * @returns {SnapshotInfo|null} - Snapshot information or null if not found - */ - getSnapshotInfo (requestOpts) { - const request = formatRequestKey(requestOpts, this.#headerFilters, this.matchOptions) - const hash = createRequestHash(request) - const snapshot = this.#snapshots.get(hash) + onResponseError (controller, err) { + switch (err.code) { + case 'ETIMEDOUT': + case 'ECONNREFUSED': { + if (this.#state.dualStack) { + if (!this.#firstTry) { + super.onResponseError(controller, err) + return + } + this.#firstTry = false - if (!snapshot) return null + // Pick an ip address from the other family + const otherFamily = this.#newOrigin.hostname[0] === '[' ? 4 : 6 + const ip = this.#state.pickFamily(this.#origin, otherFamily) + if (ip == null) { + super.onResponseError(controller, err) + return + } - return { - hash, - request: snapshot.request, - responseCount: snapshot.responses ? snapshot.responses.length : (snapshot.response ? 1 : 0), // .response for legacy snapshots - callCount: snapshot.callCount || 0, - timestamp: snapshot.timestamp - } - } + let port + if (typeof ip.port === 'number') { + port = `:${ip.port}` + } else if (this.#origin.port !== '') { + port = `:${this.#origin.port}` + } else { + port = '' + } - /** - * Replaces all snapshots with new data (full replacement) - * @param {Array<{hash: string; snapshot: SnapshotEntry}>|Record} snapshotData - New snapshot data to replace existing ones - * @returns {void} - */ - replaceSnapshots (snapshotData) { - this.#snapshots.clear() + const dispatchOpts = { + ...this.#opts, + origin: `${this.#origin.protocol}//${ + ip.family === 6 ? `[${ip.address}]` : ip.address + }${port}` + } + this.#dispatch(dispatchOpts, this) + return + } - if (Array.isArray(snapshotData)) { - for (const { hash, snapshot } of snapshotData) { - this.#snapshots.set(hash, snapshot) + // if dual-stack disabled, we error out + super.onResponseError(controller, err) + break } - } else if (snapshotData && typeof snapshotData === 'object') { - // Legacy object format - this.#snapshots = new Map(Object.entries(snapshotData)) + case 'ENOTFOUND': + this.#state.deleteRecords(this.#origin) + super.onResponseError(controller, err) + break + default: + super.onResponseError(controller, err) + break } } +} - /** - * Starts the auto-flush timer - * @returns {void} - */ - #startAutoFlush () { - return this.#scheduleFlush() - } - - /** - * Stops the auto-flush timer - * @returns {void} - */ - #stopAutoFlush () { - if (this.#flushTimeout) { - clearTimeout(this.#flushTimeout) - // Ensure any pending flush is completed - this.saveSnapshots().catch(() => { - // Ignore flush errors - }) - this.#flushTimeout = null - } +module.exports = interceptorOpts => { + if ( + interceptorOpts?.maxTTL != null && + (typeof interceptorOpts?.maxTTL !== 'number' || interceptorOpts?.maxTTL < 0) + ) { + throw new InvalidArgumentError('Invalid maxTTL. Must be a positive number') } - /** - * Schedules a flush (debounced to avoid excessive writes) - */ - #scheduleFlush () { - this.#flushTimeout = setTimeout(() => { - this.saveSnapshots().catch(() => { - // Ignore flush errors - }) - if (this.#autoFlush) { - this.#flushTimeout?.refresh() - } else { - this.#flushTimeout = null - } - }, 1000) // 1 second debounce + if ( + interceptorOpts?.maxItems != null && + (typeof interceptorOpts?.maxItems !== 'number' || + interceptorOpts?.maxItems < 1) + ) { + throw new InvalidArgumentError( + 'Invalid maxItems. Must be a positive number and greater than zero' + ) } - /** - * Cleanup method to stop timers - * @returns {void} - */ - destroy () { - this.#stopAutoFlush() - if (this.#flushTimeout) { - clearTimeout(this.#flushTimeout) - this.#flushTimeout = null - } + if ( + interceptorOpts?.affinity != null && + interceptorOpts?.affinity !== 4 && + interceptorOpts?.affinity !== 6 + ) { + throw new InvalidArgumentError('Invalid affinity. Must be either 4 or 6') } - /** - * Async close method that saves all recordings and performs cleanup - * @returns {Promise} - */ - async close () { - // Save any pending recordings if we have a snapshot path - if (this.#snapshotPath && this.#snapshots.size !== 0) { - await this.saveSnapshots() - } + if ( + interceptorOpts?.dualStack != null && + typeof interceptorOpts?.dualStack !== 'boolean' + ) { + throw new InvalidArgumentError('Invalid dualStack. Must be a boolean') + } - // Perform cleanup - this.destroy() + if ( + interceptorOpts?.lookup != null && + typeof interceptorOpts?.lookup !== 'function' + ) { + throw new InvalidArgumentError('Invalid lookup. Must be a function') } -} -module.exports = { SnapshotRecorder, formatRequestKey, createRequestHash, filterHeadersForMatching, filterHeadersForStorage, createHeaderFilters } + if ( + interceptorOpts?.pick != null && + typeof interceptorOpts?.pick !== 'function' + ) { + throw new InvalidArgumentError('Invalid pick. Must be a function') + } + if ( + interceptorOpts?.storage != null && + (typeof interceptorOpts?.storage?.get !== 'function' || + typeof interceptorOpts?.storage?.set !== 'function' || + typeof interceptorOpts?.storage?.full !== 'function' || + typeof interceptorOpts?.storage?.delete !== 'function' + ) + ) { + throw new InvalidArgumentError('Invalid storage. Must be a object with methods: { get, set, full, delete }') + } -/***/ }), + const dualStack = interceptorOpts?.dualStack ?? true + let affinity + if (dualStack) { + affinity = interceptorOpts?.affinity ?? null + } else { + affinity = interceptorOpts?.affinity ?? 4 + } -/***/ 1998: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + const opts = { + maxTTL: interceptorOpts?.maxTTL ?? 10e3, // Expressed in ms + lookup: interceptorOpts?.lookup ?? null, + pick: interceptorOpts?.pick ?? null, + dualStack, + affinity, + maxItems: interceptorOpts?.maxItems ?? Infinity, + storage: interceptorOpts?.storage + } -"use strict"; + const instance = new DNSInstance(opts) + return dispatch => { + return function dnsInterceptor (origDispatchOpts, handler) { + const origin = + origDispatchOpts.origin.constructor === URL + ? origDispatchOpts.origin + : new URL(origDispatchOpts.origin) -const { InvalidArgumentError } = __nccwpck_require__(4928) -const { runtimeFeatures } = __nccwpck_require__(1422) + if (isIP(origin.hostname) !== 0) { + return dispatch(origDispatchOpts, handler) + } -/** - * @typedef {Object} HeaderFilters - * @property {Set} ignore - Set of headers to ignore for matching - * @property {Set} exclude - Set of headers to exclude from matching - * @property {Set} match - Set of headers to match (empty means match - */ + instance.runLookup(origin, origDispatchOpts, (err, newOrigin) => { + if (err) { + return handler.onResponseError(null, err) + } -/** - * Creates cached header sets for performance - * - * @param {import('./snapshot-recorder').SnapshotRecorderMatchOptions} matchOptions - Matching options for headers - * @returns {HeaderFilters} - Cached sets for ignore, exclude, and match headers - */ -function createHeaderFilters (matchOptions = {}) { - const { ignoreHeaders = [], excludeHeaders = [], matchHeaders = [], caseSensitive = false } = matchOptions + const dispatchOpts = { + ...origDispatchOpts, + servername: origin.hostname, // For SNI on TLS + origin: newOrigin.origin, + headers: { + host: origin.host, + ...origDispatchOpts.headers + } + } - return { - ignore: new Set(ignoreHeaders.map(header => caseSensitive ? header : header.toLowerCase())), - exclude: new Set(excludeHeaders.map(header => caseSensitive ? header : header.toLowerCase())), - match: new Set(matchHeaders.map(header => caseSensitive ? header : header.toLowerCase())) + dispatch( + dispatchOpts, + instance.getHandler( + { origin, dispatch, handler, newOrigin }, + origDispatchOpts + ) + ) + }) + + return true + } } } -const crypto = runtimeFeatures.has('crypto') - ? __nccwpck_require__(7598) - : null -/** - * @callback HashIdFunction - * @param {string} value - The value to hash - * @returns {string} - The base64url encoded hash of the value - */ +/***/ }), -/** - * Generates a hash for a given value - * @type {HashIdFunction} - */ -const hashId = crypto?.hash - ? (value) => crypto.hash('sha256', value, 'base64url') - : (value) => Buffer.from(value).toString('base64url') +/***/ 3694: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -/** - * @typedef {(url: string) => boolean} IsUrlExcluded Checks if a URL matches any of the exclude patterns - */ -/** @typedef {{[key: Lowercase]: string}} NormalizedHeaders */ -/** @typedef {Array} UndiciHeaders */ -/** @typedef {Record} Headers */ -/** - * @param {*} headers - * @returns {headers is UndiciHeaders} - */ -function isUndiciHeaders (headers) { - return Array.isArray(headers) && (headers.length & 1) === 0 -} +const { InvalidArgumentError, RequestAbortedError } = __nccwpck_require__(5093) +const DecoratorHandler = __nccwpck_require__(169) -/** - * Factory function to create a URL exclusion checker - * @param {Array} [excludePatterns=[]] - Array of patterns to exclude - * @returns {IsUrlExcluded} - A function that checks if a URL matches any of the exclude patterns - */ -function isUrlExcludedFactory (excludePatterns = []) { - if (excludePatterns.length === 0) { - return () => false +class DumpHandler extends DecoratorHandler { + #maxSize = 1024 * 1024 + #dumped = false + #size = 0 + #controller = null + aborted = false + reason = false + + constructor ({ maxSize, signal }, handler) { + if (maxSize != null && (!Number.isFinite(maxSize) || maxSize < 1)) { + throw new InvalidArgumentError('maxSize must be a number greater than 0') + } + + super(handler) + + this.#maxSize = maxSize ?? this.#maxSize + // this.#handler = handler } - return function isUrlExcluded (url) { - let urlLowerCased + #abort (reason) { + this.aborted = true + this.reason = reason + } - for (const pattern of excludePatterns) { - if (typeof pattern === 'string') { - if (!urlLowerCased) { - // Convert URL to lowercase only once - urlLowerCased = url.toLowerCase() - } - // Simple string match (case-insensitive) - if (urlLowerCased.includes(pattern.toLowerCase())) { - return true - } - } else if (pattern instanceof RegExp) { - // Regex pattern match - if (pattern.test(url)) { - return true - } - } - } + onRequestStart (controller, context) { + controller.abort = this.#abort.bind(this) + this.#controller = controller - return false + return super.onRequestStart(controller, context) } -} -/** - * Normalizes headers for consistent comparison - * - * @param {Object|UndiciHeaders} headers - Headers to normalize - * @returns {NormalizedHeaders} - Normalized headers as a lowercase object - */ -function normalizeHeaders (headers) { - /** @type {NormalizedHeaders} */ - const normalizedHeaders = {} + onResponseStart (controller, statusCode, headers, statusMessage) { + const contentLength = headers['content-length'] - if (!headers) return normalizedHeaders + if (contentLength != null && contentLength > this.#maxSize) { + throw new RequestAbortedError( + `Response size (${contentLength}) larger than maxSize (${ + this.#maxSize + })` + ) + } - // Handle array format (undici internal format: [name, value, name, value, ...]) - if (isUndiciHeaders(headers)) { - for (let i = 0; i < headers.length; i += 2) { - const key = headers[i] - const value = headers[i + 1] - if (key && value !== undefined) { - // Convert Buffers to strings if needed - const keyStr = Buffer.isBuffer(key) ? key.toString() : key - const valueStr = Buffer.isBuffer(value) ? value.toString() : value - normalizedHeaders[keyStr.toLowerCase()] = valueStr - } + if (this.aborted === true) { + return true } - return normalizedHeaders + + return super.onResponseStart(controller, statusCode, headers, statusMessage) } - // Handle object format - if (headers && typeof headers === 'object') { - for (const [key, value] of Object.entries(headers)) { - if (key && typeof key === 'string') { - normalizedHeaders[key.toLowerCase()] = Array.isArray(value) ? value.join(', ') : String(value) + onResponseError (controller, err) { + if (this.#dumped) { + return + } + + // On network errors before connect, controller will be null + err = this.#controller?.reason ?? err + + super.onResponseError(controller, err) + } + + onResponseData (controller, chunk) { + this.#size = this.#size + chunk.length + + if (this.#size >= this.#maxSize) { + this.#dumped = true + + if (this.aborted === true) { + super.onResponseError(controller, this.reason) + } else { + super.onResponseEnd(controller, {}) } } + + return true } - return normalizedHeaders + onResponseEnd (controller, trailers) { + if (this.#dumped) { + return + } + + if (this.#controller.aborted === true) { + super.onResponseError(controller, this.reason) + return + } + + super.onResponseEnd(controller, trailers) + } } -const validSnapshotModes = /** @type {const} */ (['record', 'playback', 'update']) +function createDumpInterceptor ( + { maxSize: defaultMaxSize } = { + maxSize: 1024 * 1024 + } +) { + return dispatch => { + return function Intercept (opts, handler) { + const { dumpMaxSize = defaultMaxSize } = opts -/** @typedef {typeof validSnapshotModes[number]} SnapshotMode */ + const dumpHandler = new DumpHandler({ maxSize: dumpMaxSize, signal: opts.signal }, handler) -/** - * @param {*} mode - The snapshot mode to validate - * @returns {asserts mode is SnapshotMode} - */ -function validateSnapshotMode (mode) { - if (!validSnapshotModes.includes(mode)) { - throw new InvalidArgumentError(`Invalid snapshot mode: ${mode}. Must be one of: ${validSnapshotModes.join(', ')}`) + return dispatch(opts, dumpHandler) + } } } -module.exports = { - createHeaderFilters, - hashId, - isUndiciHeaders, - normalizeHeaders, - isUrlExcludedFactory, - validateSnapshotMode -} +module.exports = createDumpInterceptor /***/ }), -/***/ 630: +/***/ 3640: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; - - -const { - safeHTTPMethods, - pathHasQueryOrFragment -} = __nccwpck_require__(983) -const { serializePathWithQuery } = __nccwpck_require__(983) -/** - * @param {import('../../types/dispatcher.d.ts').default.DispatchOptions} opts - */ -function makeCacheKey (opts) { - if (!opts.origin) { - throw new Error('opts.origin is undefined') - } +const RedirectHandler = __nccwpck_require__(4628) - let fullPath = opts.path || '/' +function createRedirectInterceptor ({ maxRedirections: defaultMaxRedirections } = {}) { + return (dispatch) => { + return function Intercept (opts, handler) { + const { maxRedirections = defaultMaxRedirections, ...rest } = opts - if (opts.query && !pathHasQueryOrFragment(opts.path)) { - fullPath = serializePathWithQuery(fullPath, opts.query) - } + if (maxRedirections == null || maxRedirections === 0) { + return dispatch(opts, handler) + } - return { - origin: opts.origin.toString(), - method: opts.method, - path: fullPath, - headers: opts.headers + const dispatchOpts = { ...rest } // Stop sub dispatcher from also redirecting. + const redirectHandler = new RedirectHandler(dispatch, maxRedirections, dispatchOpts, handler) + return dispatch(dispatchOpts, redirectHandler) + } } } -/** - * @param {Record} - * @returns {Record} - */ -function normalizeHeaders (opts) { - let headers - if (opts.headers == null) { - headers = {} - } else if (typeof opts.headers[Symbol.iterator] === 'function') { - headers = {} - for (const x of opts.headers) { - if (!Array.isArray(x)) { - throw new Error('opts.headers is not a valid header map') - } - const [key, val] = x - if (typeof key !== 'string' || typeof val !== 'string') { - throw new Error('opts.headers is not a valid header map') - } - headers[key.toLowerCase()] = val - } - } else if (typeof opts.headers === 'object') { - headers = {} +module.exports = createRedirectInterceptor - for (const key of Object.keys(opts.headers)) { - headers[key.toLowerCase()] = opts.headers[key] - } - } else { - throw new Error('opts.headers is not an object') - } - return headers -} +/***/ }), -/** - * @param {any} key - */ -function assertCacheKey (key) { - if (typeof key !== 'object') { - throw new TypeError(`expected key to be object, got ${typeof key}`) - } +/***/ 4732: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - for (const property of ['origin', 'method', 'path']) { - if (typeof key[property] !== 'string') { - throw new TypeError(`expected key.${property} to be string, got ${typeof key[property]}`) - } - } - if (key.headers !== undefined && typeof key.headers !== 'object') { - throw new TypeError(`expected headers to be object, got ${typeof key}`) - } -} -/** - * @param {any} value - */ -function assertCacheValue (value) { - if (typeof value !== 'object') { - throw new TypeError(`expected value to be object, got ${typeof value}`) - } +// const { parseHeaders } = require('../core/util') +const DecoratorHandler = __nccwpck_require__(169) +const { ResponseError } = __nccwpck_require__(5093) - for (const property of ['statusCode', 'cachedAt', 'staleAt', 'deleteAt']) { - if (typeof value[property] !== 'number') { - throw new TypeError(`expected value.${property} to be number, got ${typeof value[property]}`) - } - } +class ResponseErrorHandler extends DecoratorHandler { + #statusCode + #contentType + #decoder + #headers + #body - if (typeof value.statusMessage !== 'string') { - throw new TypeError(`expected value.statusMessage to be string, got ${typeof value.statusMessage}`) + constructor (_opts, { handler }) { + super(handler) } - if (value.headers != null && typeof value.headers !== 'object') { - throw new TypeError(`expected value.rawHeaders to be object, got ${typeof value.headers}`) + #checkContentType (contentType) { + return (this.#contentType ?? '').indexOf(contentType) === 0 } - if (value.vary !== undefined && typeof value.vary !== 'object') { - throw new TypeError(`expected value.vary to be object, got ${typeof value.vary}`) - } + onRequestStart (controller, context) { + this.#statusCode = 0 + this.#contentType = null + this.#decoder = null + this.#headers = null + this.#body = '' - if (value.etag !== undefined && typeof value.etag !== 'string') { - throw new TypeError(`expected value.etag to be string, got ${typeof value.etag}`) + return super.onRequestStart(controller, context) } -} - -/** - * @see https://www.rfc-editor.org/rfc/rfc9111.html#name-cache-control - * @see https://www.iana.org/assignments/http-cache-directives/http-cache-directives.xhtml - * @param {string | string[]} header - * @returns {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives} - */ -function parseCacheControlHeader (header) { - /** - * @type {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives} - */ - const output = {} + onResponseStart (controller, statusCode, headers, statusMessage) { + this.#statusCode = statusCode + this.#headers = headers + this.#contentType = headers['content-type'] - let directives - if (Array.isArray(header)) { - directives = [] + if (this.#statusCode < 400) { + return super.onResponseStart(controller, statusCode, headers, statusMessage) + } - for (const directive of header) { - directives.push(...directive.split(',')) + if (this.#checkContentType('application/json') || this.#checkContentType('text/plain')) { + this.#decoder = new TextDecoder('utf-8') } - } else { - directives = header.split(',') } - for (let i = 0; i < directives.length; i++) { - const directive = directives[i].toLowerCase() - const keyValueDelimiter = directive.indexOf('=') + onResponseData (controller, chunk) { + if (this.#statusCode < 400) { + return super.onResponseData(controller, chunk) + } - let key - let value - if (keyValueDelimiter !== -1) { - key = directive.substring(0, keyValueDelimiter).trimStart() - value = directive.substring(keyValueDelimiter + 1) - } else { - key = directive.trim() - } - - switch (key) { - case 'min-fresh': - case 'max-stale': - case 'max-age': - case 's-maxage': - case 'stale-while-revalidate': - case 'stale-if-error': { - if (value === undefined || value[0] === ' ') { - continue - } - - if ( - value.length >= 2 && - value[0] === '"' && - value[value.length - 1] === '"' - ) { - value = value.substring(1, value.length - 1) - } + this.#body += this.#decoder?.decode(chunk, { stream: true }) ?? '' + } - const parsedValue = parseInt(value, 10) - // eslint-disable-next-line no-self-compare - if (parsedValue !== parsedValue) { - continue - } + onResponseEnd (controller, trailers) { + if (this.#statusCode >= 400) { + this.#body += this.#decoder?.decode(undefined, { stream: false }) ?? '' - if (key === 'max-age' && key in output && output[key] >= parsedValue) { - continue + if (this.#checkContentType('application/json')) { + try { + this.#body = JSON.parse(this.#body) + } catch { + // Do nothing... } - - output[key] = parsedValue - - break } - case 'private': - case 'no-cache': { - if (value) { - // The private and no-cache directives can be unqualified (aka just - // `private` or `no-cache`) or qualified (w/ a value). When they're - // qualified, it's a list of headers like `no-cache=header1`, - // `no-cache="header1"`, or `no-cache="header1, header2"` - // If we're given multiple headers, the comma messes us up since - // we split the full header by commas. So, let's loop through the - // remaining parts in front of us until we find one that ends in a - // quote. We can then just splice all of the parts in between the - // starting quote and the ending quote out of the directives array - // and continue parsing like normal. - // https://www.rfc-editor.org/rfc/rfc9111.html#name-no-cache-2 - if (value[0] === '"') { - // Something like `no-cache="some-header"` OR `no-cache="some-header, another-header"`. - - // Add the first header on and cut off the leading quote - const headers = [value.substring(1)] - - let foundEndingQuote = value[value.length - 1] === '"' - if (!foundEndingQuote) { - // Something like `no-cache="some-header, another-header"` - // This can still be something invalid, e.g. `no-cache="some-header, ...` - for (let j = i + 1; j < directives.length; j++) { - const nextPart = directives[j] - const nextPartLength = nextPart.length - - headers.push(nextPart.trim()) - - if (nextPartLength !== 0 && nextPart[nextPartLength - 1] === '"') { - foundEndingQuote = true - break - } - } - } - - if (foundEndingQuote) { - let lastHeader = headers[headers.length - 1] - if (lastHeader[lastHeader.length - 1] === '"') { - lastHeader = lastHeader.substring(0, lastHeader.length - 1) - headers[headers.length - 1] = lastHeader - } - - if (key in output) { - output[key] = output[key].concat(headers) - } else { - output[key] = headers - } - } - } else { - // Something like `no-cache="some-header"` - if (key in output) { - output[key] = output[key].concat(value) - } else { - output[key] = [value] - } - } - break - } + let err + const stackTraceLimit = Error.stackTraceLimit + Error.stackTraceLimit = 0 + try { + err = new ResponseError('Response Error', this.#statusCode, { + body: this.#body, + headers: this.#headers + }) + } finally { + Error.stackTraceLimit = stackTraceLimit } - // eslint-disable-next-line no-fallthrough - case 'public': - case 'no-store': - case 'must-revalidate': - case 'proxy-revalidate': - case 'immutable': - case 'no-transform': - case 'must-understand': - case 'only-if-cached': - if (value) { - // These are qualified (something like `public=...`) when they aren't - // allowed to be, skip - continue - } - - output[key] = true - break - default: - // Ignore unknown directives as per https://www.rfc-editor.org/rfc/rfc9111.html#section-5.2.3-1 - continue - } - } - - return output -} - -/** - * @param {string | string[]} varyHeader Vary header from the server - * @param {Record} headers Request headers - * @returns {Record} - */ -function parseVaryHeader (varyHeader, headers) { - if (typeof varyHeader === 'string' && varyHeader.includes('*')) { - return headers - } - - const output = /** @type {Record} */ ({}) - - const varyingHeaders = typeof varyHeader === 'string' - ? varyHeader.split(',') - : varyHeader - - for (const header of varyingHeaders) { - const trimmedHeader = header.trim().toLowerCase() - - output[trimmedHeader] = headers[trimmedHeader] ?? null - } - - return output -} - -/** - * Note: this deviates from the spec a little. Empty etags ("", W/"") are valid, - * however, including them in cached resposnes serves little to no purpose. - * - * @see https://www.rfc-editor.org/rfc/rfc9110.html#name-etag - * - * @param {string} etag - * @returns {boolean} - */ -function isEtagUsable (etag) { - if (etag.length <= 2) { - // Shortest an etag can be is two chars (just ""). This is where we deviate - // from the spec requiring a min of 3 chars however - return false - } - - if (etag[0] === '"' && etag[etag.length - 1] === '"') { - // ETag: ""asd123"" or ETag: "W/"asd123"", kinda undefined behavior in the - // spec. Some servers will accept these while others don't. - // ETag: "asd123" - return !(etag[1] === '"' || etag.startsWith('"W/')) - } - - if (etag.startsWith('W/"') && etag[etag.length - 1] === '"') { - // ETag: W/"", also where we deviate from the spec & require a min of 3 - // chars - // ETag: for W/"", W/"asd123" - return etag.length !== 4 - } - - // Anything else - return false -} - -/** - * @param {unknown} store - * @returns {asserts store is import('../../types/cache-interceptor.d.ts').default.CacheStore} - */ -function assertCacheStore (store, name = 'CacheStore') { - if (typeof store !== 'object' || store === null) { - throw new TypeError(`expected type of ${name} to be a CacheStore, got ${store === null ? 'null' : typeof store}`) - } - for (const fn of ['get', 'createWriteStream', 'delete']) { - if (typeof store[fn] !== 'function') { - throw new TypeError(`${name} needs to have a \`${fn}()\` function`) + super.onResponseError(controller, err) + } else { + super.onResponseEnd(controller, trailers) } } -} -/** - * @param {unknown} methods - * @returns {asserts methods is import('../../types/cache-interceptor.d.ts').default.CacheMethods[]} - */ -function assertCacheMethods (methods, name = 'CacheMethods') { - if (!Array.isArray(methods)) { - throw new TypeError(`expected type of ${name} needs to be an array, got ${methods === null ? 'null' : typeof methods}`) - } - if (methods.length === 0) { - throw new TypeError(`${name} needs to have at least one method`) - } - - for (const method of methods) { - if (!safeHTTPMethods.includes(method)) { - throw new TypeError(`element of ${name}-array needs to be one of following values: ${safeHTTPMethods.join(', ')}, got ${method}`) - } + onResponseError (controller, err) { + super.onResponseError(controller, err) } } -/** - * Creates a string key for request deduplication purposes. - * This key is used to identify in-flight requests that can be shared. - * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} cacheKey - * @param {Set} [excludeHeaders] Set of lowercase header names to exclude from the key - * @returns {string} - */ -function makeDeduplicationKey (cacheKey, excludeHeaders) { - // Create a deterministic string key from the cache key - // Include origin, method, path, and sorted headers - let key = `${cacheKey.origin}:${cacheKey.method}:${cacheKey.path}` - - if (cacheKey.headers) { - const sortedHeaders = Object.keys(cacheKey.headers).sort() - for (const header of sortedHeaders) { - // Skip excluded headers - if (excludeHeaders?.has(header.toLowerCase())) { - continue - } - const value = cacheKey.headers[header] - key += `:${header}=${Array.isArray(value) ? value.join(',') : value}` +module.exports = () => { + return (dispatch) => { + return function Intercept (opts, handler) { + return dispatch(opts, new ResponseErrorHandler(opts, { handler })) } } - - return key -} - -module.exports = { - makeCacheKey, - normalizeHeaders, - assertCacheKey, - assertCacheValue, - parseCacheControlHeader, - parseVaryHeader, - isEtagUsable, - assertCacheMethods, - assertCacheStore, - makeDeduplicationKey } /***/ }), -/***/ 6810: -/***/ ((module) => { - -"use strict"; - - -/** - * @see https://www.rfc-editor.org/rfc/rfc9110.html#name-date-time-formats - * - * @param {string} date - * @returns {Date | undefined} - */ -function parseHttpDate (date) { - // Sun, 06 Nov 1994 08:49:37 GMT ; IMF-fixdate - // Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format - // Sunday, 06-Nov-94 08:49:37 GMT ; obsolete RFC 850 format - - switch (date[3]) { - case ',': return parseImfDate(date) - case ' ': return parseAscTimeDate(date) - default: return parseRfc850Date(date) - } -} - -/** - * @see https://httpwg.org/specs/rfc9110.html#preferred.date.format - * - * @param {string} date - * @returns {Date | undefined} - */ -function parseImfDate (date) { - if ( - date.length !== 29 || - date[4] !== ' ' || - date[7] !== ' ' || - date[11] !== ' ' || - date[16] !== ' ' || - date[19] !== ':' || - date[22] !== ':' || - date[25] !== ' ' || - date[26] !== 'G' || - date[27] !== 'M' || - date[28] !== 'T' - ) { - return undefined - } +/***/ 9128: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - let weekday = -1 - if (date[0] === 'S' && date[1] === 'u' && date[2] === 'n') { // Sunday - weekday = 0 - } else if (date[0] === 'M' && date[1] === 'o' && date[2] === 'n') { // Monday - weekday = 1 - } else if (date[0] === 'T' && date[1] === 'u' && date[2] === 'e') { // Tuesday - weekday = 2 - } else if (date[0] === 'W' && date[1] === 'e' && date[2] === 'd') { // Wednesday - weekday = 3 - } else if (date[0] === 'T' && date[1] === 'h' && date[2] === 'u') { // Thursday - weekday = 4 - } else if (date[0] === 'F' && date[1] === 'r' && date[2] === 'i') { // Friday - weekday = 5 - } else if (date[0] === 'S' && date[1] === 'a' && date[2] === 't') { // Saturday - weekday = 6 - } else { - return undefined // Not a valid day of the week - } - let day = 0 - if (date[5] === '0') { - // Single digit day, e.g. "Sun Nov 6 08:49:37 1994" - const code = date.charCodeAt(6) - if (code < 49 || code > 57) { - return undefined // Not a digit - } - day = code - 48 // Convert ASCII code to number - } else { - const code1 = date.charCodeAt(5) - if (code1 < 49 || code1 > 51) { - return undefined // Not a digit between 1 and 3 - } - const code2 = date.charCodeAt(6) - if (code2 < 48 || code2 > 57) { - return undefined // Not a digit - } - day = (code1 - 48) * 10 + (code2 - 48) // Convert ASCII codes to number - } +const RetryHandler = __nccwpck_require__(1557) - let monthIdx = -1 - if ( - (date[8] === 'J' && date[9] === 'a' && date[10] === 'n') - ) { - monthIdx = 0 // Jan - } else if ( - (date[8] === 'F' && date[9] === 'e' && date[10] === 'b') - ) { - monthIdx = 1 // Feb - } else if ( - (date[8] === 'M' && date[9] === 'a') - ) { - if (date[10] === 'r') { - monthIdx = 2 // Mar - } else if (date[10] === 'y') { - monthIdx = 4 // May - } else { - return undefined // Invalid month - } - } else if ( - (date[8] === 'J') - ) { - if (date[9] === 'a' && date[10] === 'n') { - monthIdx = 0 // Jan - } else if (date[9] === 'u') { - if (date[10] === 'n') { - monthIdx = 5 // Jun - } else if (date[10] === 'l') { - monthIdx = 6 // Jul - } else { - return undefined // Invalid month - } - } else { - return undefined // Invalid month - } - } else if ( - (date[8] === 'A') - ) { - if (date[9] === 'p' && date[10] === 'r') { - monthIdx = 3 // Apr - } else if (date[9] === 'u' && date[10] === 'g') { - monthIdx = 7 // Aug - } else { - return undefined // Invalid month +module.exports = globalOpts => { + return dispatch => { + return function retryInterceptor (opts, handler) { + return dispatch( + opts, + new RetryHandler( + { ...opts, retryOptions: { ...globalOpts, ...opts.retryOptions } }, + { + handler, + dispatch + } + ) + ) } - } else if ( - (date[8] === 'S' && date[9] === 'e' && date[10] === 'p') - ) { - monthIdx = 8 // Sep - } else if ( - (date[8] === 'O' && date[9] === 'c' && date[10] === 't') - ) { - monthIdx = 9 // Oct - } else if ( - (date[8] === 'N' && date[9] === 'o' && date[10] === 'v') - ) { - monthIdx = 10 // Nov - } else if ( - (date[8] === 'D' && date[9] === 'e' && date[10] === 'c') - ) { - monthIdx = 11 // Dec - } else { - // Not a valid month - return undefined } +} - const yearDigit1 = date.charCodeAt(12) - if (yearDigit1 < 48 || yearDigit1 > 57) { - return undefined // Not a digit - } - const yearDigit2 = date.charCodeAt(13) - if (yearDigit2 < 48 || yearDigit2 > 57) { - return undefined // Not a digit - } - const yearDigit3 = date.charCodeAt(14) - if (yearDigit3 < 48 || yearDigit3 > 57) { - return undefined // Not a digit - } - const yearDigit4 = date.charCodeAt(15) - if (yearDigit4 < 48 || yearDigit4 > 57) { - return undefined // Not a digit - } - const year = (yearDigit1 - 48) * 1000 + (yearDigit2 - 48) * 100 + (yearDigit3 - 48) * 10 + (yearDigit4 - 48) - let hour = 0 - if (date[17] === '0') { - const code = date.charCodeAt(18) - if (code < 48 || code > 57) { - return undefined // Not a digit - } - hour = code - 48 // Convert ASCII code to number - } else { - const code1 = date.charCodeAt(17) - if (code1 < 48 || code1 > 50) { - return undefined // Not a digit between 0 and 2 - } - const code2 = date.charCodeAt(18) - if (code2 < 48 || code2 > 57) { - return undefined // Not a digit - } - if (code1 === 50 && code2 > 51) { - return undefined // Hour cannot be greater than 23 - } - hour = (code1 - 48) * 10 + (code2 - 48) // Convert ASCII codes to number - } +/***/ }), - let minute = 0 - if (date[20] === '0') { - const code = date.charCodeAt(21) - if (code < 48 || code > 57) { - return undefined // Not a digit - } - minute = code - 48 // Convert ASCII code to number - } else { - const code1 = date.charCodeAt(20) - if (code1 < 48 || code1 > 53) { - return undefined // Not a digit between 0 and 5 - } - const code2 = date.charCodeAt(21) - if (code2 < 48 || code2 > 57) { - return undefined // Not a digit - } - minute = (code1 - 48) * 10 + (code2 - 48) // Convert ASCII codes to number - } +/***/ 1478: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - let second = 0 - if (date[23] === '0') { - const code = date.charCodeAt(24) - if (code < 48 || code > 57) { - return undefined // Not a digit - } - second = code - 48 // Convert ASCII code to number - } else { - const code1 = date.charCodeAt(23) - if (code1 < 48 || code1 > 53) { - return undefined // Not a digit between 0 and 5 - } - const code2 = date.charCodeAt(24) - if (code2 < 48 || code2 > 57) { - return undefined // Not a digit - } - second = (code1 - 48) * 10 + (code2 - 48) // Convert ASCII codes to number - } - const result = new Date(Date.UTC(year, monthIdx, day, hour, minute, second)) - return result.getUTCDay() === weekday ? result : undefined +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.SPECIAL_HEADERS = exports.MINOR = exports.MAJOR = exports.HTAB_SP_VCHAR_OBS_TEXT = exports.QUOTED_STRING = exports.CONNECTION_TOKEN_CHARS = exports.HEADER_CHARS = exports.TOKEN = exports.HEX = exports.URL_CHAR = exports.USERINFO_CHARS = exports.MARK = exports.ALPHANUM = exports.NUM = exports.HEX_MAP = exports.NUM_MAP = exports.ALPHA = exports.STATUSES_HTTP = exports.H_METHOD_MAP = exports.METHOD_MAP = exports.METHODS_RTSP = exports.METHODS_ICE = exports.METHODS_HTTP = exports.HEADER_STATE = exports.FINISH = exports.STATUSES = exports.METHODS = exports.LENIENT_FLAGS = exports.FLAGS = exports.TYPE = exports.ERROR = void 0; +const utils_1 = __nccwpck_require__(9054); +// Emums +exports.ERROR = { + OK: 0, + INTERNAL: 1, + STRICT: 2, + CR_EXPECTED: 25, + LF_EXPECTED: 3, + UNEXPECTED_CONTENT_LENGTH: 4, + UNEXPECTED_SPACE: 30, + CLOSED_CONNECTION: 5, + INVALID_METHOD: 6, + INVALID_URL: 7, + INVALID_CONSTANT: 8, + INVALID_VERSION: 9, + INVALID_HEADER_TOKEN: 10, + INVALID_CONTENT_LENGTH: 11, + INVALID_CHUNK_SIZE: 12, + INVALID_STATUS: 13, + INVALID_EOF_STATE: 14, + INVALID_TRANSFER_ENCODING: 15, + CB_MESSAGE_BEGIN: 16, + CB_HEADERS_COMPLETE: 17, + CB_MESSAGE_COMPLETE: 18, + CB_CHUNK_HEADER: 19, + CB_CHUNK_COMPLETE: 20, + PAUSED: 21, + PAUSED_UPGRADE: 22, + PAUSED_H2_UPGRADE: 23, + USER: 24, + CB_URL_COMPLETE: 26, + CB_STATUS_COMPLETE: 27, + CB_METHOD_COMPLETE: 32, + CB_VERSION_COMPLETE: 33, + CB_HEADER_FIELD_COMPLETE: 28, + CB_HEADER_VALUE_COMPLETE: 29, + CB_CHUNK_EXTENSION_NAME_COMPLETE: 34, + CB_CHUNK_EXTENSION_VALUE_COMPLETE: 35, + CB_RESET: 31, + CB_PROTOCOL_COMPLETE: 38, +}; +exports.TYPE = { + BOTH: 0, // default + REQUEST: 1, + RESPONSE: 2, +}; +exports.FLAGS = { + CONNECTION_KEEP_ALIVE: 1 << 0, + CONNECTION_CLOSE: 1 << 1, + CONNECTION_UPGRADE: 1 << 2, + CHUNKED: 1 << 3, + UPGRADE: 1 << 4, + CONTENT_LENGTH: 1 << 5, + SKIPBODY: 1 << 6, + TRAILING: 1 << 7, + // 1 << 8 is unused + TRANSFER_ENCODING: 1 << 9, +}; +exports.LENIENT_FLAGS = { + HEADERS: 1 << 0, + CHUNKED_LENGTH: 1 << 1, + KEEP_ALIVE: 1 << 2, + TRANSFER_ENCODING: 1 << 3, + VERSION: 1 << 4, + DATA_AFTER_CLOSE: 1 << 5, + OPTIONAL_LF_AFTER_CR: 1 << 6, + OPTIONAL_CRLF_AFTER_CHUNK: 1 << 7, + OPTIONAL_CR_BEFORE_LF: 1 << 8, + SPACES_AFTER_CHUNK_SIZE: 1 << 9, +}; +exports.METHODS = { + 'DELETE': 0, + 'GET': 1, + 'HEAD': 2, + 'POST': 3, + 'PUT': 4, + /* pathological */ + 'CONNECT': 5, + 'OPTIONS': 6, + 'TRACE': 7, + /* WebDAV */ + 'COPY': 8, + 'LOCK': 9, + 'MKCOL': 10, + 'MOVE': 11, + 'PROPFIND': 12, + 'PROPPATCH': 13, + 'SEARCH': 14, + 'UNLOCK': 15, + 'BIND': 16, + 'REBIND': 17, + 'UNBIND': 18, + 'ACL': 19, + /* subversion */ + 'REPORT': 20, + 'MKACTIVITY': 21, + 'CHECKOUT': 22, + 'MERGE': 23, + /* upnp */ + 'M-SEARCH': 24, + 'NOTIFY': 25, + 'SUBSCRIBE': 26, + 'UNSUBSCRIBE': 27, + /* RFC-5789 */ + 'PATCH': 28, + 'PURGE': 29, + /* CalDAV */ + 'MKCALENDAR': 30, + /* RFC-2068, section 19.6.1.2 */ + 'LINK': 31, + 'UNLINK': 32, + /* icecast */ + 'SOURCE': 33, + /* RFC-7540, section 11.6 */ + 'PRI': 34, + /* RFC-2326 RTSP */ + 'DESCRIBE': 35, + 'ANNOUNCE': 36, + 'SETUP': 37, + 'PLAY': 38, + 'PAUSE': 39, + 'TEARDOWN': 40, + 'GET_PARAMETER': 41, + 'SET_PARAMETER': 42, + 'REDIRECT': 43, + 'RECORD': 44, + /* RAOP */ + 'FLUSH': 45, + /* DRAFT https://www.ietf.org/archive/id/draft-ietf-httpbis-safe-method-w-body-02.html */ + 'QUERY': 46, +}; +exports.STATUSES = { + CONTINUE: 100, + SWITCHING_PROTOCOLS: 101, + PROCESSING: 102, + EARLY_HINTS: 103, + RESPONSE_IS_STALE: 110, // Unofficial + REVALIDATION_FAILED: 111, // Unofficial + DISCONNECTED_OPERATION: 112, // Unofficial + HEURISTIC_EXPIRATION: 113, // Unofficial + MISCELLANEOUS_WARNING: 199, // Unofficial + OK: 200, + CREATED: 201, + ACCEPTED: 202, + NON_AUTHORITATIVE_INFORMATION: 203, + NO_CONTENT: 204, + RESET_CONTENT: 205, + PARTIAL_CONTENT: 206, + MULTI_STATUS: 207, + ALREADY_REPORTED: 208, + TRANSFORMATION_APPLIED: 214, // Unofficial + IM_USED: 226, + MISCELLANEOUS_PERSISTENT_WARNING: 299, // Unofficial + MULTIPLE_CHOICES: 300, + MOVED_PERMANENTLY: 301, + FOUND: 302, + SEE_OTHER: 303, + NOT_MODIFIED: 304, + USE_PROXY: 305, + SWITCH_PROXY: 306, // No longer used + TEMPORARY_REDIRECT: 307, + PERMANENT_REDIRECT: 308, + BAD_REQUEST: 400, + UNAUTHORIZED: 401, + PAYMENT_REQUIRED: 402, + FORBIDDEN: 403, + NOT_FOUND: 404, + METHOD_NOT_ALLOWED: 405, + NOT_ACCEPTABLE: 406, + PROXY_AUTHENTICATION_REQUIRED: 407, + REQUEST_TIMEOUT: 408, + CONFLICT: 409, + GONE: 410, + LENGTH_REQUIRED: 411, + PRECONDITION_FAILED: 412, + PAYLOAD_TOO_LARGE: 413, + URI_TOO_LONG: 414, + UNSUPPORTED_MEDIA_TYPE: 415, + RANGE_NOT_SATISFIABLE: 416, + EXPECTATION_FAILED: 417, + IM_A_TEAPOT: 418, + PAGE_EXPIRED: 419, // Unofficial + ENHANCE_YOUR_CALM: 420, // Unofficial + MISDIRECTED_REQUEST: 421, + UNPROCESSABLE_ENTITY: 422, + LOCKED: 423, + FAILED_DEPENDENCY: 424, + TOO_EARLY: 425, + UPGRADE_REQUIRED: 426, + PRECONDITION_REQUIRED: 428, + TOO_MANY_REQUESTS: 429, + REQUEST_HEADER_FIELDS_TOO_LARGE_UNOFFICIAL: 430, // Unofficial + REQUEST_HEADER_FIELDS_TOO_LARGE: 431, + LOGIN_TIMEOUT: 440, // Unofficial + NO_RESPONSE: 444, // Unofficial + RETRY_WITH: 449, // Unofficial + BLOCKED_BY_PARENTAL_CONTROL: 450, // Unofficial + UNAVAILABLE_FOR_LEGAL_REASONS: 451, + CLIENT_CLOSED_LOAD_BALANCED_REQUEST: 460, // Unofficial + INVALID_X_FORWARDED_FOR: 463, // Unofficial + REQUEST_HEADER_TOO_LARGE: 494, // Unofficial + SSL_CERTIFICATE_ERROR: 495, // Unofficial + SSL_CERTIFICATE_REQUIRED: 496, // Unofficial + HTTP_REQUEST_SENT_TO_HTTPS_PORT: 497, // Unofficial + INVALID_TOKEN: 498, // Unofficial + CLIENT_CLOSED_REQUEST: 499, // Unofficial + INTERNAL_SERVER_ERROR: 500, + NOT_IMPLEMENTED: 501, + BAD_GATEWAY: 502, + SERVICE_UNAVAILABLE: 503, + GATEWAY_TIMEOUT: 504, + HTTP_VERSION_NOT_SUPPORTED: 505, + VARIANT_ALSO_NEGOTIATES: 506, + INSUFFICIENT_STORAGE: 507, + LOOP_DETECTED: 508, + BANDWIDTH_LIMIT_EXCEEDED: 509, + NOT_EXTENDED: 510, + NETWORK_AUTHENTICATION_REQUIRED: 511, + WEB_SERVER_UNKNOWN_ERROR: 520, // Unofficial + WEB_SERVER_IS_DOWN: 521, // Unofficial + CONNECTION_TIMEOUT: 522, // Unofficial + ORIGIN_IS_UNREACHABLE: 523, // Unofficial + TIMEOUT_OCCURED: 524, // Unofficial + SSL_HANDSHAKE_FAILED: 525, // Unofficial + INVALID_SSL_CERTIFICATE: 526, // Unofficial + RAILGUN_ERROR: 527, // Unofficial + SITE_IS_OVERLOADED: 529, // Unofficial + SITE_IS_FROZEN: 530, // Unofficial + IDENTITY_PROVIDER_AUTHENTICATION_ERROR: 561, // Unofficial + NETWORK_READ_TIMEOUT: 598, // Unofficial + NETWORK_CONNECT_TIMEOUT: 599, // Unofficial +}; +exports.FINISH = { + SAFE: 0, + SAFE_WITH_CB: 1, + UNSAFE: 2, +}; +exports.HEADER_STATE = { + GENERAL: 0, + CONNECTION: 1, + CONTENT_LENGTH: 2, + TRANSFER_ENCODING: 3, + UPGRADE: 4, + CONNECTION_KEEP_ALIVE: 5, + CONNECTION_CLOSE: 6, + CONNECTION_UPGRADE: 7, + TRANSFER_ENCODING_CHUNKED: 8, +}; +// C headers +exports.METHODS_HTTP = [ + exports.METHODS.DELETE, + exports.METHODS.GET, + exports.METHODS.HEAD, + exports.METHODS.POST, + exports.METHODS.PUT, + exports.METHODS.CONNECT, + exports.METHODS.OPTIONS, + exports.METHODS.TRACE, + exports.METHODS.COPY, + exports.METHODS.LOCK, + exports.METHODS.MKCOL, + exports.METHODS.MOVE, + exports.METHODS.PROPFIND, + exports.METHODS.PROPPATCH, + exports.METHODS.SEARCH, + exports.METHODS.UNLOCK, + exports.METHODS.BIND, + exports.METHODS.REBIND, + exports.METHODS.UNBIND, + exports.METHODS.ACL, + exports.METHODS.REPORT, + exports.METHODS.MKACTIVITY, + exports.METHODS.CHECKOUT, + exports.METHODS.MERGE, + exports.METHODS['M-SEARCH'], + exports.METHODS.NOTIFY, + exports.METHODS.SUBSCRIBE, + exports.METHODS.UNSUBSCRIBE, + exports.METHODS.PATCH, + exports.METHODS.PURGE, + exports.METHODS.MKCALENDAR, + exports.METHODS.LINK, + exports.METHODS.UNLINK, + exports.METHODS.PRI, + // TODO(indutny): should we allow it with HTTP? + exports.METHODS.SOURCE, + exports.METHODS.QUERY, +]; +exports.METHODS_ICE = [ + exports.METHODS.SOURCE, +]; +exports.METHODS_RTSP = [ + exports.METHODS.OPTIONS, + exports.METHODS.DESCRIBE, + exports.METHODS.ANNOUNCE, + exports.METHODS.SETUP, + exports.METHODS.PLAY, + exports.METHODS.PAUSE, + exports.METHODS.TEARDOWN, + exports.METHODS.GET_PARAMETER, + exports.METHODS.SET_PARAMETER, + exports.METHODS.REDIRECT, + exports.METHODS.RECORD, + exports.METHODS.FLUSH, + // For AirPlay + exports.METHODS.GET, + exports.METHODS.POST, +]; +exports.METHOD_MAP = (0, utils_1.enumToMap)(exports.METHODS); +exports.H_METHOD_MAP = Object.fromEntries(Object.entries(exports.METHODS).filter(([k]) => k.startsWith('H'))); +exports.STATUSES_HTTP = [ + exports.STATUSES.CONTINUE, + exports.STATUSES.SWITCHING_PROTOCOLS, + exports.STATUSES.PROCESSING, + exports.STATUSES.EARLY_HINTS, + exports.STATUSES.RESPONSE_IS_STALE, + exports.STATUSES.REVALIDATION_FAILED, + exports.STATUSES.DISCONNECTED_OPERATION, + exports.STATUSES.HEURISTIC_EXPIRATION, + exports.STATUSES.MISCELLANEOUS_WARNING, + exports.STATUSES.OK, + exports.STATUSES.CREATED, + exports.STATUSES.ACCEPTED, + exports.STATUSES.NON_AUTHORITATIVE_INFORMATION, + exports.STATUSES.NO_CONTENT, + exports.STATUSES.RESET_CONTENT, + exports.STATUSES.PARTIAL_CONTENT, + exports.STATUSES.MULTI_STATUS, + exports.STATUSES.ALREADY_REPORTED, + exports.STATUSES.TRANSFORMATION_APPLIED, + exports.STATUSES.IM_USED, + exports.STATUSES.MISCELLANEOUS_PERSISTENT_WARNING, + exports.STATUSES.MULTIPLE_CHOICES, + exports.STATUSES.MOVED_PERMANENTLY, + exports.STATUSES.FOUND, + exports.STATUSES.SEE_OTHER, + exports.STATUSES.NOT_MODIFIED, + exports.STATUSES.USE_PROXY, + exports.STATUSES.SWITCH_PROXY, + exports.STATUSES.TEMPORARY_REDIRECT, + exports.STATUSES.PERMANENT_REDIRECT, + exports.STATUSES.BAD_REQUEST, + exports.STATUSES.UNAUTHORIZED, + exports.STATUSES.PAYMENT_REQUIRED, + exports.STATUSES.FORBIDDEN, + exports.STATUSES.NOT_FOUND, + exports.STATUSES.METHOD_NOT_ALLOWED, + exports.STATUSES.NOT_ACCEPTABLE, + exports.STATUSES.PROXY_AUTHENTICATION_REQUIRED, + exports.STATUSES.REQUEST_TIMEOUT, + exports.STATUSES.CONFLICT, + exports.STATUSES.GONE, + exports.STATUSES.LENGTH_REQUIRED, + exports.STATUSES.PRECONDITION_FAILED, + exports.STATUSES.PAYLOAD_TOO_LARGE, + exports.STATUSES.URI_TOO_LONG, + exports.STATUSES.UNSUPPORTED_MEDIA_TYPE, + exports.STATUSES.RANGE_NOT_SATISFIABLE, + exports.STATUSES.EXPECTATION_FAILED, + exports.STATUSES.IM_A_TEAPOT, + exports.STATUSES.PAGE_EXPIRED, + exports.STATUSES.ENHANCE_YOUR_CALM, + exports.STATUSES.MISDIRECTED_REQUEST, + exports.STATUSES.UNPROCESSABLE_ENTITY, + exports.STATUSES.LOCKED, + exports.STATUSES.FAILED_DEPENDENCY, + exports.STATUSES.TOO_EARLY, + exports.STATUSES.UPGRADE_REQUIRED, + exports.STATUSES.PRECONDITION_REQUIRED, + exports.STATUSES.TOO_MANY_REQUESTS, + exports.STATUSES.REQUEST_HEADER_FIELDS_TOO_LARGE_UNOFFICIAL, + exports.STATUSES.REQUEST_HEADER_FIELDS_TOO_LARGE, + exports.STATUSES.LOGIN_TIMEOUT, + exports.STATUSES.NO_RESPONSE, + exports.STATUSES.RETRY_WITH, + exports.STATUSES.BLOCKED_BY_PARENTAL_CONTROL, + exports.STATUSES.UNAVAILABLE_FOR_LEGAL_REASONS, + exports.STATUSES.CLIENT_CLOSED_LOAD_BALANCED_REQUEST, + exports.STATUSES.INVALID_X_FORWARDED_FOR, + exports.STATUSES.REQUEST_HEADER_TOO_LARGE, + exports.STATUSES.SSL_CERTIFICATE_ERROR, + exports.STATUSES.SSL_CERTIFICATE_REQUIRED, + exports.STATUSES.HTTP_REQUEST_SENT_TO_HTTPS_PORT, + exports.STATUSES.INVALID_TOKEN, + exports.STATUSES.CLIENT_CLOSED_REQUEST, + exports.STATUSES.INTERNAL_SERVER_ERROR, + exports.STATUSES.NOT_IMPLEMENTED, + exports.STATUSES.BAD_GATEWAY, + exports.STATUSES.SERVICE_UNAVAILABLE, + exports.STATUSES.GATEWAY_TIMEOUT, + exports.STATUSES.HTTP_VERSION_NOT_SUPPORTED, + exports.STATUSES.VARIANT_ALSO_NEGOTIATES, + exports.STATUSES.INSUFFICIENT_STORAGE, + exports.STATUSES.LOOP_DETECTED, + exports.STATUSES.BANDWIDTH_LIMIT_EXCEEDED, + exports.STATUSES.NOT_EXTENDED, + exports.STATUSES.NETWORK_AUTHENTICATION_REQUIRED, + exports.STATUSES.WEB_SERVER_UNKNOWN_ERROR, + exports.STATUSES.WEB_SERVER_IS_DOWN, + exports.STATUSES.CONNECTION_TIMEOUT, + exports.STATUSES.ORIGIN_IS_UNREACHABLE, + exports.STATUSES.TIMEOUT_OCCURED, + exports.STATUSES.SSL_HANDSHAKE_FAILED, + exports.STATUSES.INVALID_SSL_CERTIFICATE, + exports.STATUSES.RAILGUN_ERROR, + exports.STATUSES.SITE_IS_OVERLOADED, + exports.STATUSES.SITE_IS_FROZEN, + exports.STATUSES.IDENTITY_PROVIDER_AUTHENTICATION_ERROR, + exports.STATUSES.NETWORK_READ_TIMEOUT, + exports.STATUSES.NETWORK_CONNECT_TIMEOUT, +]; +exports.ALPHA = []; +for (let i = 'A'.charCodeAt(0); i <= 'Z'.charCodeAt(0); i++) { + // Upper case + exports.ALPHA.push(String.fromCharCode(i)); + // Lower case + exports.ALPHA.push(String.fromCharCode(i + 0x20)); } - -/** - * @see https://httpwg.org/specs/rfc9110.html#obsolete.date.formats - * - * @param {string} date - * @returns {Date | undefined} +exports.NUM_MAP = { + 0: 0, 1: 1, 2: 2, 3: 3, 4: 4, + 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, +}; +exports.HEX_MAP = { + 0: 0, 1: 1, 2: 2, 3: 3, 4: 4, + 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, + A: 0XA, B: 0XB, C: 0XC, D: 0XD, E: 0XE, F: 0XF, + a: 0xa, b: 0xb, c: 0xc, d: 0xd, e: 0xe, f: 0xf, +}; +exports.NUM = [ + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', +]; +exports.ALPHANUM = exports.ALPHA.concat(exports.NUM); +exports.MARK = ['-', '_', '.', '!', '~', '*', '\'', '(', ')']; +exports.USERINFO_CHARS = exports.ALPHANUM + .concat(exports.MARK) + .concat(['%', ';', ':', '&', '=', '+', '$', ',']); +// TODO(indutny): use RFC +exports.URL_CHAR = [ + '!', '"', '$', '%', '&', '\'', + '(', ')', '*', '+', ',', '-', '.', '/', + ':', ';', '<', '=', '>', + '@', '[', '\\', ']', '^', '_', + '`', + '{', '|', '}', '~', +].concat(exports.ALPHANUM); +exports.HEX = exports.NUM.concat(['a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F']); +/* Tokens as defined by rfc 2616. Also lowercases them. + * token = 1* + * separators = "(" | ")" | "<" | ">" | "@" + * | "," | ";" | ":" | "\" | <"> + * | "/" | "[" | "]" | "?" | "=" + * | "{" | "}" | SP | HT */ -function parseAscTimeDate (date) { - // This is assumed to be in UTC - - if ( - date.length !== 24 || - date[7] !== ' ' || - date[10] !== ' ' || - date[19] !== ' ' - ) { - return undefined - } - - let weekday = -1 - if (date[0] === 'S' && date[1] === 'u' && date[2] === 'n') { // Sunday - weekday = 0 - } else if (date[0] === 'M' && date[1] === 'o' && date[2] === 'n') { // Monday - weekday = 1 - } else if (date[0] === 'T' && date[1] === 'u' && date[2] === 'e') { // Tuesday - weekday = 2 - } else if (date[0] === 'W' && date[1] === 'e' && date[2] === 'd') { // Wednesday - weekday = 3 - } else if (date[0] === 'T' && date[1] === 'h' && date[2] === 'u') { // Thursday - weekday = 4 - } else if (date[0] === 'F' && date[1] === 'r' && date[2] === 'i') { // Friday - weekday = 5 - } else if (date[0] === 'S' && date[1] === 'a' && date[2] === 't') { // Saturday - weekday = 6 - } else { - return undefined // Not a valid day of the week - } - - let monthIdx = -1 - if ( - (date[4] === 'J' && date[5] === 'a' && date[6] === 'n') - ) { - monthIdx = 0 // Jan - } else if ( - (date[4] === 'F' && date[5] === 'e' && date[6] === 'b') - ) { - monthIdx = 1 // Feb - } else if ( - (date[4] === 'M' && date[5] === 'a') - ) { - if (date[6] === 'r') { - monthIdx = 2 // Mar - } else if (date[6] === 'y') { - monthIdx = 4 // May - } else { - return undefined // Invalid month - } - } else if ( - (date[4] === 'J') - ) { - if (date[5] === 'a' && date[6] === 'n') { - monthIdx = 0 // Jan - } else if (date[5] === 'u') { - if (date[6] === 'n') { - monthIdx = 5 // Jun - } else if (date[6] === 'l') { - monthIdx = 6 // Jul - } else { - return undefined // Invalid month - } - } else { - return undefined // Invalid month - } - } else if ( - (date[4] === 'A') - ) { - if (date[5] === 'p' && date[6] === 'r') { - monthIdx = 3 // Apr - } else if (date[5] === 'u' && date[6] === 'g') { - monthIdx = 7 // Aug - } else { - return undefined // Invalid month - } - } else if ( - (date[4] === 'S' && date[5] === 'e' && date[6] === 'p') - ) { - monthIdx = 8 // Sep - } else if ( - (date[4] === 'O' && date[5] === 'c' && date[6] === 't') - ) { - monthIdx = 9 // Oct - } else if ( - (date[4] === 'N' && date[5] === 'o' && date[6] === 'v') - ) { - monthIdx = 10 // Nov - } else if ( - (date[4] === 'D' && date[5] === 'e' && date[6] === 'c') - ) { - monthIdx = 11 // Dec - } else { - // Not a valid month - return undefined - } - - let day = 0 - if (date[8] === ' ') { - // Single digit day, e.g. "Sun Nov 6 08:49:37 1994" - const code = date.charCodeAt(9) - if (code < 49 || code > 57) { - return undefined // Not a digit - } - day = code - 48 // Convert ASCII code to number - } else { - const code1 = date.charCodeAt(8) - if (code1 < 49 || code1 > 51) { - return undefined // Not a digit between 1 and 3 +exports.TOKEN = [ + '!', '#', '$', '%', '&', '\'', + '*', '+', '-', '.', + '^', '_', '`', + '|', '~', +].concat(exports.ALPHANUM); +/* + * Verify that a char is a valid visible (printable) US-ASCII + * character or %x80-FF + */ +exports.HEADER_CHARS = ['\t']; +for (let i = 32; i <= 255; i++) { + if (i !== 127) { + exports.HEADER_CHARS.push(i); } - const code2 = date.charCodeAt(9) - if (code2 < 48 || code2 > 57) { - return undefined // Not a digit +} +// ',' = \x44 +exports.CONNECTION_TOKEN_CHARS = exports.HEADER_CHARS.filter((c) => c !== 44); +exports.QUOTED_STRING = ['\t', ' ']; +for (let i = 0x21; i <= 0xff; i++) { + if (i !== 0x22 && i !== 0x5c) { // All characters in ASCII except \ and " + exports.QUOTED_STRING.push(i); } - day = (code1 - 48) * 10 + (code2 - 48) // Convert ASCII codes to number - } +} +exports.HTAB_SP_VCHAR_OBS_TEXT = ['\t', ' ']; +// VCHAR: https://tools.ietf.org/html/rfc5234#appendix-B.1 +for (let i = 0x21; i <= 0x7E; i++) { + exports.HTAB_SP_VCHAR_OBS_TEXT.push(i); +} +// OBS_TEXT: https://datatracker.ietf.org/doc/html/rfc9110#name-collected-abnf +for (let i = 0x80; i <= 0xff; i++) { + exports.HTAB_SP_VCHAR_OBS_TEXT.push(i); +} +exports.MAJOR = exports.NUM_MAP; +exports.MINOR = exports.MAJOR; +exports.SPECIAL_HEADERS = { + 'connection': exports.HEADER_STATE.CONNECTION, + 'content-length': exports.HEADER_STATE.CONTENT_LENGTH, + 'proxy-connection': exports.HEADER_STATE.CONNECTION, + 'transfer-encoding': exports.HEADER_STATE.TRANSFER_ENCODING, + 'upgrade': exports.HEADER_STATE.UPGRADE, +}; +exports["default"] = { + ERROR: exports.ERROR, + TYPE: exports.TYPE, + FLAGS: exports.FLAGS, + LENIENT_FLAGS: exports.LENIENT_FLAGS, + METHODS: exports.METHODS, + STATUSES: exports.STATUSES, + FINISH: exports.FINISH, + HEADER_STATE: exports.HEADER_STATE, + ALPHA: exports.ALPHA, + NUM_MAP: exports.NUM_MAP, + HEX_MAP: exports.HEX_MAP, + NUM: exports.NUM, + ALPHANUM: exports.ALPHANUM, + MARK: exports.MARK, + USERINFO_CHARS: exports.USERINFO_CHARS, + URL_CHAR: exports.URL_CHAR, + HEX: exports.HEX, + TOKEN: exports.TOKEN, + HEADER_CHARS: exports.HEADER_CHARS, + CONNECTION_TOKEN_CHARS: exports.CONNECTION_TOKEN_CHARS, + QUOTED_STRING: exports.QUOTED_STRING, + HTAB_SP_VCHAR_OBS_TEXT: exports.HTAB_SP_VCHAR_OBS_TEXT, + MAJOR: exports.MAJOR, + MINOR: exports.MINOR, + SPECIAL_HEADERS: exports.SPECIAL_HEADERS, + METHODS_HTTP: exports.METHODS_HTTP, + METHODS_ICE: exports.METHODS_ICE, + METHODS_RTSP: exports.METHODS_RTSP, + METHOD_MAP: exports.METHOD_MAP, + H_METHOD_MAP: exports.H_METHOD_MAP, + STATUSES_HTTP: exports.STATUSES_HTTP, +}; - let hour = 0 - if (date[11] === '0') { - const code = date.charCodeAt(12) - if (code < 48 || code > 57) { - return undefined // Not a digit - } - hour = code - 48 // Convert ASCII code to number - } else { - const code1 = date.charCodeAt(11) - if (code1 < 48 || code1 > 50) { - return undefined // Not a digit between 0 and 2 - } - const code2 = date.charCodeAt(12) - if (code2 < 48 || code2 > 57) { - return undefined // Not a digit - } - if (code1 === 50 && code2 > 51) { - return undefined // Hour cannot be greater than 23 - } - hour = (code1 - 48) * 10 + (code2 - 48) // Convert ASCII codes to number - } - let minute = 0 - if (date[14] === '0') { - const code = date.charCodeAt(15) - if (code < 48 || code > 57) { - return undefined // Not a digit - } - minute = code - 48 // Convert ASCII code to number - } else { - const code1 = date.charCodeAt(14) - if (code1 < 48 || code1 > 53) { - return undefined // Not a digit between 0 and 5 - } - const code2 = date.charCodeAt(15) - if (code2 < 48 || code2 > 57) { - return undefined // Not a digit - } - minute = (code1 - 48) * 10 + (code2 - 48) // Convert ASCII codes to number - } +/***/ }), - let second = 0 - if (date[17] === '0') { - const code = date.charCodeAt(18) - if (code < 48 || code > 57) { - return undefined // Not a digit - } - second = code - 48 // Convert ASCII code to number - } else { - const code1 = date.charCodeAt(17) - if (code1 < 48 || code1 > 53) { - return undefined // Not a digit between 0 and 5 - } - const code2 = date.charCodeAt(18) - if (code2 < 48 || code2 > 57) { - return undefined // Not a digit - } - second = (code1 - 48) * 10 + (code2 - 48) // Convert ASCII codes to number - } +/***/ 1020: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - const yearDigit1 = date.charCodeAt(20) - if (yearDigit1 < 48 || yearDigit1 > 57) { - return undefined // Not a digit - } - const yearDigit2 = date.charCodeAt(21) - if (yearDigit2 < 48 || yearDigit2 > 57) { - return undefined // Not a digit - } - const yearDigit3 = date.charCodeAt(22) - if (yearDigit3 < 48 || yearDigit3 > 57) { - return undefined // Not a digit - } - const yearDigit4 = date.charCodeAt(23) - if (yearDigit4 < 48 || yearDigit4 > 57) { - return undefined // Not a digit - } - const year = (yearDigit1 - 48) * 1000 + (yearDigit2 - 48) * 100 + (yearDigit3 - 48) * 10 + (yearDigit4 - 48) +/* module decorator */ module = __nccwpck_require__.nmd(module); - const result = new Date(Date.UTC(year, monthIdx, day, hour, minute, second)) - return result.getUTCDay() === weekday ? result : undefined -} -/** - * @see https://httpwg.org/specs/rfc9110.html#obsolete.date.formats - * - * @param {string} date - * @returns {Date | undefined} - */ -function parseRfc850Date (date) { - let commaIndex = -1 +const { Buffer } = __nccwpck_require__(4573) - let weekday = -1 - if (date[0] === 'S') { - if (date[1] === 'u' && date[2] === 'n' && date[3] === 'd' && date[4] === 'a' && date[5] === 'y') { - weekday = 0 // Sunday - commaIndex = 6 - } else if (date[1] === 'a' && date[2] === 't' && date[3] === 'u' && date[4] === 'r' && date[5] === 'd' && date[6] === 'a' && date[7] === 'y') { - weekday = 6 // Saturday - commaIndex = 8 - } - } else if (date[0] === 'M' && date[1] === 'o' && date[2] === 'n' && date[3] === 'd' && date[4] === 'a' && date[5] === 'y') { - weekday = 1 // Monday - commaIndex = 6 - } else if (date[0] === 'T') { - if (date[1] === 'u' && date[2] === 'e' && date[3] === 's' && date[4] === 'd' && date[5] === 'a' && date[6] === 'y') { - weekday = 2 // Tuesday - commaIndex = 7 - } else if (date[1] === 'h' && date[2] === 'u' && date[3] === 'r' && date[4] === 's' && date[5] === 'd' && date[6] === 'a' && date[7] === 'y') { - weekday = 4 // Thursday - commaIndex = 8 - } - } else if (date[0] === 'W' && date[1] === 'e' && date[2] === 'd' && date[3] === 'n' && date[4] === 'e' && date[5] === 's' && date[6] === 'd' && date[7] === 'a' && date[8] === 'y') { - weekday = 3 // Wednesday - commaIndex = 9 - } else if (date[0] === 'F' && date[1] === 'r' && date[2] === 'i' && date[3] === 'd' && date[4] === 'a' && date[5] === 'y') { - weekday = 5 // Friday - commaIndex = 6 - } else { - // Not a valid day name - return undefined - } +const wasmBase64 = 'AGFzbQEAAAABJwdgAX8Bf2ADf39/AX9gAn9/AGABfwBgBH9/f38Bf2AAAGADf39/AALLAQgDZW52GHdhc21fb25faGVhZGVyc19jb21wbGV0ZQAEA2VudhV3YXNtX29uX21lc3NhZ2VfYmVnaW4AAANlbnYLd2FzbV9vbl91cmwAAQNlbnYOd2FzbV9vbl9zdGF0dXMAAQNlbnYUd2FzbV9vbl9oZWFkZXJfZmllbGQAAQNlbnYUd2FzbV9vbl9oZWFkZXJfdmFsdWUAAQNlbnYMd2FzbV9vbl9ib2R5AAEDZW52GHdhc21fb25fbWVzc2FnZV9jb21wbGV0ZQAAAzU0BQYAAAMAAAAAAAADAQMAAwMDAAACAAAAAAICAgICAgICAgIBAQEBAQEBAQEBAwAAAwAAAAQFAXABExMFAwEAAgYIAX8BQcDZBAsHxQcoBm1lbW9yeQIAC19pbml0aWFsaXplAAgZX19pbmRpcmVjdF9mdW5jdGlvbl90YWJsZQEAC2xsaHR0cF9pbml0AAkYbGxodHRwX3Nob3VsZF9rZWVwX2FsaXZlADcMbGxodHRwX2FsbG9jAAsGbWFsbG9jADkLbGxodHRwX2ZyZWUADARmcmVlAAwPbGxodHRwX2dldF90eXBlAA0VbGxodHRwX2dldF9odHRwX21ham9yAA4VbGxodHRwX2dldF9odHRwX21pbm9yAA8RbGxodHRwX2dldF9tZXRob2QAEBZsbGh0dHBfZ2V0X3N0YXR1c19jb2RlABESbGxodHRwX2dldF91cGdyYWRlABIMbGxodHRwX3Jlc2V0ABMObGxodHRwX2V4ZWN1dGUAFBRsbGh0dHBfc2V0dGluZ3NfaW5pdAAVDWxsaHR0cF9maW5pc2gAFgxsbGh0dHBfcGF1c2UAFw1sbGh0dHBfcmVzdW1lABgbbGxodHRwX3Jlc3VtZV9hZnRlcl91cGdyYWRlABkQbGxodHRwX2dldF9lcnJubwAaF2xsaHR0cF9nZXRfZXJyb3JfcmVhc29uABsXbGxodHRwX3NldF9lcnJvcl9yZWFzb24AHBRsbGh0dHBfZ2V0X2Vycm9yX3BvcwAdEWxsaHR0cF9lcnJub19uYW1lAB4SbGxodHRwX21ldGhvZF9uYW1lAB8SbGxodHRwX3N0YXR1c19uYW1lACAabGxodHRw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AXRrQT5qIQILIAEgAjYCHCABQgA3AhAgAkECdEH01wBqIQACQEHI1QAoAgAiA0EBIAJ0IgdxRQRAIAAgATYCAEHI1QAgAyAHcjYCACABIAA2AhggASABNgIIIAEgATYCDAwBCyAEQRkgAkEBdmtBACACQR9HG3QhAiAAKAIAIQACQANAIAAiAygCBEF4cSAERg0BIAJBHXYhACACQQF0IQIgAyAAQQRxakEQaiIHKAIAIgANAAsgByABNgIAIAEgAzYCGCABIAE2AgwgASABNgIIDAELIAMoAggiACABNgIMIAMgATYCCCABQQA2AhggASADNgIMIAEgADYCCAtB5NUAQeTVACgCAEEBayIAQX8gABs2AgALCwcAIAAtACgLBwAgAC0AKgsHACAALQArCwcAIAAtACkLBwAgAC8BNAsHACAALQAwC0ABBH8gACgCGCEBIAAvAS4hAiAALQAoIQMgACgCOCEEIAAQOCAAIAQ2AjggACADOgAoIAAgAjsBLiAAIAE2AhgL5YUCAgd/A34gASACaiEEAkAgACIDKAIMIgANACADKAIEBEAgAyABNgIECyMAQRBrIgkkAAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAn8CQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAC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C0HjAQwHC0HXAQwGC0HYAQwFC0HZAQwEC0HaAQwDC0HbAQwCC0HdAQwBC0HcAQshAgNAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCADAn8CQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAn8CQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAn8CQAJAAkACQAJAAkACQAJ/AkACQAJAAn8CQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIAMCfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAg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ogKiAqICogKiAqICogKiAqICogKiAqICogIAogILIAQgAUEBaiIBRw0AC0HJACECDOwCCyABQQFqIQEgA0Evai0AAEEBcQ2lAiADQQA2AhwgAyABNgIUIANBlxA2AhAgA0EKNgIMQQAhAgzrAgsgASAERwRAA0AgAS0AAEEgRw0VIAQgAUEBaiIBRw0AC0H4ACECDOsCC0H4ACECDOoCCyADQQI6ACgMOAtBACECIANBADYCHCADQb8LNgIQIANBAjYCDCADIAFBAWo2AhQM6AILQQAhAgzOAgtBDSECDM0CC0ETIQIMzAILQRUhAgzLAgtBFiECDMoCC0EYIQIMyQILQRkhAgzIAgtBGiECDMcCC0EbIQIMxgILQRwhAgzFAgtBHSECDMQCC0EeIQIMwwILQR8hAgzCAgtBICECDMECC0EiIQIMwAILQSMhAgy/AgtBJSECDL4CC0HlACECDL0CCyADQT02AhwgAyABNgIUIAMgADYCDEEAIQIM1QILIANBGzYCHCADIAE2AhQgA0GkHDYCECADQRU2AgxBACECDNQCCyADQSA2AhwgAyABNgIUIANBmBo2AhAgA0EVNgIMQQAhAgzTAgsgA0ETNgIcIAMgATYCFCADQZgaNgIQIANBFTYCDEEAIQIM0gILIANBCzYCHCADIAE2AhQgA0GYGjYCECADQRU2AgxBACECDNECCyADQRA2AhwgAyABNgIUIANBmBo2AhAgA0EVNgIMQQAhAgzQAgsgA0EgNgIcIAMgATYCFCADQaQcNgIQIANBFTYCDEEAIQIMzwILIANBCzYCHCADIAE2AhQgA0GkHDYCECADQRU2AgxBACECDM4CCyADQQw2AhwgAyABNgIUIANBpBw2AhAgA0EVNgIMQQAhAgzNAgtBACECIANBADYCHCADIAE2AhQgA0HdDjYCECADQRI2AgwMzAILAkADQAJAIAEtAABBCmsOBAACAgACCyAEIAFBAWoiAUcNAAtB/QEhAgzMAgsCQAJAIAMtADZBAUcNAEEAIQACQCADKAI4IgJFDQAgAigCYCICRQ0AIAMgAhEAACEACyAARQ0AIABBFUcNASADQfwBNgIcIAMgATYCFCADQdwZNgIQIANBFTYCDEEAIQIMzQILQdwBIQIMswILIANBADYCHCADIAE2AhQgA0H5CzYCECADQR82AgxBACECDMsCCwJAAkAgAy0AKEEBaw4CBAEAC0HbASECDLICC0HUASECDLECCyADQQI6ADFBACEAAkAgAygCOCICRQ0AIAIoAgAiAkUNACADIAIRAAAhAAsgAEUEQEHdASECDLECCyAAQRVHBEAgA0EANgIcIAMgATYCFCADQbQMNgIQIANBEDYCDEEAIQIMygILIANB+wE2AhwgAyABNgIUIANBgRo2AhAgA0EVNgIMQQAhAgzJAgsgASAERgRAQfoBIQIMyQILIAEtAABByABGDQEgA0EBOgAoC0HAASECDK4CC0HaASECDK0CCyABIARHBEAgA0EMNgIIIAMgATYCBEHZASECDK0CC0H5ASECDMUCCyABIARGBEBB+AEhAgzFAgsgAS0AAEHIAEcNBCABQQFqIQFB2AEhAgyrAgsgASAERgRAQfcBIQIMxAILAkACQCABLQAAQcUAaw4QAAUFBQUFBQUFBQUFBQUFAQULIAFBAWohAUHWASECDKsCCyABQQFqIQFB1wEhAgyqAgtB9gEhAiABIARGDcICIAMoAgAiACAEIAFraiEFIAEgAGtBAmohBgJAA0AgAS0AACAAQbrVAGotAABHDQMgAEECRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADMMCCyADKAIEIQAgA0IANwMAIAMgACAGQQFqIgEQLiIARQRAQeMBIQIMqgILIANB9QE2AhwgAyABNgIUIAMgADYCDEEAIQIMwgILQfQBIQIgASAERg3BAiADKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEG41QBqLQAARw0CIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzCAgsgA0GBBDsBKCADKAIEIQAgA0IANwMAIAMgACAGQQFqIgEQLiIADQMMAgsgA0EANgIAC0EAIQIgA0EANgIcIAMgATYCFCADQeUfNgIQIANBCDYCDAy/AgtB1QEhAgylAgsgA0HzATYCHCADIAE2AhQgAyAANgIMQQAhAgy9AgtBACEAAkAgAygCOCICRQ0AIAIoAkAiAkUNACADIAIRAAAhAAsgAEUNbiAAQRVHBEAgA0EANgIcIAMgATYCFCADQYIPNgIQIANBIDYCDEEAIQIMvQILIANBjwE2AhwgAyABNgIUIANB7Bs2AhAgA0EVNgIMQQAhAgy8AgsgASAERwRAIANBDTYCCCADIAE2AgRB0wEhAgyjAgtB8gEhAgy7AgsgASAERgRAQfEBIQIMuwILAkACQAJAIAEtAABByABrDgsAAQgICAgICAgIAggLIAFBAWohAUHQASECDKMCCyABQQFqIQFB0QEhAgyiAgsgAUEBaiEBQdIBIQIMoQILQfABIQIgASAERg25AiADKAIAIgAgBCABa2ohBiABIABrQQJqIQUDQCABLQAAIABBtdUAai0AAEcNBCAAQQJGDQMgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAY2AgAMuQILQe8BIQIgASAERg24AiADKAIAIgAgBCABa2ohBiABIABrQQFqIQUDQCABLQAAIABBs9UAai0AAEcNAyAAQQFGDQIgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAY2AgAMuAILQe4BIQIgASAERg23AiADKAIAIgAgBCABa2ohBiABIABrQQJqIQUDQCABLQAAIABBsNUAai0AAEcNAiAAQQJGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAY2AgAMtwILIAMoAgQhACADQgA3AwAgAyAAIAVBAWoiARArIgBFDQIgA0HsATYCHCADIAE2AhQgAyAANgIMQQAhAgy2AgsgA0EANgIACyADKAIEIQAgA0EANgIEIAMgACABECsiAEUNnAIgA0HtATYCHCADIAE2AhQgAyAANgIMQQAhAgy0AgtBzwEhAgyaAgtBACEAAkAgAygCOCICRQ0AIAIoAjQiAkUNACADIAIRAAAhAAsCQCAABEAgAEEVRg0BIANBADYCHCADIAE2AhQgA0HqDTYCECADQSY2AgxBACECDLQCC0HOASECDJoCCyADQesBNgIcIAMgATYCFCADQYAbNgIQIANBFTYCDEEAIQIMsgILIAEgBEYEQEHrASECDLICCyABLQAAQS9GBEAgAUEBaiEBDAELIANBADYCHCADIAE2AhQgA0GyODYCECADQQg2AgxBACECDLECC0HNASECDJcCCyABIARHBEAgA0EONgIIIAMgATYCBEHMASECDJcCC0HqASECDK8CCyABIARGBEBB6QEhAgyvAgsgAS0AAEEwayIAQf8BcUEKSQRAIAMgADoAKiABQQFqIQFBywEhAgyWAgsgAygCBCEAIANBADYCBCADIAAgARAvIgBFDZcCIANB6AE2AhwgAyABNgIUIAMgADYCDEEAIQIMrgILIAEgBEYEQEHnASECDK4CCwJAIAEtAABBLkYEQCABQQFqIQEMAQsgAygCBCEAIANBADYCBCADIAAgARAvIgBFDZgCIANB5gE2AhwgAyABNgIUIAMgADYCDEEAIQIMrgILQcoBIQIMlAILIAEgBEYEQEHlASECDK0CC0EAIQBBASEFQQEhB0EAIQICQAJAAkACQAJAAn8CQAJAAkACQAJAAkACQCABLQAAQTBrDgoKCQABAgMEBQYICwtBAgwGC0EDDAULQQQMBAtBBQwDC0EGDAILQQcMAQtBCAshAkEAIQVBACEHDAILQQkhAkEBIQBBACEFQQAhBwwBC0EAIQVBASECCyADIAI6ACsgAUEBaiEBAkACQCADLQAuQRBxDQACQAJAAkAgAy0AKg4DAQACBAsgB0UNAwwCCyAADQEMAgsgBUUNAQsgAygCBCEAIANBADYCBCADIAAgARAvIgBFDQIgA0HiATYCHCADIAE2AhQgAyAANgIMQQAhAgyvAgsgAygCBCEAIANBADYCBCADIAAgARAvIgBFDZoCIANB4wE2AhwgAyABNgIUIAMgADYCDEEAIQIMrgILIAMoAgQhACADQQA2AgQgAyAAIAEQLyIARQ2YAiADQeQBNgIcIAMgATYCFCADIAA2AgwMrQILQckBIQIMkwILQQAhAAJAIAMoAjgiAkUNACACKAJEIgJFDQAgAyACEQAAIQALAkAgAARAIABBFUYNASADQQA2AhwgAyABNgIUIANBpA02AhAgA0EhNgIMQQAhAgytAgtByAEhAgyTAgsgA0HhATYCHCADIAE2AhQgA0HQGjYCECADQRU2AgxBACECDKsCCyABIARGBEBB4QEhAgyrAgsCQCABLQAAQSBGBEAgA0EAOwE0IAFBAWohAQwBCyADQQA2AhwgAyABNgIUIANBmRE2AhAgA0EJNgIMQQAhAgyrAgtBxwEhAgyRAgsgASAERgRAQeABIQIMqgILAkAgAS0AAEEwa0H/AXEiAkEKSQRAIAFBAWohAQJAIAMvATQiAEGZM0sNACADIABBCmwiADsBNCAAQf7/A3EgAkH//wNzSw0AIAMgACACajsBNAwCC0EAIQIgA0EANgIcIAMgATYCFCADQZUeNgIQIANBDTYCDAyrAgsgA0EANgIcIAMgATYCFCADQZUeNgIQIANBDTYCDEEAIQIMqgILQcYBIQIMkAILIAEgBEYEQEHfASECDKkCCwJAIAEtAABBMGtB/wFxIgJBCkkEQCABQQFqIQECQCADLwE0IgBBmTNLDQAgAyAAQQpsIgA7ATQgAEH+/wNxIAJB//8Dc0sNACADIAAgAmo7ATQMAgtBACECIANBADYCHCADIAE2AhQgA0GVHjYCECADQQ02AgwMqgILIANBADYCHCADIAE2AhQgA0GVHjYCECADQQ02AgxBACECDKkCC0HFASECDI8CCyABIARGBEBB3gEhAgyoAgsCQCABLQAAQTBrQf8BcSICQQpJBEAgAUEBaiEBAkAgAy8BNCIAQZkzSw0AIAMgAEEKbCIAOwE0IABB/v8DcSACQf//A3NLDQAgAyAAIAJqOwE0DAILQQAhAiADQQA2AhwgAyABNgIUIANBlR42AhAgA0ENNgIMDKkCCyADQQA2AhwgAyABNgIUIANBlR42AhAgA0ENNgIMQQAhAgyoAgtBxAEhAgyOAgsgASAERgRAQd0BIQIMpwILAkACQAJAAkAgAS0AAEEKaw4XAgMDAAMDAwMDAwMDAwMDAwMDAwMDAwEDCyABQQFqDAULIAFBAWohAUHDASECDI8CCyABQQFqIQEgA0Evai0AAEEBcQ0IIANBADYCHCADIAE2AhQgA0GNCzYCECADQQ02AgxBACECDKcCCyADQQA2AhwgAyABNgIUIANBjQs2AhAgA0ENNgIMQQAhAgymAgsgASAERwRAIANBDzYCCCADIAE2AgRBASECDI0CC0HcASECDKUCCwJAAkADQAJAIAEtAABBCmsOBAIAAAMACyAEIAFBAWoiAUcNAAtB2wEhAgymAgsgAygCBCEAIANBADYCBCADIAAgARAtIgBFBEAgAUEBaiEBDAQLIANB2gE2AhwgAyAANgIMIAMgAUEBajYCFEEAIQIMpQILIAMoAgQhACADQQA2AgQgAyAAIAEQLSIADQEgAUEBagshAUHBASECDIoCCyADQdkBNgIcIAMgADYCDCADIAFBAWo2AhRBACECDKICC0HCASECDIgCCyADQS9qLQAAQQFxDQEgA0EANgIcIAMgATYCFCADQeQcNgIQIANBGTYCDEEAIQIMoAILIAEgBEYEQEHZASEC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IAFBAWohAUGeASECDOQBCyABQQFqIQFBnwEhAgzjAQtBtwEhAiABIARGDfsBIAMoAgAiACAEIAFraiEFIAEgAGtBA2ohBgJAA0AgAS0AACAAQezUAGotAABHDSggAEEDRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADPwBCyADQQA2AgAgBkEBaiEBQQ0MKAtBtgEhAiABIARGDfoBIAMoAgAiACAEIAFraiEFIAEgAGtBAmohBgJAA0AgAS0AACAAQaHVAGotAABHDScgAEECRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADPsBCyADQQA2AgAgBkEBaiEBQQwMJwtBtQEhAiABIARGDfkBIAMoAgAiACAEIAFraiEFIAEgAGtBAWohBgJAA0AgAS0AACAAQerUAGotAABHDSYgAEEBRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADPoBCyADQQA2AgAgBkEBaiEBQQMMJgtBtAEhAiABIARGDfgBIAMoAgAiACAEIAFraiEFIAEgAGtBAWohBgJAA0AgAS0AACAAQejUAGotAABHDSUgAEEBRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADPkBCyADQQA2AgAgBkEBaiEBQSYMJQsgASAERgRAQbMBIQIM+AELAkACQCABLQAAQdQAaw4CAAEnCyABQQFqIQFBmQEhAgzfAQsgAUEBaiEBQZoBIQIM3gELQbIBIQIgASAERg32ASADKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEHm1ABqLQAARw0jIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAz3AQsgA0EANgIAIAZBAWohAUEnDCMLQbEBIQIgASAERg31ASADKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEHk1ABqLQAARw0iIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAz2AQsgA0EANgIAIAZBAWohAUEcDCILQbABIQIgASAERg30ASADKAIAIgAgBCABa2ohBSABIABrQQVqIQYCQANAIAEtAAAgAEHe1ABqLQAARw0hIABBBUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAz1AQsgA0EANgIAIAZBAWohAUEGDCELQa8BIQIgASAERg3zASADKAIAIgAgBCABa2ohBSABIABrQQRqIQYCQANAIAEtAAAgAEHZ1ABqLQAARw0gIABBBEYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAz0AQsgA0EANgIAIAZBAWohAUEZDCALIAEgBEYEQEGuASECDPMBCwJAAkACQAJAIAEtAABBLWsOIwAkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJAEkJCQkJAIkJCQDJAsgAUEBaiEBQY4BIQIM3AELIAFBAWohAUGPASECDNsBCyABQQFqIQFBlAEhAgzaAQsgAUEBaiEBQZUBIQIM2QELQa0BIQIgASAERg3xASADKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEHX1ABqLQAARw0eIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzyAQsgA0EANgIAIAZBAWohAUELDB4LIAEgBEYEQEGsASECDPEBCwJAAkAgAS0AAEHBAGsOAwAgASALIAFBAWohAUGQASECDNgBCyABQQFqIQFBkwEhAgzXAQsgASAERgRAQasBIQIM8AELAkACQCABLQAAQcEAaw4PAB8fHx8fHx8fHx8fHx8BHwsgAUEBaiEBQZEBIQIM1wELIAFBAWohAUGSASECDNYBCyABIARGBEBBqgEhAgzvAQsgAS0AAEHMAEcNHCABQQFqIQFBCgwbC0GpASECIAEgBEYN7QEgAygCACIAIAQgAWtqIQUgASAAa0EFaiEGAkADQCABLQAAIABB0dQAai0AAEcNGiAAQQVGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM7gELIANBADYCACAGQQFqIQFBHgwaC0GoASECIAEgBEYN7AEgAygCACIAIAQgAWtqIQUgASAAa0EGaiEGAkADQCABLQAAIABBytQAai0AAEcNGSAAQQZGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM7QELIANBADYCACAGQQFqIQFBFQwZC0GnASECIAEgBEYN6wEgAygCACIAIAQgAWtqIQUgASAAa0ECaiEGAkADQCABLQAAIABBx9QAai0AAEcNGCAAQQJGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM7AELIANBADYCACAGQQFqIQFBFwwYC0GmASECIAEgBEYN6gEgAygCACIAIAQgAWtqIQUgASAAa0EFaiEGAkADQCABLQAAIABBwdQAai0AAEcNFyAAQQVGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM6wELIANBADYCACAGQQFqIQFBGAwXCyABIARGBEBBpQEhAgzqAQsCQAJAIAEtAABByQBrDgcAGRkZGRkBGQsgAUEBaiEBQYsBIQIM0QELIAFBAWohAUGMASECDNABC0GkASECIAEgBEYN6AEgAygCACIAIAQgAWtqIQUgASAAa0EBaiEGAkADQCABLQAAIABBptUAai0AAEcNFSAAQQFGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM6QELIANBADYCACAGQQFqIQFBCQwVC0GjASECIAEgBEYN5wEgAygCACIAIAQgAWtqIQUgASAAa0EBaiEGAkADQCABLQAAIABBpNUAai0AAEcNFCAAQQFGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM6AELIANBADYCACAGQQFqIQFBHwwUC0GiASECIAEgBEYN5gEgAygCACIAIAQgAWtqIQUgASAAa0ECaiEGAkADQCABLQAAIABBvtQAai0AAEcNEyAAQQJGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM5wELIANBADYCACAGQQFqIQFBAgwTC0GhASECIAEgBEYN5QEgAygCACIAIAQgAWtqIQUgASAAa0EBaiEGA0AgAS0AACAAQbzUAGotAABHDREgAEEBRg0CIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADOUBCyABIARGBEBBoAEhAgzlAQtBASABLQAAQd8ARw0RGiABQQFqIQFBhwEhAgzLAQsgA0EANgIAIAZBAWohAUGIASECDMoBC0GfASECIAEgBEYN4gEgAygCACIAIAQgAWtqIQUgASAAa0EIaiEGAkADQCABLQAAIABBhNUAai0AAEcNDyAAQQhGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM4wELIANBADYCACAGQQFqIQFBKQwPC0GeASECIAEgBEYN4QEgAygCACIAIAQgAWtqIQUgASAAa0EDaiEGAkADQCABLQAAIABBuNQAai0AAEcNDiAAQQNGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM4gELIANBADYCACAGQQFqIQFBLQwOCyABIARGBEBBnQEhAgzhAQsgAS0AAEHFAEcNDiABQQFqIQFBhAEhAgzHAQsgASAERgRAQZwBIQIM4AELAkACQCABLQAAQcwAaw4IAA8PDw8PDwEPCyABQQFqIQFBggEhAgzHAQsgAUEBaiEBQYMBIQIMxgELQZsBIQIgASAERg3eASADKAIAIgAgBCABa2ohBSABIABrQQRqIQYCQANAIAEtAAAgAEGz1ABqLQAARw0LIABBBEYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzfAQsgA0EANgIAIAZBAWohAUEjDAsLQZoBIQIgASAERg3dASADKAIAIgAgBCABa2ohBSABIABrQQJqIQYCQANAIAEtAAAgAEGw1ABqLQAARw0KIABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzeAQsgA0EANgIAIAZBAWohAUEADAoLIAEgBEYEQEGZASECDN0BCwJAAkAgAS0AAEHIAGsOCAAMDAwMDAwBDAsgAUEBaiEBQf0AIQIMxAELIAFBAWohAUGAASECDMMBCyABIARGBEBBmAEhAgzcAQsCQAJAIAEtAABBzgBrDgMACwELCyABQQFqIQFB/gAhAgzDAQsgAUEBaiEBQf8AIQIMwgELIAEgBEYEQEGXASECDNsBCyABLQAAQdkARw0IIAFBAWohAUEIDAcLQZYBIQIgASAERg3ZASADKAIAIgAgBCABa2ohBSABIABrQQNqIQYCQANAIAEtAAAgAEGs1ABqLQAARw0GIABBA0YNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzaAQsgA0EANgIAIAZBAWohAUEFDAYLQZUBIQIgASAERg3YASADKAIAIgAgBCABa2ohBSABIABrQQVqIQYCQANAIAEtAAAgAEGm1ABqLQAARw0FIABBBUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzZAQsgA0EANgIAIAZBAWohAUEWDAULQZQBIQIgASAERg3XASADKAIAIgAgBCABa2ohBSABIABrQQJqIQYCQANAIAEtAAAgAEGh1QBqLQAARw0EIABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzYAQsgA0EANgIAIAZBAWohAUEQDAQLIAEgBEYEQEGTASECDNcBCwJAAkAgAS0AAEHDAGsODAAGBgYGBgYGBgYGAQYLIAFBAWohAUH5ACECDL4BCyABQQFqIQFB+gAhAgy9AQtBkgEhAiABIARGDdUBIAMoAgAiACAEIAFraiEFIAEgAGtBBWohBgJAA0AgAS0AACAAQaDUAGotAABHDQIgAEEFRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADNYBCyADQQA2AgAgBkEBaiEBQSQMAgsgA0EANgIADAILIAEgBEYEQEGRASECDNQBCyABLQAAQcwARw0BIAFBAWohAUETCzoAKSADKAIEIQAgA0EANgIEIAMgACABEC4iAA0CDAELQQAhAiADQQA2AhwgAyABNgIUIANB/h82AhAgA0EGNgIMDNEBC0H4ACECDLcBCyADQZABNgIcIAMgATYCFCADIAA2AgxBACECDM8BC0EAIQACQCADKAI4IgJFDQAgAigCQCICRQ0AIAMgAhEAACEACyAARQ0AIABBFUYNASADQQA2AhwgAyABNgIUIANBgg82AhAgA0EgNgIMQQAhAgzOAQtB9wAhAgy0AQsgA0GPATYCHCADIAE2AhQgA0HsGzYCECADQRU2AgxBACECDMwBCyABIARGBEBBjwEhAgzMAQsCQCABLQAAQSBGBEAgAUEBaiEBDAELIANBADYCHCADIAE2AhQgA0GbHzYCECADQQY2AgxBACECDMwBC0ECIQIMsgELA0AgAS0AAEEgRw0CIAQgAUEBaiIBRw0AC0GOASECDMoBCyABIARGBEBBjQEhAgzKAQsCQCABLQAAQQlrDgRKAABKAAtB9QAhAgywAQsgAy0AKUEFRgRAQfYAIQIMsAELQfQAIQIMrwELIAEgBEYEQEGMASECDMgBCyADQRA2AgggAyABNgIEDAoLIAEgBEYEQEGLASECDMcBCwJAIAEtAABBCWsOBEcAAEcAC0HzACECDK0BCyABIARHBEAgA0EQNgIIIAMgATYCBEHxACECDK0BC0GKASECDMUBCwJAIAEgBEcEQANAIAEtAABBoNAAai0AACIAQQNHBEACQCAAQQFrDgJJAAQLQfAAIQIMrwELIAQgAUEBaiIBRw0AC0GIASEC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BCABQQFqIgFHDQALQfsAIQIMpwELIAMoAgQhACADQQA2AgQgAyAAIAEQLCIARQ0DIANB2wA2AhwgAyABNgIUIAMgADYCDEEAIQIMpgELIAMoAgQhACADQQA2AgQgAyAAIAEQLCIARQ0DIANB3QA2AhwgAyABNgIUIAMgADYCDEEAIQIMpQELIAMoAgQhACADQQA2AgQgAyAAIAEQLCIARQ0DIANB+gA2AhwgAyABNgIUIAMgADYCDEEAIQIMpAELIANBADYCHCADIAE2AhQgA0G8CjYCECADQQc2AgxBACECDKMBC0HPACECDIkBC0HRACECDIgBC0HnACECDIcBCyABIARGBEBB+gAhAgygAQsCQCABLQAAQQlrDgQgAAAgAAsgAUEBaiEBQeYAIQIMhgELIAEgBEYEQEH5ACECDJ8BCwJAIAEtAABBCWsOBB8AAB8AC0EAIQACQCADKAI4IgJFDQAgAigCOCICRQ0AIAMgAhEAACEACyAARQRAQeIBIQIMhgELIABBFUcEQCADQQA2AhwgAyABNgIUIANByQ02AhAgA0EaNgIMQQAhAgyfAQsgA0H4ADYCHCADIAE2AhQgA0HqGjYCECADQRU2AgxBACECDJ4BCyABIARHBEAgA0ENNgIIIAMgATYCBEHkACECDIUBC0H3ACECDJ0BCyABIARGBEBB9gAhAgydAQsCQAJAAkAgAS0AAEHIAGsOCwABCwsLCwsLCwsCCwsgAUEBaiEBQd0AIQIMhQELIAFBAWohAUHgACECDIQBCyABQQFqIQFB4wAhAgyDAQtB9QAhAiABIARGDZsBIAMoAgAiACAEIAFraiEFIAEgAGtBAmohBgJAA0AgAS0AACAAQbXVAGotAABHDQggAEECRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADJwBCyADKAIEIQAgA0IANwMAIAMgACAGQQFqIgEQKyIABEAgA0H0ADYCHCADIAE2AhQgAyAANgIMQQAhAgycAQtB4gAhAgyCAQtBACEAAkAgAygCOCICRQ0AIAIoAjQiAkUNACADIAIRAAAhAAsCQCAABEAgAEEVRg0BIANBADYCHCADIAE2AhQgA0HqDTYCECADQSY2AgxBACECDJwBC0HhACECDIIBCyADQfMANgIcIAMgATYCFCADQYAbNgIQIANBFTYCDEEAIQIMmgELIAMtACkiAEEja0ELSQ0JAkAgAEEGSw0AQQEgAHRBygBxRQ0ADAoLQQAhAiADQQA2AhwgAyABNgIUIANB7Qk2AhAgA0EINgIMDJkBC0HyACECIAEgBEYNmAEgAygCACIAIAQgAWtqIQUgASAAa0EBaiEGAkADQCABLQAAIABBs9UAai0AAEcNBSAAQQFGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAMmQELIAMoAgQhACADQgA3AwAgAyAAIAZBAWoiARArIgAEQCADQfEANgIcIAMgATYCFCADIAA2AgxBACECDJkBC0HfACECDH8LQQAhAAJAIAMoAjgiAkUNACACKAI0IgJFDQAgAyACEQAAIQALAkAgAARAIABBFUYNASADQQA2AhwgAyABNgIUIANB6g02AhAgA0EmNgIMQQAhAgyZAQtB3gAhAgx/CyADQfAANgIcIAMgATYCFCADQYAbNgIQIANBFTYCDEEAIQIMlwELIAMtAClBIUYNBiADQQA2AhwgAyABNgIUIANBkQo2AhAgA0EINgIMQQAhAgyWAQtB7wAhAiABIARGDZUBIAMoAgAiACAEIAFraiEFIAEgAGtBAmohBgJAA0AgAS0AACAAQbDVAGotAABHDQIgAEECRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADJYBCyADKAIEIQAgA0IANwMAIAMgACAGQQFqIgEQKyIARQ0CIANB7QA2AhwgAyABNgIUIAMgADYCDEEAIQIMlQELIANBADYCAAsgAygCBCEAIANBADYCBCADIAAgARArIgBFDYABIANB7gA2AhwgAyABNgIUIAMgADYCDEEAIQIMkwELQdwAIQIMeQtBACEAAkAgAygCOCICRQ0AIAIoAjQiAkUNACADIAIRAAAhAAsCQCAABEAgAEEVRg0BIANBADYCHCADIAE2AhQgA0HqDTYCECADQSY2AgxBACECDJMBC0HbACECDHkLIANB7AA2AhwgAyABNgIUIANBgBs2AhAgA0EVNgIMQQAhAgyRAQsgAy0AKSIAQSNJDQAgAEEuRg0AIANBADYCHCADIAE2AhQgA0HJCTYCECADQQg2AgxBACECDJABC0HaACECDHYLIAEgBEYEQEHrACECDI8BCwJAIAEtAABBL0YEQCABQQFqIQEMAQsgA0EANgIcIAMgATYCFCADQbI4NgIQIANBCDYCDEEAIQIMjwELQdkAIQIMdQsgASAERwRAIANBDjYCCCADIAE2AgRB2AAhAgx1C0HqACECDI0BCyABIARGBEBB6QAhAgyNAQsgAS0AAEEwayIAQf8BcUEKSQRAIAMgADoAKiABQQFqIQFB1wAhAgx0CyADKAIEIQAgA0EANgIEIAMgACABEC8iAEUNeiADQegANgIcIAMgATYCFCADIAA2AgxBACECDIwBCyABIARGBEBB5wAhAgyMAQsCQCABLQAAQS5GBEAgAUEBaiEBDAELIAMoAgQhACADQQA2AgQgAyAAIAEQLyIARQ17IANB5gA2AhwgAyABNgIUIAMgADYCDEEAIQIMjAELQdYAIQIMcgsgASAERgRAQeUAIQIMiwELQQAhAEEBIQVBASEHQQAhAgJAAkACQAJAAkACfwJAAkACQAJAAkACQAJAIAEtAABBMGsOCgoJAAECAwQFBggLC0ECDAYLQQMMBQtBBAwEC0EFDAMLQQYMAgtBBwwBC0EICyECQQAhBUEAIQcMAgtBCSECQQEhAEEAIQVBACEHDAELQQAhBUEBIQILIAMgAjoAKyABQQFqIQECQAJAIAMtAC5BEHENAAJAAkACQCADLQAqDgMBAAIECyAHRQ0DDAILIAANAQwCCyAFRQ0BCyADKAIEIQAgA0EANgIEIAMgACABEC8iAEUNAiADQeIANgIcIAMgATYCFCADIAA2AgxBACECDI0BCyADKAIEIQAgA0EANgIEIAMgACABEC8iAEUNfSADQeMANgIcIAMgATYCFCADIAA2AgxBACECDIwBCyADKAIEIQAgA0EANgIEIAMgACABEC8iAEUNeyADQeQANgIcIAMgATYCFCADIAA2AgwMiwELQdQAIQIMcQsgAy0AKUEiRg2GAUHTACECDHALQQAhAAJAIAMoAjgiAkUNACACKAJEIgJFDQAgAyACEQAAIQALIABFBEBB1QAhAgxwCyAAQRVHBEAgA0EANgIcIAMgATYCFCADQaQNNgIQIANBITYCDEEAIQIMiQELIANB4QA2AhwgAyABNgIUIANB0Bo2AhAgA0EVNgIMQQAhAgyIAQsgASAERgRAQeAAIQIMiAELAkACQAJAAkACQCABLQAAQQprDgQBBAQABAsgAUEBaiEBDAELIAFBAWohASADQS9qLQAAQQFxRQ0BC0HSACECDHALIANBADYCHCADIAE2AhQgA0G2ETYCECADQQk2AgxBACECDIgBCyADQQA2AhwgAyABNgIUIANBthE2AhAgA0EJNgIMQQAhAgyHAQsgASAERgRAQd8AIQIMhwELIAEtAABBCkYEQCABQQFqIQEMCQsgAy0ALkHAAHENCCADQQA2AhwgAyABNgIUIANBthE2AhAgA0ECNgIMQQAhAgyGAQsgASAERgRAQd0AIQIMhgELIAEtAAAiAkENRgRAIAFBAWohAUHQACECDG0LIAEhACACQQlrDgQFAQEFAQsgBCABIgBGBEBB3AAhAgyFAQsgAC0AAEEKRw0AIABBAWoMAgtBACECIANBADYCHCADIAA2AhQgA0HKLTYCECADQQc2AgwMgwELIAEgBEYEQEHbACECDIMBCwJAIAEtAABBCWsOBAMAAAMACyABQQFqCyEBQc4AIQIMaAsgASAERgRAQdoAIQIMgQELIAEtAABBCWsOBAABAQABC0EAIQIgA0EANgIcIANBmhI2AhAgA0EHNgIMIAMgAUEBajYCFAx/CyADQYASOwEqQQAhAAJAIAMoAjgiAkUNACACKAI4IgJFDQAgAyACEQAAIQALIABFDQAgAEEVRw0BIANB2QA2AhwgAyABNgIUIANB6ho2AhAgA0EVNgIMQQAhAgx+C0HNACECDGQLIANBADYCHCADIAE2AhQgA0HJDTYCECADQRo2AgxBACECDHwLIAEgBEYEQEHZACECDHwLIAEtAABBIEcNPSABQQFqIQEgAy0ALkEBcQ09IANBADYCHCADIAE2AhQgA0HCHDYCECADQR42AgxBACECDHsLIAEgBEYEQEHYACECDHsLAkACQAJAAkACQCABLQAAIgBBCmsOBAIDAwABCyABQQFqIQFBLCECDGULIABBOkcNASADQQA2AhwgAyABNgIUIANB5xE2AhAgA0EKNgIMQQAhAgx9CyABQQFqIQEgA0Evai0AAEEBcUUNcyADLQAyQYABcUUEQCADQTJqIQIgAxA1QQAhAAJAIAMoAjgiBkUNACAGKAIoIgZFDQAgAyAGEQAAIQALAkACQCAADhZNTEsBAQEBAQEBAQEBAQEBAQEBAQEAAQsgA0EpNgIcIAMgATYCFCADQawZNgIQIANBFTYCDEEAIQIMfgsg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c3BvbnNlIHN0YXR1cwBFeHBlY3RlZCBMRiBhZnRlciBoZWFkZXJzAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMAVXNlciBjYWxsYmFjayBlcnJvcgBgb25fcmVzZXRgIGNhbGxiYWNrIGVycm9yAGBvbl9jaHVua19oZWFkZXJgIGNhbGxiYWNrIGVycm9yAGBvbl9tZXNzYWdlX2JlZ2luYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlYCBjYWxsYmFjayBlcnJvcgBgb25fc3RhdHVzX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fdmVyc2lvbl9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX3VybF9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX3Byb3RvY29sX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9oZWFkZXJfdmFsdWVfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9tZXNzYWdlX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fbWV0aG9kX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25faGVhZGVyX2ZpZWxkX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfZXh0ZW5zaW9uX25hbWVgIGNhbGxiYWNrIGVycm9yAFVuZXhwZWN0ZWQgY2hhciBpbiB1cmwgc2VydmVyAEludmFsaWQgaGVhZGVyIHZhbHVlIGNoYXIASW52YWxpZCBoZWFkZXIgZmllbGQgY2hhcgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3ZlcnNpb24ASW52YWxpZCBtaW5vciB2ZXJzaW9uAEludmFsaWQgbWFqb3IgdmVyc2lvbgBFeHBlY3RlZCBzcGFjZSBhZnRlciB2ZXJzaW9uAEV4cGVjdGVkIENSTEYgYWZ0ZXIgdmVyc2lvbgBJbnZhbGlkIEhUVFAgdmVyc2lvbgBJbnZhbGlkIGhlYWRlciB0b2tlbgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3VybABJbnZhbGlkIGNoYXJhY3RlcnMgaW4gdXJsAFVuZXhwZWN0ZWQgc3RhcnQgY2hhciBpbiB1cmwARG91YmxlIEAgaW4gdXJsAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fcHJvdG9jb2wARW1wdHkgQ29udGVudC1MZW5ndGgASW52YWxpZCBjaGFyYWN0ZXIgaW4gQ29udGVudC1MZW5ndGgAVHJhbnNmZXItRW5jb2RpbmcgY2FuJ3QgYmUgcHJlc2VudCB3aXRoIENvbnRlbnQtTGVuZ3RoAER1cGxpY2F0ZSBDb250ZW50LUxlbmd0aABJbnZhbGlkIGNoYXIgaW4gdXJsIHBhdGgAQ29udGVudC1MZW5ndGggY2FuJ3QgYmUgcHJlc2VudCB3aXRoIFRyYW5zZmVyLUVuY29kaW5nAE1pc3NpbmcgZXhwZWN0ZWQgQ1IgYWZ0ZXIgY2h1bmsgc2l6ZQBFeHBlY3RlZCBMRiBhZnRlciBjaHVuayBzaXplAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIHNpemUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfdmFsdWUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9jaHVua19leHRlbnNpb25fdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyB2YWx1ZQBVbmV4cGVjdGVkIHdoaXRlc3BhY2UgYWZ0ZXIgaGVhZGVyIHZhbHVlAE1pc3NpbmcgZXhwZWN0ZWQgQ1IgYWZ0ZXIgaGVhZGVyIHZhbHVlAE1pc3NpbmcgZXhwZWN0ZWQgTEYgYWZ0ZXIgaGVhZGVyIHZhbHVlAEludmFsaWQgYFRyYW5zZmVyLUVuY29kaW5nYCBoZWFkZXIgdmFsdWUATWlzc2luZyBleHBlY3RlZCBDUiBhZnRlciBjaHVuayBleHRlbnNpb24gdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyBxdW90ZSB2YWx1ZQBJbnZhbGlkIHF1b3RlZC1wYWlyIGluIGNodW5rIGV4dGVuc2lvbnMgcXVvdGVkIHZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgcXVvdGVkIHZhbHVlAFBhdXNlZCBieSBvbl9oZWFkZXJzX2NvbXBsZXRlAEludmFsaWQgRU9GIHN0YXRlAG9uX3Jlc2V0IHBhdXNlAG9uX2NodW5rX2hlYWRlciBwYXVzZQBvbl9tZXNzYWdlX2JlZ2luIHBhdXNlAG9uX2NodW5rX2V4dGVuc2lvbl92YWx1ZSBwYXVzZQBvbl9zdGF0dXNfY29tcGxldGUgcGF1c2UAb25fdmVyc2lvbl9jb21wbGV0ZSBwYXVzZQBvbl91cmxfY29tcGxldGUgcGF1c2UAb25fcHJvdG9jb2xfY29tcGxldGUgcGF1c2UAb25fY2h1bmtfY29tcGxldGUgcGF1c2UAb25faGVhZGVyX3ZhbHVlX2NvbXBsZXRlIHBhdXNlAG9uX21lc3NhZ2VfY29tcGxldGUgcGF1c2UAb25fbWV0aG9kX2NvbXBsZXRlIHBhdXNlAG9uX2hlYWRlcl9maWVsZF9jb21wbGV0ZSBwYXVzZQBvbl9jaHVua19leHRlbnNpb25fbmFtZSBwYXVzZQBVbmV4cGVjdGVkIHNwYWNlIGFmdGVyIHN0YXJ0IGxpbmUATWlzc2luZyBleHBlY3RlZCBDUiBhZnRlciByZXNwb25zZSBsaW5lAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fY2h1bmtfZXh0ZW5zaW9uX25hbWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyBuYW1lAE1pc3NpbmcgZXhwZWN0ZWQgQ1IgYWZ0ZXIgY2h1bmsgZXh0ZW5zaW9uIG5hbWUASW52YWxpZCBzdGF0dXMgY29kZQBQYXVzZSBvbiBDT05ORUNUL1VwZ3JhZGUAUGF1c2Ugb24gUFJJL1VwZ3JhZGUARXhwZWN0ZWQgSFRUUC8yIENvbm5lY3Rpb24gUHJlZmFjZQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX21ldGhvZABFeHBlY3RlZCBzcGFjZSBhZnRlciBtZXRob2QAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfZmllbGQAUGF1c2VkAEludmFsaWQgd29yZCBlbmNvdW50ZXJlZABJbnZhbGlkIG1ldGhvZCBlbmNvdW50ZXJlZABNaXNzaW5nIGV4cGVjdGVkIENSIGFmdGVyIGNodW5rIGRhdGEARXhwZWN0ZWQgTEYgYWZ0ZXIgY2h1bmsgZGF0YQBVbmV4cGVjdGVkIGNoYXIgaW4gdXJsIHNjaGVtYQBSZXF1ZXN0IGhhcyBpbnZhbGlkIGBUcmFuc2Zlci1FbmNvZGluZ2AARGF0YSBhZnRlciBgQ29ubmVjdGlvbjogY2xvc2VgAFNXSVRDSF9QUk9YWQBVU0VfUFJPWFkATUtBQ1RJVklUWQBVTlBST0NFU1NBQkxFX0VOVElUWQBRVUVSWQBDT1BZAE1PVkVEX1BFUk1BTkVOVExZAFRPT19FQVJMWQBOT1RJRlkARkFJTEVEX0RFUEVOREVOQ1kAQkFEX0dBVEVXQVkAUExBWQBQVVQAQ0hFQ0tPVVQAR0FURVdBWV9USU1FT1VUAFJFUVVFU1RfVElNRU9VVABORVRXT1JLX0NPTk5FQ1RfVElNRU9VVABDT05ORUNUSU9OX1RJTUVPVVQATE9HSU5fVElNRU9VVABORVRXT1JLX1JFQURfVElNRU9VVABQT1NUAE1JU0RJUkVDVEVEX1JFUVVFU1QAQ0xJRU5UX0NMT1NFRF9SRVFVRVNUAENMSUVOVF9DTE9TRURfTE9BRF9CQUxBTkNFRF9SRVFVRVNUAEJBRF9SRVFVRVNUAEhUVFBfUkVRVUVTVF9TRU5UX1RPX0hUVFBTX1BPUlQAUkVQT1JUAElNX0FfVEVBUE9UAFJFU0VUX0NPTlRFTlQATk9fQ09OVEVOVABQQVJUSUFMX0NPTlRFTlQASFBFX0lOVkFMSURfQ09OU1RBTlQASFBFX0NCX1JFU0VUAEdFVABIUEVfU1RSSUNUAENPTkZMSUNUAFRFTVBPUkFSWV9SRURJUkVDVABQRVJNQU5FTlRfUkVESVJFQ1QAQ09OTkVDVABNVUxUSV9TVEFUVVMASFBFX0lOVkFMSURfU1RBVFVTAFRPT19NQU5ZX1JFUVVFU1RTAEVBUkxZX0hJTlRTAFVOQVZBSUxBQkxFX0ZPUl9MRUdBTF9SRUFTT05TAE9QVElPTlMAU1dJVENISU5HX1BST1RPQ09MUwBWQVJJQU5UX0FMU09fTkVHT1RJQVRFUwBNVUxUSVBMRV9DSE9JQ0VTAElOVEVSTkFMX1NFUlZFUl9FUlJPUgBXRUJfU0VSVkVSX1VOS05PV05fRVJST1IAUkFJTEdVTl9FUlJPUgBJREVOVElUWV9QUk9WSURFUl9BVVRIRU5USUNBVElPTl9FUlJPUgBTU0xfQ0VSVElGSUNBVEVfRVJST1IASU5WQUxJRF9YX0ZPUldBUkRFRF9GT1IAU0VUX1BBUkFNRVRFUgBHRVRfUEFSQU1FVEVSAEhQRV9VU0VSAFNFRV9PVEhFUgBIUEVfQ0JfQ0hVTktfSEVBREVSAEV4cGVjdGVkIExGIGFmdGVyIENSAE1LQ0FMRU5EQVIAU0VUVVAAV0VCX1NFUlZFUl9JU19ET1dOAFRFQVJET1dOAEhQRV9DTE9TRURfQ09OTkVDVElPTgBIRVVSSVNUSUNfRVhQSVJBVElPTgBESVNDT05ORUNURURfT1BFUkFUSU9OAE5PTl9BVVRIT1JJVEFUSVZFX0lORk9STUFUSU9OAEhQRV9JTlZBTElEX1ZFUlNJT04ASFBFX0NCX01FU1NBR0VfQkVHSU4AU0lURV9JU19GUk9aRU4ASFBFX0lOVkFMSURfSEVBREVSX1RPS0VOAElOVkFMSURfVE9LRU4ARk9SQklEREVOAEVOSEFOQ0VfWU9VUl9DQUxNAEhQRV9JTlZBTElEX1VSTABCTE9DS0VEX0JZX1BBUkVOVEFMX0NPTlRST0wATUtDT0wAQUNMAEhQRV9JTlRFUk5BTABSRVFVRVNUX0hFQURFUl9GSUVMRFNfVE9PX0xBUkdFX1VOT0ZGSUNJQUwASFBFX09LAFVOTElOSwBVTkxPQ0sAUFJJAFJFVFJZX1dJVEgASFBFX0lOVkFMSURfQ09OVEVOVF9MRU5HVEgASFBFX1VORVhQRUNURURfQ09OVEVOVF9MRU5HVEgARkxVU0gAUFJPUFBBVENIAE0tU0VBUkNIAFVSSV9UT09fTE9ORwBQUk9DRVNTSU5HAE1JU0NFTExBTkVPVVNfUEVSU0lTVEVOVF9XQVJOSU5HAE1JU0NFTExBTkVPVVNfV0FSTklORwBIUEVfSU5WQUxJRF9UUkFOU0ZFUl9FTkNPRElORwBFeHBlY3RlZCBDUkxGAEhQRV9JTlZBTElEX0NIVU5LX1NJWkUATU9WRQBDT05USU5VRQBIUEVfQ0JfU1RBVFVTX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJTX0NPTVBMRVRFAEhQRV9DQl9WRVJTSU9OX0NPTVBMRVRFAEhQRV9DQl9VUkxfQ09NUExFVEUASFBFX0NCX1BST1RPQ09MX0NPTVBMRVRFAEhQRV9DQl9DSFVOS19DT01QTEVURQBIUEVfQ0JfSEVBREVSX1ZBTFVFX0NPTVBMRVRFAEhQRV9DQl9DSFVOS19FWFRFTlNJT05fVkFMVUVfQ09NUExFVEUASFBFX0NCX0NIVU5LX0VYVEVOU0lPTl9OQU1FX0NPTVBMRVRFAEhQRV9DQl9NRVNTQUdFX0NPTVBMRVRFAEhQRV9DQl9NRVRIT0RfQ09NUExFVEUASFBFX0NCX0hFQURFUl9GSUVMRF9DT01QTEVURQBERUxFVEUASFBFX0lOVkFMSURfRU9GX1NUQVRFAElOVkFMSURfU1NMX0NFUlRJRklDQVRFAFBBVVNFAE5PX1JFU1BPTlNFAFVOU1VQUE9SVEVEX01FRElBX1RZUEUAR09ORQBOT1RfQUNDRVBUQUJMRQBTRVJWSUNFX1VOQVZBSUxBQkxFAFJBTkdFX05PVF9TQVRJU0ZJQUJMRQBPUklHSU5fSVNfVU5SRUFDSEFCTEUAUkVTUE9OU0VfSVNfU1RBTEUAUFVSR0UATUVSR0UAUkVRVUVTVF9IRUFERVJfRklFTERTX1RPT19MQVJHRQBSRVFVRVNUX0hFQURFUl9UT09fTEFSR0UAUEFZTE9BRF9UT09fTEFSR0UASU5TVUZGSUNJRU5UX1NUT1JBR0UASFBFX1BBVVNFRF9VUEdSQURFAEhQRV9QQVVTRURfSDJfVVBHUkFERQBTT1VSQ0UAQU5OT1VOQ0UAVFJBQ0UASFBFX1VORVhQRUNURURfU1BBQ0UAREVTQ1JJQkUAVU5TVUJTQ1JJQkUAUkVDT1JEAEhQRV9JTlZBTElEX01FVEhPRABOT1RfRk9VTkQAUFJPUEZJTkQAVU5CSU5EAFJFQklORABVTkFVVEhPUklaRUQATUVUSE9EX05PVF9BTExPV0VEAEhUVFBfVkVSU0lPTl9OT1RfU1VQUE9SVEVEAEFMUkVBRFlfUkVQT1JURUQAQUNDRVBURUQATk9UX0lNUExFTUVOVEVEAExPT1BfREVURUNURUQASFBFX0NSX0VYUEVDVEVEAEhQRV9MRl9FWFBFQ1RFRABDUkVBVEVEAElNX1VTRUQASFBFX1BBVVNFRABUSU1FT1VUX09DQ1VSRUQAUEFZTUVOVF9SRVFVSVJFRABQUkVDT05ESVRJT05fUkVRVUlSRUQAUFJPWFlfQVVUSEVOVElDQVRJT05fUkVRVUlSRUQATkVUV09SS19BVVRIRU5USUNBVElPTl9SRVFVSVJFRABMRU5HVEhfUkVRVUlSRUQAU1NMX0NFUlRJRklDQVRFX1JFUVVJUkVEAFVQR1JBREVfUkVRVUlSRUQAUEFHRV9FWFBJUkVEAFBSRUNPTkRJVElPTl9GQUlMRUQARVhQRUNUQVRJT05fRkFJTEVEAFJFVkFMSURBVElPTl9GQUlMRUQAU1NMX0hBTkRTSEFLRV9GQUlMRUQATE9DS0VEAFRSQU5TRk9STUFUSU9OX0FQUExJRUQATk9UX01PRElGSUVEAE5PVF9FWFRFTkRFRABCQU5EV0lEVEhfTElNSVRfRVhDRUVERUQAU0lURV9JU19PVkVSTE9BREVEAEhFQUQARXhwZWN0ZWQgSFRUUC8sIFJUU1AvIG9yIElDRS8A5xUAAK8VAACkEgAAkhoAACYWAACeFAAA2xkAAHkVAAB+EgAA/hQAADYVAAALFgAA2BYAAPMSAABCGAAArBYAABIVAAAUFwAA7xcAAEgUAABxFwAAshoAAGsZAAB+GQAANRQAAIIaAABEFwAA/RYAAB4YAACHFwAAqhkAAJMSAAAHGAAALBcAAMoXAACkFwAA5xUAAOcVAABYFwAAOxgAAKASAAAtHAAAwxEAAEgRAADeEgAAQhMAAKQZAAD9EAAA9xUAAKUVAADvFgAA+BkAAEoWAABWFgAA9RUAAAoaAAAIGgAAARoAAKsVAABCEgAA1xAAAEwRAAAFGQAAVBYAAB4RAADKGQAAyBkAAE4WAAD/GAAAcRQAAPAVAADuFQAAlBkAAPwVAAC/GQAAmxkAAHwUAABDEQAAcBgAAJUUAAAnFAAAGRQAANUSAADUGQAARBYAAPcQAEG5OwsBAQBB0DsL4AEBAQIBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQBBuj0LBAEAAAIAQdE9C14DBAMDAwMDAAADAwADAwADAwMDAwMDAwMDAAUAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAwADAEG6PwsEAQAAAgBB0T8LXgMAAwMDAwMAAAMDAAMDAAMDAwMDAwMDAwMABAAFAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwADAAMAQbDBAAsNbG9zZWVlcC1hbGl2ZQBBycEACwEBAEHgwQAL4AEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQBBycMACwEBAEHgwwAL5wEBAQEBAQEBAQEBAQECAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAWNodW5rZWQAQfHFAAteAQABAQEBAQAAAQEAAQEAAQEBAQEBAQEBAQAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEAAQBB0McACyFlY3Rpb25lbnQtbGVuZ3Rob25yb3h5LWNvbm5lY3Rpb24AQYDIAAsgcmFuc2Zlci1lbmNvZGluZ3BncmFkZQ0KDQpTTQ0KDQoAQanIAAsFAQIAAQMAQcDIAAtfBAUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUAQanKAAsFAQIAAQMAQcDKAAtfBAUFBgUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUAQanMAAsEAQAAAQBBwcwAC14CAgACAgICAgICAgICAgICAgICAgICAgICAgICAgIAAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAEGpzgALBQECAAEDAEHAzgALXwQFAAAFBQUFBQUFBQUFBQYFBQUFBQUFBQUFBQUABQAHCAUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQAFAAUABQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUAAAAFAEGp0AALBQEBAAEBAEHA0AALAQEAQdrQAAtBAgAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAQanSAAsFAQEAAQEAQcDSAAsBAQBBytIACwYCAAAAAAIAQeHSAAs6AwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwBBoNQAC50BTk9VTkNFRUNLT1VUTkVDVEVURUNSSUJFTFVTSEVURUFEU0VBUkNIUkdFQ1RJVklUWUxFTkRBUlZFT1RJRllQVElPTlNDSFNFQVlTVEFUQ0hHRVVFUllPUkRJUkVDVE9SVFJDSFBBUkFNRVRFUlVSQ0VCU0NSSUJFQVJET1dOQUNFSU5ETktDS1VCU0NSSUJFVFRQQ0VUU1BBRFRQLw==' - if ( - date[commaIndex] !== ',' || - (date.length - commaIndex - 1) !== 23 || - date[commaIndex + 1] !== ' ' || - date[commaIndex + 4] !== '-' || - date[commaIndex + 8] !== '-' || - date[commaIndex + 11] !== ' ' || - date[commaIndex + 14] !== ':' || - date[commaIndex + 17] !== ':' || - date[commaIndex + 20] !== ' ' || - date[commaIndex + 21] !== 'G' || - date[commaIndex + 22] !== 'M' || - date[commaIndex + 23] !== 'T' - ) { - return undefined - } +let wasmBuffer - let day = 0 - if (date[commaIndex + 2] === '0') { - // Single digit day, e.g. "Sun Nov 6 08:49:37 1994" - const code = date.charCodeAt(commaIndex + 3) - if (code < 49 || code > 57) { - return undefined // Not a digit - } - day = code - 48 // Convert ASCII code to number - } else { - const code1 = date.charCodeAt(commaIndex + 2) - if (code1 < 49 || code1 > 51) { - return undefined // Not a digit between 1 and 3 - } - const code2 = date.charCodeAt(commaIndex + 3) - if (code2 < 48 || code2 > 57) { - return undefined // Not a digit - } - day = (code1 - 48) * 10 + (code2 - 48) // Convert ASCII codes to number +Object.defineProperty(module, 'exports', { + get: () => { + return wasmBuffer + ? wasmBuffer + : (wasmBuffer = Buffer.from(wasmBase64, 'base64')) } +}) - let monthIdx = -1 - if ( - (date[commaIndex + 5] === 'J' && date[commaIndex + 6] === 'a' && date[commaIndex + 7] === 'n') - ) { - monthIdx = 0 // Jan - } else if ( - (date[commaIndex + 5] === 'F' && date[commaIndex + 6] === 'e' && date[commaIndex + 7] === 'b') - ) { - monthIdx = 1 // Feb - } else if ( - (date[commaIndex + 5] === 'M' && date[commaIndex + 6] === 'a' && date[commaIndex + 7] === 'r') - ) { - monthIdx = 2 // Mar - } else if ( - (date[commaIndex + 5] === 'A' && date[commaIndex + 6] === 'p' && date[commaIndex + 7] === 'r') - ) { - monthIdx = 3 // Apr - } else if ( - (date[commaIndex + 5] === 'M' && date[commaIndex + 6] === 'a' && date[commaIndex + 7] === 'y') - ) { - monthIdx = 4 // May - } else if ( - (date[commaIndex + 5] === 'J' && date[commaIndex + 6] === 'u' && date[commaIndex + 7] === 'n') - ) { - monthIdx = 5 // Jun - } else if ( - (date[commaIndex + 5] === 'J' && date[commaIndex + 6] === 'u' && date[commaIndex + 7] === 'l') - ) { - monthIdx = 6 // Jul - } else if ( - (date[commaIndex + 5] === 'A' && date[commaIndex + 6] === 'u' && date[commaIndex + 7] === 'g') - ) { - monthIdx = 7 // Aug - } else if ( - (date[commaIndex + 5] === 'S' && date[commaIndex + 6] === 'e' && date[commaIndex + 7] === 'p') - ) { - monthIdx = 8 // Sep - } else if ( - (date[commaIndex + 5] === 'O' && date[commaIndex + 6] === 'c' && date[commaIndex + 7] === 't') - ) { - monthIdx = 9 // Oct - } else if ( - (date[commaIndex + 5] === 'N' && date[commaIndex + 6] === 'o' && date[commaIndex + 7] === 'v') - ) { - monthIdx = 10 // Nov - } else if ( - (date[commaIndex + 5] === 'D' && date[commaIndex + 6] === 'e' && date[commaIndex + 7] === 'c') - ) { - monthIdx = 11 // Dec - } else { - // Not a valid month - return undefined - } - const yearDigit1 = date.charCodeAt(commaIndex + 9) - if (yearDigit1 < 48 || yearDigit1 > 57) { - return undefined // Not a digit - } - const yearDigit2 = date.charCodeAt(commaIndex + 10) - if (yearDigit2 < 48 || yearDigit2 > 57) { - return undefined // Not a digit - } +/***/ }), - let year = (yearDigit1 - 48) * 10 + (yearDigit2 - 48) // Convert ASCII codes to number +/***/ 820: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - // RFC 6265 states that the year is in the range 1970-2069. - // @see https://datatracker.ietf.org/doc/html/rfc6265#section-5.1.1 - // - // 3. If the year-value is greater than or equal to 70 and less than or - // equal to 99, increment the year-value by 1900. - // 4. If the year-value is greater than or equal to 0 and less than or - // equal to 69, increment the year-value by 2000. - year += year < 70 ? 2000 : 1900 +/* module decorator */ module = __nccwpck_require__.nmd(module); - let hour = 0 - if (date[commaIndex + 12] === '0') { - const code = date.charCodeAt(commaIndex + 13) - if (code < 48 || code > 57) { - return undefined // Not a digit - } - hour = code - 48 // Convert ASCII code to number - } else { - const code1 = date.charCodeAt(commaIndex + 12) - if (code1 < 48 || code1 > 50) { - return undefined // Not a digit between 0 and 2 - } - const code2 = date.charCodeAt(commaIndex + 13) - if (code2 < 48 || code2 > 57) { - return undefined // Not a digit - } - if (code1 === 50 && code2 > 51) { - return undefined // Hour cannot be greater than 23 - } - hour = (code1 - 48) * 10 + (code2 - 48) // Convert ASCII codes to number - } - let minute = 0 - if (date[commaIndex + 15] === '0') { - const code = date.charCodeAt(commaIndex + 16) - if (code < 48 || code > 57) { - return undefined // Not a digit - } - minute = code - 48 // Convert ASCII code to number - } else { - const code1 = date.charCodeAt(commaIndex + 15) - if (code1 < 48 || code1 > 53) { - return undefined // Not a digit between 0 and 5 - } - const code2 = date.charCodeAt(commaIndex + 16) - if (code2 < 48 || code2 > 57) { - return undefined // Not a digit - } - minute = (code1 - 48) * 10 + (code2 - 48) // Convert ASCII codes to number - } +const { Buffer } = __nccwpck_require__(4573) - let second = 0 - if (date[commaIndex + 18] === '0') { - const code = date.charCodeAt(commaIndex + 19) - if (code < 48 || code > 57) { - return undefined // Not a digit - } - second = code - 48 // Convert ASCII code to number - } else { - const code1 = date.charCodeAt(commaIndex + 18) - if (code1 < 48 || code1 > 53) { - return undefined // Not a digit between 0 and 5 - } - const code2 = date.charCodeAt(commaIndex + 19) - if (code2 < 48 || code2 > 57) { - return undefined // Not a digit - } - second = (code1 - 48) * 10 + (code2 - 48) // Convert ASCII codes to number - } +const wasmBase64 = 'AGFzbQEAAAABJwdgAX8Bf2ADf39/AX9gAn9/AGABfwBgBH9/f38Bf2AAAGADf39/AALLAQgDZW52GHdhc21fb25faGVhZGVyc19jb21wbGV0ZQAEA2VudhV3YXNtX29uX21lc3NhZ2VfYmVnaW4AAANlbnYLd2FzbV9vbl91cmwAAQNlbnYOd2FzbV9vbl9zdGF0dXMAAQNlbnYUd2FzbV9vbl9oZWFkZXJfZmllbGQAAQNlbnYUd2FzbV9vbl9oZWFkZXJfdmFsdWUAAQNlbnYMd2FzbV9vbl9ib2R5AAEDZW52GHdhc21fb25fbWVzc2FnZV9jb21wbGV0ZQAAAzU0BQYAAAMAAAAAAAADAQMAAwMDAAACAAAAAAICAgICAgICAgIBAQEBAQEBAQEBAwAAAwAAAAQFAXABExMFAwEAAgYIAX8BQcDZBAsHxQcoBm1lbW9yeQIAC19pbml0aWFsaXplAAgZX19pbmRpcmVjdF9mdW5jdGlvbl90YWJsZQEAC2xsaHR0cF9pbml0AAkYbGxodHRwX3Nob3VsZF9rZWVwX2FsaXZlADcMbGxodHRwX2FsbG9jAAsGbWFsbG9jADkLbGxodHRwX2ZyZWUADARmcmVlAAwPbGxodHRwX2dldF90eXBlAA0VbGxodHRwX2dldF9odHRwX21ham9yAA4VbGxodHRwX2dldF9odHRwX21pbm9yAA8RbGxodHRwX2dldF9tZXRob2QAEBZsbGh0dHBfZ2V0X3N0YXR1c19jb2RlABESbGxodHRwX2dldF91cGdyYWRlABIMbGxodHRwX3Jlc2V0ABMObGxodHRwX2V4ZWN1dGUAFBRsbGh0dHBfc2V0dGluZ3NfaW5pdAAVDWxsaHR0cF9maW5pc2gAFgxsbGh0dHBfcGF1c2UAFw1sbGh0dHBfcmVzdW1lABgbbGxodHRwX3Jlc3VtZV9hZnRlcl91cGdyYWRlABkQbGxodHRwX2dldF9lcnJubwAaF2xsaHR0cF9nZXRfZXJyb3JfcmVhc29uABsXbGxodHRwX3NldF9lcnJvcl9yZWFzb24AHBRsbGh0dHBfZ2V0X2Vycm9yX3BvcwAdEWxsaHR0cF9lcnJub19uYW1lAB4SbGxodHRwX21ldGhvZF9uYW1lAB8SbGxodHRwX3N0YXR1c19uYW1lACAabGxodHRw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AXRrQT5qIQILIAEgAjYCHCABQgA3AhAgAkECdEH01wBqIQACQEHI1QAoAgAiA0EBIAJ0IgdxRQRAIAAgATYCAEHI1QAgAyAHcjYCACABIAA2AhggASABNgIIIAEgATYCDAwBCyAEQRkgAkEBdmtBACACQR9HG3QhAiAAKAIAIQACQANAIAAiAygCBEF4cSAERg0BIAJBHXYhACACQQF0IQIgAyAAQQRxakEQaiIHKAIAIgANAAsgByABNgIAIAEgAzYCGCABIAE2AgwgASABNgIIDAELIAMoAggiACABNgIMIAMgATYCCCABQQA2AhggASADNgIMIAEgADYCCAtB5NUAQeTVACgCAEEBayIAQX8gABs2AgALCwcAIAAtACgLBwAgAC0AKgsHACAALQArCwcAIAAtACkLBwAgAC8BNAsHACAALQAwC0ABBH8gACgCGCEBIAAvAS4hAiAALQAoIQMgACgCOCEEIAAQOCAAIAQ2AjggACADOgAoIAAgAjsBLiAAIAE2AhgLhocCAwd/A34BeyABIAJqIQQCQCAAIgMoAgwiAA0AIAMoAgQEQCADIAE2AgQLIwBBEGsiCSQAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAC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DAgLQeMBDAcLQdcBDAYLQdgBDAULQdkBDAQLQdoBDAMLQdsBDAILQd0BDAELQdwBCyECA0ACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIAMCfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACfwJAAkACQAJAAkACQAJAAn8CQAJAAkACfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgAwJ/AkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJ/AkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAC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A0EXNgIcIAMgADYCDCADIAFBAWo2AhQM+AILIABBFUYNI0EAIQIgA0EANgIcIAMgATYCFCADQdYMNgIQIANBIzYCDAz3AgsgAygCBCEAQQAhAiADQQA2AgQgAyAAIAEQNCIARQRAIAFBAWohAQwdCyADQRk2AhwgAyAANgIMIAMgAUEBajYCFAz2AgsgAygCBCEAQQAhAiADQQA2AgQgAyAAIAEQNCIARQRAIAFBAWohAQzvAgsgA0EaNgIcIAMgADYCDCADIAFBAWo2AhQM9QILIABBFUYNH0EAIQIgA0EANgIcIAMgATYCFCADQdAPNgIQIANBIjYCDAz0AgsgAygCBCEAIANBADYCBCADIAAgARAzIgBFBEAgAUEBaiEBDBsLIANBHDYCHCADIAA2AgwgAyABQQFqNgIUQQAhAgzzAgsgAygCBCEAIANBADYCBCADIAAgARAzIgBFBEAgAUEBaiEBDOsCCyADQR02AhwgAyAANgIMIAMgAUEBajYCFEEAIQIM8gILIABBO0cNASABQQFqIQELQSYhAgzXAgtBACECIANBADYCHCADIAE2AhQgA0GfFTYCECADQQw2AgwM7wILIAEgBEcEQANAIAEtAABBIEcNhAIgBCABQQFqIgFHDQALQSwhAgzvAgtBLCECDO4CCyABIARGBEBBNCECDO4CCwJAAkADQAJAIAEtAABBCmsOBAIAAAMACyAEIAFBAWoiAUcNAAtBNCECDO8CCyADKAIEIQAgA0EANgIEIAMgACABEDEiAEUNnwIgA0EyNgIcIAMgATYCFCADIAA2AgxBACECDO4CCyADKAIEIQAgA0EANgIEIAMgACABEDEiAEUEQCABQQFqIQEMnwILIANBMjYCHCADIAA2AgwgAyABQQFqNgIUQQAhAgztAgsgASAERwRAAkADQCABLQAAQTBrIgBB/wFxQQpPBEBBOiECDNcCCyADKQMgIgtCmbPmzJmz5swZVg0BIAMgC0IKfiIKNwMgIAogAK1C/wGDIgtCf4VWDQEgAyAKIAt8NwMgIAQgAUEBaiIBRw0AC0HAACECDO4CCyADKAIEIQAgA0EANgIEIAMgACABQQFqIgEQMSIADRcM4gILQcAAIQIM7AILIAEgBEYEQEHJACECDOwCCwJAA0ACQCABLQAAQQlrDhgAAqICogKpAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAgCiAgsgBCABQQFqIgFHDQALQckAIQIM7AILIAFBAWohASADQS9qLQAAQQFxDaUCIANBADYCHCADIAE2AhQgA0GXEDYCECADQQo2AgxBACECDOsCCyABIARHBEADQCABLQAAQSBHDRUgBCABQQFqIgFHDQALQfgAIQIM6wILQfgAIQIM6gILIANBAjoAKAw4C0EAIQIgA0EANgIcIANBvws2AhAgA0ECNgIMIAMgAUEBajYCFAzoAgtBACECDM4CC0ENIQIMzQILQRMhAgzMAgtBFSECDMsCC0EWIQIMygILQRghAgzJAgtBGSECDMgCC0EaIQIMxwILQRshAgzGAgtBHCECDMUCC0EdIQIMxAILQR4hAgzDAgtBHyECDMICC0EgIQIMwQILQSIhAgzAAgtBIyECDL8CC0ElIQIMvgILQeUAIQIMvQILIANBPTYCHCADIAE2AhQgAyAANgIMQQAhAgzVAgsgA0EbNgIcIAMgATYCFCADQaQcNgIQIANBFTYCDEEAIQIM1AILIANBIDYCHCADIAE2AhQgA0GYGjYCECADQRU2AgxBACECDNMCCyADQRM2AhwgAyABNgIUIANBmBo2AhAgA0EVNgIMQQAhAgzSAgsgA0ELNgIcIAMgATYCFCADQZgaNgIQIANBFTYCDEEAIQIM0QILIANBEDYCHCADIAE2AhQgA0GYGjYCECADQRU2AgxBACECDNACCyADQSA2AhwgAyABNgIUIANBpBw2AhAgA0EVNgIMQQAhAgzPAgsgA0ELNgIcIAMgATYCFCADQaQcNgIQIANBFTYCDEEAIQIMzgILIANBDDYCHCADIAE2AhQgA0GkHDYCECADQRU2AgxBACECDM0CC0EAIQIgA0EANgIcIAMgATYCFCADQd0ONgIQIANBEjYCDAzMAgsCQANAAkAgAS0AAEEKaw4EAAICAAILIAQgAUEBaiIBRw0AC0H9ASECDMwCCwJAAkAgAy0ANkEBRw0AQQAhAAJAIAMoAjgiAkUNACACKAJgIgJFDQAgAyACEQAAIQALIABFDQAgAEEVRw0BIANB/AE2AhwgAyABNgIUIANB3Bk2AhAgA0EVNgIMQQAhAgzNAgtB3AEhAgyzAgsgA0EANgIcIAMgATYCFCADQfkLNgIQIANBHzYCDEEAIQIMywILAkACQCADLQAoQQFrDgIEAQALQdsBIQIMsgILQdQBIQIMsQILIANBAjoAMUEAIQACQCADKAI4IgJFDQAgAigCACICRQ0AIAMgAhEAACEACyAARQRAQd0BIQIMsQILIABBFUcEQCADQQA2AhwgAyABNgIUIANBtAw2AhAgA0EQNgIMQQAhAgzKAgsgA0H7ATYCHCADIAE2AhQgA0GBGjYCECADQRU2AgxBACECDMkCCyABIARGBEBB+gEhAgzJAgsgAS0AAEHIAEYNASADQQE6ACgLQcABIQIMrgILQdoBIQIMrQILIAEgBEcEQCADQQw2AgggAyABNgIEQdkBIQIMrQILQfkBIQIMxQILIAEgBEYEQEH4ASECDMUCCyABLQAAQcgARw0EIAFBAWohAUHYASECDKsCCyABIARGBEBB9wEhAgzEAgsCQAJAIAEtAABBxQBrDhAABQUFBQUFBQUFBQUFBQUBBQsgAUEBaiEBQdYBIQIMqwILIAFBAWohAUHXASECDKoCC0H2ASECIAEgBEYNwgIgAygCACIAIAQgAWtqIQUgASAAa0ECaiEGAkADQCABLQAAIABButUAai0AAEcNAyAAQQJGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAMwwILIAMoAgQhACADQgA3AwAgAyAAIAZBAWoiARAuIgBFBEBB4wEhAgyqAgsgA0H1ATYCHCADIAE2AhQgAyAANgIMQQAhAgzCAgtB9AEhAiABIARGDcECIAMoAgAiACAEIAFraiEFIAEgAGtBAWohBgJAA0AgAS0AACAAQbjVAGotAABHDQIgAEEBRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADMICCyADQYEEOwEoIAMoAgQhACADQgA3AwAgAyAAIAZBAWoiARAuIgANAwwCCyADQQA2AgALQQAhAiADQQA2AhwgAyABNgIUIANB5R82AhAgA0EINgIMDL8CC0HVASECDKUCCyADQfMBNgIcIAMgATYCFCADIAA2AgxBACECDL0CC0EAIQACQCADKAI4IgJFDQAgAigCQCICRQ0AIAMgAhEAACEACyAARQ1uIABBFUcEQCADQQA2AhwgAyABNgIUIANBgg82AhAgA0EgNgIMQQAhAgy9AgsgA0GPATYCHCADIAE2AhQgA0HsGzYCECADQRU2AgxBACECDLwCCyABIARHBEAgA0ENNgIIIAMgATYCBEHTASECDKMCC0HyASECDLsCCyABIARGBEBB8QEhAgy7AgsCQAJAAkAgAS0AAEHIAGsOCwABCAgICAgICAgCCAsgAUEBaiEBQdABIQIMowILIAFBAWohAUHRASECDKICCyABQQFqIQFB0gEhAgyhAgtB8AEhAiABIARGDbkCIAMoAgAiACAEIAFraiEGIAEgAGtBAmohBQNAIAEtAAAgAEG11QBqLQAARw0EIABBAkYNAyAAQQFqIQAgBCABQQFqIgFHDQALIAMgBjYCAAy5AgtB7wEhAiABIARGDbgCIAMoAgAiACAEIAFraiEGIAEgAGtBAWohBQNAIAEtAAAgAEGz1QBqLQAARw0DIABBAUYNAiAAQQFqIQAgBCABQQFqIgFHDQALIAMgBjYCAAy4AgtB7gEhAiABIARGDbcCIAMoAgAiACAEIAFraiEGIAEgAGtBAmohBQNAIAEtAAAgAEGw1QBqLQAARw0CIABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBjYCAAy3AgsgAygCBCEAIANCADcDACADIAAgBUEBaiIBECsiAEUNAiADQewBNgIcIAMgATYCFCADIAA2AgxBACECDLYCCyADQQA2AgALIAMoAgQhACADQQA2AgQgAyAAIAEQKyIARQ2cAiADQe0BNgIcIAMgATYCFCADIAA2AgxBACECDLQCC0HPASECDJoCC0EAIQACQCADKAI4IgJFDQAgAigCNCICRQ0AIAMgAhEAACEACwJAIAAEQCAAQRVGDQEgA0EANgIcIAMgATYCFCADQeoNNgIQIANBJjYCDEEAIQIMtAILQc4BIQIMmgILIANB6wE2AhwgAyABNgIUIANBgBs2AhAgA0EVNgIMQQAhAgyyAgsgASAERgRAQesBIQIMsgILIAEtAABBL0YEQCABQQFqIQEMAQsgA0EANgIcIAMgATYCFCADQbI4NgIQIANBCDYCDEEAIQIMsQILQc0BIQIMlwILIAEgBEcEQCADQQ42AgggAyABNgIEQcwBIQIMlwILQeoBIQIMrwILIAEgBEYEQEHpASECDK8CCyABLQAAQTBrIgBB/wFxQQpJBEAgAyAAOgAqIAFBAWohAUHLASECDJYCCyADKAIEIQAgA0EANgIEIAMgACABEC8iAEUNlwIgA0HoATYCHCADIAE2AhQgAyAANgIMQQAhAgyuAgsgASAERgRAQecBIQIMrgILAkAgAS0AAEEuRgRAIAFBAWohAQwBCyADKAIEIQAgA0EANgIEIAMgACABEC8iAEUNmAIgA0HmATYCHCADIAE2AhQgAyAANgIMQQAhAgyuAgtBygEhAgyUAgsgASAERgRAQeUBIQIMrQILQQAhAEEBIQVBASEHQQAhAgJAAkACQAJAAkACfwJAAkACQAJAAkACQAJAIAEtAABBMGsOCgoJAAECAwQFBggLC0ECDAYLQQMMBQtBBAwEC0EFDAMLQQYMAgtBBwwBC0EICyECQQAhBUEAIQcMAgtBCSECQQEhAEEAIQVBACEHDAELQQAhBUEBIQILIAMgAjoAKyABQQFqIQECQAJAIAMtAC5BEHENAAJAAkACQCADLQAqDgMBAAIECyAHRQ0DDAILIAANAQwCCyAFRQ0BCyADKAIEIQAgA0EANgIEIAMgACABEC8iAEUNAiADQeIBNgIcIAMgATYCFCADIAA2AgxBACECDK8CCyADKAIEIQAgA0EANgIEIAMgACABEC8iAEUNmgIgA0HjATYCHCADIAE2AhQgAyAANgIMQQAhAgyuAgsgAygCBCEAIANBADYCBCADIAAgARAvIgBFDZgCIANB5AE2AhwgAyABNgIUIAMgADYCDAytAgtByQEhAgyTAgtBACEAAkAgAygCOCICRQ0AIAIoAkQiAkUNACADIAIRAAAhAAsCQCAABEAgAEEVRg0BIANBADYCHCADIAE2AhQgA0GkDTYCECADQSE2AgxBACECDK0CC0HIASECDJMCCyADQeEBNgIcIAMgATYCFCADQdAaNgIQIANBFTYCDEEAIQIMqwILIAEgBEYEQEHhASECDKsCCwJAIAEtAABBIEYEQCADQQA7ATQgAUEBaiEBDAELIANBADYCHCADIAE2AhQgA0GZETYCECADQQk2AgxBACECDKsCC0HHASECDJECCyABIARGBEBB4AEhAgyqAgsCQCABLQAAQTBrQf8BcSICQQpJBEAgAUEBaiEBAkAgAy8BNCIAQZkzSw0AIAMgAEEKbCIAOwE0IABB/v8DcSACQf//A3NLDQAgAyAAIAJqOwE0DAILQQAhAiADQQA2AhwgAyABNgIUIANBlR42AhAgA0ENNgIMDKsCCyADQQA2AhwgAyABNgIUIANBlR42AhAgA0ENNgIMQQAhAgyqAgtBxgEhAgyQAgsgASAERgRAQd8BIQIMqQILAkAgAS0AAEEwa0H/AXEiAkEKSQRAIAFBAWohAQJAIAMvATQiAEGZM0sNACADIABBCmwiADsBNCAAQf7/A3EgAkH//wNzSw0AIAMgACACajsBNAwCC0EAIQIgA0EANgIcIAMgATYCFCADQZUeNgIQIANBDTYCDAyqAgsgA0EANgIcIAMgATYCFCADQZUeNgIQIANBDTYCDEEAIQIMqQILQcUBIQIMjwILIAEgBEYEQEHeASECDKgCCwJAIAEtAABBMGtB/wFxIgJBCkkEQCABQQFqIQECQCADLwE0IgBBmTNLDQAgAyAAQQpsIgA7ATQgAEH+/wNxIAJB//8Dc0sNACADIAAgAmo7ATQMAgtBACECIANBADYCHCADIAE2AhQgA0GVHjYCECADQQ02AgwMqQILIANBADYCHCADIAE2AhQgA0GVHjYCECADQQ02AgxBACECDKgCC0HEASECDI4CCyABIARGBEBB3QEhAgynAgsCQAJAAkACQCABLQAAQQprDhcCAwMAAwMDAwMDAwMDAwMDAwMDAwMDAQMLIAFBAWoMBQsgAUEBaiEBQcMBIQIMjwILIAFBAWohASADQS9qLQAAQQFxDQggA0EANgIcIAMgATYCFCADQY0LNgIQIANBDTYCDEEAIQIMpwILIANBADYCHCADIAE2AhQgA0GNCzYCECADQQ02AgxBACECDKYCCyABIARHBEAgA0EPNgIIIAMgATYCBEEBIQIMjQILQdwBIQIMpQILAkACQANAAkAgAS0AAEEKaw4EAgAAAwALIAQgAUEBaiIBRw0AC0HbASECDKYCCyADKAIEIQAgA0EANgIEIAMgACABEC0iAEUEQCABQQFqIQEMBAsgA0HaATYCHCADIAA2AgwgAyABQQFqNgIUQQAhAgylAgsgAygCBCEAIANBADYCBCADIAAgARAtIgANASABQQFqCyEBQcEBIQIMigILIANB2QE2AhwgAyAANgIMIAMgAUEBajYCFEEAIQIMogILQcIBIQIMiAILIANBL2otAABBAXENASADQQA2AhwgAyABNgIUIANB5Bw2AhAgA0EZNgIMQQAhAgygAgsgASAERgRAQdkB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CyADIAU2AgAMkAILIANBADYCACAGQQFqIQFBGgw8C0HKASECIAEgBEYNjgIgAygCACIAIAQgAWtqIQUgASAAa0EDaiEGAkADQCABLQAAIABBjdUAai0AAEcNOyAAQQNGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAMjwILIANBADYCACAGQQFqIQFBIQw7CyABIARGBEBByQEhAgyOAgsCQAJAIAEtAABBwQBrDhQAPT09PT09PT09PT09PT09PT09AT0LIAFBAWohAUGtASECDPUBCyABQQFqIQFBsAEhAgz0AQsgASAERgRAQcgBIQIMjQILAkACQCABLQAAQdUAaw4LADw8PDw8PDw8PAE8CyABQQFqIQFBrgEhAgz0AQsgAUEBaiEBQa8BIQIM8wELQccBIQIgASAERg2LAiADKAIAIgAgBCABa2ohBSABIABrQQhqIQYCQANAIAEtAAAgAEGE1QBqLQAARw04IABBCEYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAyMAgsgA0EANgIAIAZBAWohAUEqDDgLIAEgBEYEQEHGASECDIsCCyABLQAAQdAARw04IAFBAWohAUElDDcLQcUBIQIgASAERg2JAiADKAIAIgAgBCABa2ohBSABIABrQQJqIQYCQANAIAEtAAAgAEGB1QBqLQAARw02IABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAyKAgsgA0EANgIAIAZBAWohAUEODDYLIAEgBEYEQEHEASECDIkCCyABLQAAQcUARw02IAFBAWohAUGrASECDO8BCyABIARGBEBBwwEhAgyIAgsCQAJAAkACQCABLQAAQcIAaw4PAAECOTk5OTk5OTk5OTkDOQsgAUEBaiEBQacBIQIM8QELIAFBAWohAUGoASECDPABCyABQQFqIQFBqQEhAgzvAQsgAUEBaiEBQaoBIQIM7gELQcIBIQIgASAERg2GAiADKAIAIgAgBCABa2ohBSABIABrQQJqIQYCQANAIAEtAAAgAEH+1ABqLQAARw0zIABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAyHAgsgA0EANgIAIAZBAWohAUEUDDMLQcEBIQIgASAERg2FAiADKAIAIgAgBCABa2ohBSABIABrQQRqIQYCQANAIAEtAAAgAEH51ABqLQAARw0yIABBBEYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAyGAgsgA0EANgIAIAZBAWohAUErDDILQcABIQIgASAERg2EAiADKAIAIgAgBCABa2ohBSABIABrQQJqIQYCQANAIAEtAAAgAEH21ABqLQAARw0xIABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAyFAgsgA0EANgIAIAZBAWohAUEsDDELQb8BIQIgASAERg2DAiADKAIAIgAgBCABa2ohBSABIABrQQJqIQYCQANAIAEtAAAgAEGh1QBqLQAARw0wIABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAyEAgsgA0EANgIAIAZBAWohAUERDDALQb4BIQIgASAERg2CAiADKAIAIgAgBCABa2ohBSABIABrQQNqIQYCQANAIAEtAAAgAEHy1ABqLQAARw0vIABBA0YNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAyDAgsgA0EANgIAIAZBAWohAUEuDC8LIAEgBEYEQEG9ASECDIICCwJAAkACQAJAAkAgAS0AAEHBAGsOFQA0NDQ0NDQ0NDQ0ATQ0AjQ0AzQ0BDQLIAFBAWohAUGbASECDOwBCyABQQFqIQFBnAEhAgzrAQsgAUEBaiEBQZ0BIQIM6gELIAFBAWohAUGiASECDOkBCyABQQFqIQFBpAEhAgzoAQsgASAERgRAQbwBIQIMgQILAkACQCABLQAAQdIAaw4DADABMAsgAUEBaiEBQaMBIQIM6AELIAFBAWohAUEEDC0LQbsBIQIgASAERg3/ASADKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEHw1ABqLQAARw0sIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAyAAgsgA0EANgIAIAZBAWohAUEdDCwLIAEgBEYEQEG6ASECDP8BCwJAAkAgAS0AAEHJAGsOBwEuLi4uLgAuCyABQQFqIQFBoQEhAgzmAQsgAUEBaiEBQSIMKwsgASAERgRAQbkBIQIM/gELIAEtAABB0ABHDSsgAUEBaiEBQaABIQIM5AELIAEgBEYEQEG4ASECDP0BCwJAAkAgAS0AAEHGAGsOCwAsLCwsLCwsLCwBLAsgAUEBaiEBQZ4BIQIM5AELIAFBAWohAUGfASECDOMBC0G3ASECIAEgBEYN+wEgAygCACIAIAQgAWtqIQUgASAAa0EDaiEGAkADQCABLQAAIABB7NQAai0AAEcNKCAAQQNGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM/AELIANBADYCACAGQQFqIQFBDQwoC0G2ASECIAEgBEYN+gEgAygCACIAIAQgAWtqIQUgASAAa0ECaiEGAkADQCABLQAAIABBodUAai0AAEcNJyAAQQJGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM+wELIANBADYCACAGQQFqIQFBDAwnC0G1ASECIAEgBEYN+QEgAygCACIAIAQgAWtqIQUgASAAa0EBaiEGAkADQCABLQAAIABB6tQAai0AAEcNJiAAQQFGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM+gELIANBADYCACAGQQFqIQFBAwwmC0G0ASECIAEgBEYN+AEgAygCACIAIAQgAWtqIQUgASAAa0EBaiEGAkADQCABLQAAIABB6NQAai0AAEcNJSAAQQFGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM+QELIANBADYCACAGQQFqIQFBJgwlCyABIARGBEBBswEhAgz4AQsCQAJAIAEtAABB1ABrDgIAAScLIAFBAWohAUGZASECDN8BCyABQQFqIQFBmgEhAgzeAQtBsgEhAiABIARGDfYBIAMoAgAiACAEIAFraiEFIAEgAGtBAWohBgJAA0AgAS0AACAAQebUAGotAABHDSMgAEEBRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADPcBCyADQQA2AgAgBkEBaiEBQScMIwtBsQEhAiABIARGDfUBIAMoAgAiACAEIAFraiEFIAEgAGtBAWohBgJAA0AgAS0AACAAQeTUAGotAABHDSIgAEEBRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADPYBCyADQQA2AgAgBkEBaiEBQRwMIgtBsAEhAiABIARGDfQBIAMoAgAiACAEIAFraiEFIAEgAGtBBWohBgJAA0AgAS0AACAAQd7UAGotAABHDSEgAEEFRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADPUBCyADQQA2AgAgBkEBaiEBQQYMIQtBrwEhAiABIARGDfMBIAMoAgAiACAEIAFraiEFIAEgAGtBBGohBgJAA0AgAS0AACAAQdnUAGotAABHDSAgAEEERg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADPQBCyADQQA2AgAgBkEBaiEBQRkMIAsgASAERgRAQa4BIQIM8wELAkACQAJAAkAgAS0AAEEtaw4jACQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkASQkJCQkAiQkJAMkCyABQQFqIQFBjgEhAgzcAQsgAUEBaiEBQY8BIQIM2wELIAFBAWohAUGUASECDNoBCyABQQFqIQFBlQEhAgzZAQtBrQEhAiABIARGDfEBIAMoAgAiACAEIAFraiEFIAEgAGtBAWohBgJAA0AgAS0AACAAQdfUAGotAABHDR4gAEEBRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADPIBCyADQQA2AgAgBkEBaiEBQQsMHgsgASAERgRAQawBIQIM8QELAkACQCABLQAAQcEAaw4DACABIAsgAUEBaiEBQZABIQIM2AELIAFBAWohAUGTASECDNcBCyABIARGBEBBqwEhAgzwAQsCQAJAIAEtAABBwQBrDg8AHx8fHx8fHx8fHx8fHwEfCyABQQFqIQFBkQEhAgzXAQsgAUEBaiEBQZIBIQIM1gELIAEgBEYEQEGqASECDO8BCyABLQAAQcwARw0cIAFBAWohAUEKDBsLQakBIQIgASAERg3tASADKAIAIgAgBCABa2ohBSABIABrQQVqIQYCQANAIAEtAAAgAEHR1ABqLQAARw0aIABBBUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzuAQsgA0EANgIAIAZBAWohAUEeDBoLQagBIQIgASAERg3sASADKAIAIgAgBCABa2ohBSABIABrQQZqIQYCQANAIAEtAAAgAEHK1ABqLQAARw0ZIABBBkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAztAQsgA0EANgIAIAZBAWohAUEVDBkLQacBIQIgASAERg3rASADKAIAIgAgBCABa2ohBSABIABrQQJqIQYCQANAIAEtAAAgAEHH1ABqLQAARw0YIABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzsAQsgA0EANgIAIAZBAWohAUEXDBgLQaYBIQIgASAERg3qASADKAIAIgAgBCABa2ohBSABIABrQQVqIQYCQANAIAEtAAAgAEHB1ABqLQAARw0XIABBBUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzrAQsgA0EANgIAIAZBAWohAUEYDBcLIAEgBEYEQEGlASECDOoBCwJAAkAgAS0AAEHJAGsOBwAZGRkZGQEZCyABQQFqIQFBiwEhAgzRAQsgAUEBaiEBQYwBIQIM0AELQaQBIQIgASAERg3oASADKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEGm1QBqLQAARw0VIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzpAQsgA0EANgIAIAZBAWohAUEJDBULQaMBIQIgASAERg3nASADKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEGk1QBqLQAARw0UIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzoAQsgA0EANgIAIAZBAWohAUEfDBQLQaIBIQIgASAERg3mASADKAIAIgAgBCABa2ohBSABIABrQQJqIQYCQANAIAEtAAAgAEG+1ABqLQAARw0TIABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAznAQsgA0EANgIAIAZBAWohAUECDBMLQaEBIQIgASAERg3lASADKAIAIgAgBCABa2ohBSABIABrQQFqIQYDQCABLQAAIABBvNQAai0AAEcNESAAQQFGDQIgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM5QELIAEgBEYEQEGgASECDOUBC0EBIAEtAABB3wBHDREaIAFBAWohAUGHASECDMsBCyADQQA2AgAgBkEBaiEBQYgBIQIMygELQZ8BIQIgASAERg3iASADKAIAIgAgBCABa2ohBSABIABrQQhqIQYCQANAIAEtAAAgAEGE1QBqLQAARw0PIABBCEYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzjAQsgA0EANgIAIAZBAWohAUEpDA8LQZ4BIQIgASAERg3hASADKAIAIgAgBCABa2ohBSABIABrQQNqIQYCQANAIAEtAAAgAEG41ABqLQAARw0OIABBA0YNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAziAQsgA0EANgIAIAZBAWohAUEtDA4LIAEgBEYEQEGdASECDOEBCyABLQAAQcUARw0OIAFBAWohAUGEASECDMcBCyABIARGBEBBnAEhAgzgAQsCQAJAIAEtAABBzABrDggADw8PDw8PAQ8LIAFBAWohAUGCASECDMcBCyABQQFqIQFBgwEhAgzGAQtBmwEhAiABIARGDd4BIAMoAgAiACAEIAFraiEFIAEgAGtBBGohBgJAA0AgAS0AACAAQbPUAGotAABHDQsgAEEERg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADN8BCyADQQA2AgAgBkEBaiEBQSMMCwtBmgEhAiABIARGDd0BIAMoAgAiACAEIAFraiEFIAEgAGtBAmohBgJAA0AgAS0AACAAQbDUAGotAABHDQogAEECRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADN4BCyADQQA2AgAgBkEBaiEBQQAMCgsgASAERgRAQZkBIQIM3QELAkACQCABLQAAQcgAaw4IAAwMDAwMDAEMCyABQQFqIQFB/QAhAgzEAQsgAUEBaiEBQYABIQIMwwELIAEgBEYEQEGYASECDNwBCwJAAkAgAS0AAEHOAGsOAwALAQsLIAFBAWohAUH+ACECDMMBCyABQQFqIQFB/wAhAgzCAQsgASAERgRAQZcBIQIM2wELIAEtAABB2QBHDQggAUEBaiEBQQgMBwtBlgEhAiABIARGDdkBIAMoAgAiACAEIAFraiEFIAEgAGtBA2ohBgJAA0AgAS0AACAAQazUAGotAABHDQYgAEEDRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADNoBCyADQQA2AgAgBkEBaiEBQQUMBgtBlQEhAiABIARGDdgBIAMoAgAiACAEIAFraiEFIAEgAGtBBWohBgJAA0AgAS0AACAAQabUAGotAABHDQUgAEEFRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADNkBCyADQQA2AgAgBkEBaiEBQRYMBQtBlAEhAiABIARGDdcBIAMoAgAiACAEIAFraiEFIAEgAGtBAmohBgJAA0AgAS0AACAAQaHVAGotAABHDQQgAEECRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADNgBCyADQQA2AgAgBkEBaiEBQRAMBAsgASAERgRAQZMBIQIM1wELAkACQCABLQAAQcMAaw4MAAYGBgYGBgYGBgYBBgsgAUEBaiEBQfkAIQIMvgELIAFBAWohAUH6ACECDL0BC0GSASECIAEgBEYN1QEgAygCACIAIAQgAWtqIQUgASAAa0EFaiEGAkADQCABLQAAIABBoNQAai0AAEcNAiAAQQVGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM1gELIANBADYCACAGQQFqIQFBJAwCCyADQQA2AgAMAgsgASAERgRAQZEBIQIM1AELIAEtAABBzABHDQEgAUEBaiEBQRMLOgApIAMoAgQhACADQQA2AgQgAyAAIAEQLiIADQIMAQtBACECIANBADYCHCADIAE2AhQgA0H+HzYCECADQQY2AgwM0QELQfgAIQIMtwELIANBkAE2AhwgAyABNgIUIAMgADYCDEEAIQIMzwELQQAhAAJAIAMoAjgiAkUNACACKAJAIgJFDQAgAyACEQAAIQALIABFDQAgAEEVRg0BIANBADYCHCADIAE2AhQgA0GCDzYCECADQSA2AgxBACECDM4BC0H3ACECDLQBCyADQY8BNgIcIAMgATYCFCADQewbNgIQIANBFTYCDEEAIQIMzAELIAEgBEYEQEGPASECDMwBCwJAIAEtAABBIEYEQCABQQFqIQEMAQsgA0EANgIcIAMgATYCFCADQZsfNgIQIANBBjYCDEEAIQIMzAELQQIhAgyyAQsDQCABLQAAQSBHDQIgBCABQQFqIgFHDQALQY4BIQIMygELIAEgBEYEQEGNASECDMoBCwJAIAEtAABBCWsOBEoAAEoAC0H1ACECDLABCyADLQApQQVGBEBB9gAhAgywAQtB9AAhAgyvAQsgASAERgRAQYwBIQIMyAELIANBEDYCCCADIAE2AgQMCgsgASAERgRAQYsBIQIMxwELAkAgAS0AAEEJaw4ERwAARwALQfMAIQIMrQELIAEgBEcEQCADQRA2AgggAyABNgIEQfEAIQIMrQELQYoBIQIMxQELAkAgASAERwRAA0AgAS0AAEGg0ABqLQAAIgBBA0cEQAJAIABBAWsOAkkABAtB8AAhAgyvAQsgBCABQQFqIgFHDQALQYgBIQIMxgELQYgBIQIMxQELIANBADYCHCADIAE2AhQgA0HbIDYCECADQQc2AgxBACECDMQBCyABIARGBEBBiQEhAgzEAQsCQAJAAkAgAS0AAEGg0gBqLQAAQQFrDgNGAgABC0HyACECDKwBCyADQQA2AhwgAyABNgIUIANBtBI2AhAgA0EHNgIMQQAhAgzEAQtB6gAhAgyqAQsgASAERwRAIAFBAWohAUHvACECDKoBC0GHASECDMIBCyAEIAEiAEYEQEGGASECDMIBCyAALQAAIgFBL0YEQCAAQQFqIQFB7gAhAgypAQsgAUEJayICQRdLDQEgACEBQQEgAnRBm4CABHENQQwBCyAEIAEiAEYEQEGFASECDMEBCyAALQAAQS9HDQAgAEEBaiEBDAMLQQAhAiADQQA2AhwgAyAANgIUIANB2yA2AhAgA0EHNgIMDL8BCwJAAkACQAJAAkADQCABLQAAQaDOAGotAAAiAEEFRwRAAkACQCAAQQFrDghHBQYHCAAEAQgLQesAIQIMrQELIAFBAWohAUHtACECDKwBCyAEIAFBAWoiAUcNAAtBhAEhAgzDAQsgAUEBagwUCyADKAIEIQAgA0EANgIEIAMgACABECwiAEUNHiADQdsANgIcIAMgATYCFCADIAA2AgxBACECDMEBCyADKAIEIQAgA0EANgIEIAMgACABECwiAEUNHiADQd0ANgIcIAMgATYCFCADIAA2AgxBACECDMABCyADKAIEIQAgA0EANgIEIAMgACABECwiAEUNHiADQfoANgIcIAMgATYCFCADIAA2AgxBACECDL8BCyADQQA2AhwgAyABNgIUIANB+Q82AhAgA0EHNgIMQQAhAgy+AQsgASAERgRAQYMBIQIMvgELAkAgAS0AAEGgzgBqLQAAQQFrDgg+BAUGAAgCAwcLIAFBAWohAQtBAyECDKMBCyABQQFqDA0LQQAhAiADQQA2AhwgA0HREjYCECADQQc2AgwgAyABQQFqNgIUDLoBCyADKAIEIQAgA0EANgIEIAMgACABECwiAEUNFiADQdsANgIcIAMgATYCFCADIAA2AgxBACECDLkBCyADKAIEIQAgA0EANgIEIAMgACABECwiAEUNFiADQd0ANgIcIAMgATYCFCADIAA2AgxBACECDLgBCyADKAIEIQAgA0EANgIEIAMgACABECwiAEUNFiADQfoANgIcIAMgATYCFCADIAA2AgxBACECDLcBCyADQQA2AhwgAyABNgIUIANB+Q82AhAgA0EHNgIMQQAhAgy2AQtB7AAhAgycAQsgASAERgRAQYIBIQIMtQELIAFBAWoMAgsgASAERgRAQYEBIQIMtAELIAFBAWoMAQsgASAERg0BIAFBAWoLIQFBBCECDJgBC0GAASECDLABCwNAIAEtAABBoMwAai0AACIAQQJHBEAgAEEBRwRAQekAIQIMmQELDDELIAQgAUEBaiIBRw0AC0H/ACECDK8BCyABIARGBEBB/gAhAgyvAQsCQCABLQAAQQlrDjcvAwYvBAYGBgYGBgYGBgYGBgYGBgYGBgUGBgIGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYABgsgAUEBagshAUEFIQIMlAELIAFBAWoMBgsgAygCBCEAIANBADYCBCADIAAgARAsIgBFDQggA0HbADYCHCADIAE2AhQgAyAANgIMQQAhAgyrAQsgAygCBCEAIANBADYCBCADIAAgARAsIgBFDQggA0HdADYCHCADIAE2AhQgAyAANgIMQQAhAgyqAQsgAygCBCEAIANBADYCBCADIAAgARAsIgBFDQggA0H6ADYCHCADIAE2AhQgAyAANgIMQQAhAgypAQsgA0EANgIcIAMgATYCFCADQY0UNgIQIANBBzYCDEEAIQIMqAELAkACQAJAAkADQCABLQAAQaDKAGotAAAiAEEFRwRAAkAgAEEBaw4GLgMEBQYABgtB6AAhAgyUAQsgBCABQQFqIgFHDQALQf0AIQIMqwELIAMoAgQhACADQQA2AgQgAyAAIAEQLCIARQ0HIANB2wA2AhwgAyABNgIUIAMgADYCDEEAIQIMqgELIAMoAgQhACADQQA2AgQgAyAAIAEQLCIARQ0HIANB3QA2AhwgAyABNgIUIAMgADYCDEEAIQIMqQELIAMoAgQhACADQQA2AgQgAyAAIAEQLCIARQ0HIANB+gA2AhwgAyABNgIUIAMgADYCDEEAIQIMqAELIANBADYCHCADIAE2AhQgA0HkCDYCECADQQc2AgxBACECDKcBCyABIARGDQEgAUEBagshAUEGIQIMjAELQfwAIQIMpAELAkACQAJAAkADQCABLQAAQaDIAGotAAAiAEEFRwRAIABBAWsOBCkCAwQFCyAEIAFBAWoiAUcNAAtB+wAhAgynAQsgAygCBCEAIANBADYCBCADIAAgARAsIgBFDQMgA0HbADYCHCADIAE2AhQgAyAANgIMQQAhAgymAQsgAygCBCEAIANBADYCBCADIAAgARAsIgBFDQMgA0HdADYCHCADIAE2AhQgAyAANgIMQQAhAgylAQsgAygCBCEAIANBADYCBCADIAAgARAsIgBFDQMgA0H6ADYCHCADIAE2AhQgAyAANgIMQQAhAgykAQsgA0EANgIcIAMgATYCFCADQbwKNgIQIANBBzYCDEEAIQIMowELQc8AIQIMiQELQdEAIQIMiAELQecAIQIMhwELIAEgBEYEQEH6ACECDKABCwJAIAEtAABBCWsOBCAAACAACyABQQFqIQFB5gAhAgyGAQsgASAERgRAQfkAIQIMnwELAkAgAS0AAEEJaw4EHwAAHwALQQAhAAJAIAMoAjgiAkUNACACKAI4IgJFDQAgAyACEQAAIQALIABFBEBB4gEhAgyGAQsgAEEVRwRAIANBADYCHCADIAE2AhQgA0HJDTYCECADQRo2AgxBACECDJ8BCyADQfgANgIcIAMgATYCFCADQeoaNgIQIANBFTYCDEEAIQIMngELIAEgBEcEQCADQQ02AgggAyABNgIEQeQAIQIMhQELQfcAIQIMnQELIAEgBEYEQEH2ACECDJ0BCwJAAkACQCABLQAAQcgAaw4LAAELCwsLCwsLCwILCyABQQFqIQFB3QAhAgyFAQsgAUEBaiEBQeAAIQIMhAELIAFBAWohAUHjACECDIMBC0H1ACECIAEgBEYNmwEgAygCACIAIAQgAWtqIQUgASAAa0ECaiEGAkADQCABLQAAIABBtdUAai0AAEcNCCAAQQJGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAMnAELIAMoAgQhACADQgA3AwAgAyAAIAZBAWoiARArIgAEQCADQfQANgIcIAMgATYCFCADIAA2AgxBACECDJwBC0HiACECDIIBC0EAIQACQCADKAI4IgJFDQAgAigCNCICRQ0AIAMgAhEAACEACwJAIAAEQCAAQRVGDQEgA0EANgIcIAMgATYCFCADQeoNNgIQIANBJjYCDEEAIQIMnAELQeEAIQIMggELIANB8wA2AhwgAyABNgIUIANBgBs2AhAgA0EVNgIMQQAhAgyaAQsgAy0AKSIAQSNrQQtJDQkCQCAAQQZLDQBBASAAdEHKAHFFDQAMCgtBACECIANBADYCHCADIAE2AhQgA0HtCTYCECADQQg2AgwMmQELQfIAIQIgASAERg2YASADKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEGz1QBqLQAARw0FIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAyZAQsgAygCBCEAIANCADcDACADIAAgBkEBaiIBECsiAARAIANB8QA2AhwgAyABNgIUIAMgADYCDEEAIQIMmQELQd8AIQIMfwtBACEAAkAgAygCOCICRQ0AIAIoAjQiAkUNACADIAIRAAAhAAsCQCAABEAgAEEVRg0BIANBADYCHCADIAE2AhQgA0HqDTYCECADQSY2AgxBACECDJkBC0HeACECDH8LIANB8AA2AhwgAyABNgIUIANBgBs2AhAgA0EVNgIMQQAhAgyXAQsgAy0AKUEhRg0GIANBADYCHCADIAE2AhQgA0GRCjYCECADQQg2AgxBACECDJYBC0HvACECIAEgBEYNlQEgAygCACIAIAQgAWtqIQUgASAAa0ECaiEGAkADQCABLQAAIABBsNUAai0AAEcNAiAAQQJGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAMlgELIAMoAgQhACADQgA3AwAgAyAAIAZBAWoiARArIgBFDQIgA0HtADYCHCADIAE2AhQgAyAANgIMQQAhAgyVAQsgA0EANgIACyADKAIEIQAgA0EANgIEIAMgACABECsiAEUNgAEgA0HuADYCHCADIAE2AhQgAyAANgIMQQAhAgyTAQtB3AAhAgx5C0EAIQACQCADKAI4IgJFDQAgAigCNCICRQ0AIAMgAhEAACEACwJAIAAEQCAAQRVGDQEgA0EANgIcIAMgATYCFCADQeoNNgIQIANBJjYCDEEAIQIMkwELQdsAIQIMeQsgA0HsADYCHCADIAE2AhQgA0GAGzYCECADQRU2AgxBACECDJEBCyADLQApIgBBI0kNACAAQS5GDQAgA0EANgIcIAMgATYCFCADQckJNgIQIANBCDYCDEEAIQIMkAELQdoAIQIMdgsgASAERgRAQesAIQIMjwELAkAgAS0AAEEvRgRAIAFBAWohAQwBCyADQQA2AhwgAyABNgIUIANBsjg2AhAgA0EINgIMQQAhAgyPAQtB2QAhAgx1CyABIARHBEAgA0EONgIIIAMgATYCBEHYACECDHULQeoAIQIMjQELIAEgBEYEQEHpACECDI0BCyABLQAAQTBrIgBB/wFxQQpJBEAgAyAAOgAqIAFBAWohAUHXACECDHQLIAMoAgQhACADQQA2AgQgAyAAIAEQLyIARQ16IANB6AA2AhwgAyABNgIUIAMgADYCDEEAIQIMjAELIAEgBEYEQEHnACECDIwBCwJAIAEtAABBLkYEQCABQQFqIQEMAQsgAygCBCEAIANBADYCBCADIAAgARAvIgBFDXsgA0HmADYCHCADIAE2AhQgAyAANgIMQQAhAgyMAQtB1gAhAgxyCyABIARGBEBB5QAhAgyLAQtBACEAQQEhBUEBIQdBACECAkACQAJAAkACQAJ/AkACQAJAAkACQAJAAkAgAS0AAEEwaw4KCgkAAQIDBAUGCAsLQQIMBgtBAwwFC0EEDAQLQQUMAwtBBgwCC0EHDAELQQgLIQJBACEFQQAhBwwCC0EJIQJBASEAQQAhBUEAIQcMAQtBACEFQQEhAgsgAyACOgArIAFBAWohAQJAAkAgAy0ALkEQcQ0AAkACQAJAIAMtACoOAwEAAgQLIAdFDQMMAgsgAA0BDAILIAVFDQELIAMoAgQhACADQQA2AgQgAyAAIAEQLyIARQ0CIANB4gA2AhwgAyABNgIUIAMgADYCDEEAIQIMjQELIAMoAgQhACADQQA2AgQgAyAAIAEQLyIARQ19IANB4wA2AhwgAyABNgIUIAMgADYCDEEAIQIMjAELIAMoAgQhACADQQA2AgQgAyAAIAEQLyIARQ17IANB5AA2AhwgAyABNgIUIAMgADYCDAyLAQtB1AAhAgxxCyADLQApQSJGDYYBQdMAIQIMcAtBACEAAkAgAygCOCICRQ0AIAIoAkQiAkUNACADIAIRAAAhAAsgAEUEQEHVACECDHALIABBFUcEQCADQQA2AhwgAyABNgIUIANBpA02AhAgA0EhNgIMQQAhAgyJAQsgA0HhADYCHCADIAE2AhQgA0HQGjYCECADQRU2AgxBACECDIgBCyABIARGBEBB4AAhAgyIAQsCQAJAAkACQAJAIAEtAABBCmsOBAEEBAAECyABQQFqIQEMAQsgAUEBaiEBIANBL2otAABBAXFFDQELQdIAIQIMcAsgA0EANgIcIAMgATYCFCADQbYRNgIQIANBCTYCDEEAIQIMiAELIANBADYCHCADIAE2AhQgA0G2ETYCECADQQk2AgxBACECDIcBCyABIARGBEBB3wAhAgyHAQsgAS0AAEEKRgRAIAFBAWohAQwJCyADLQAuQcAAcQ0IIANBADYCHCADIAE2AhQgA0G2ETYCECADQQI2AgxBACECDIYBCyABIARGBEBB3QAhAgyGAQsgAS0AACICQQ1GBEAgAUEBaiEBQdAAIQIMbQsgASEAIAJBCWsOBAUBAQUBCyAEIAEiAEYEQEHcACECDIUBCyAALQAAQQpHDQAgAEEBagwCC0EAIQIgA0EANgIcIAMgADYCFCADQcotNgIQIANBBzYCDAyDAQsgASAERgRAQdsAIQIMgwELAkAgAS0AAEEJaw4EAwAAAwALIAFBAWoLIQFBzgAhAgxoCyABIARGBEBB2gAhAgyBAQsgAS0AAEEJaw4EAAEBAAELQQAhAiADQQA2AhwgA0GaEjYCECADQQc2AgwgAyABQQFqNgIUDH8LIANBgBI7ASpBACEAAkAgAygCOCICRQ0AIAIoAjgiAkUNACADIAIRAAAhAAsgAEUNACAAQRVHDQEgA0HZADYCHCADIAE2AhQgA0HqGjYCECADQRU2AgxBACECDH4LQc0AIQIMZAsgA0EANgIcIAMgATYCFCADQckNNgIQIANBGjYCDEEAIQIMfAsgASAERgRAQdkAIQIMfAsgAS0AAEEgRw09IAFBAWohASADLQAuQQFxDT0gA0EANgIcIAMgATYCFCADQcIcNgIQIANBHjYCDEEAIQIMewsgASAERgRAQdgAIQIMewsCQAJAAkACQAJAIAEtAAAiAEEKaw4EAgMDAAELIAFBAWohAUEsIQIMZQsgAEE6Rw0BIANBADYCHCADIAE2AhQgA0HnETYCECADQQo2AgxBACECDH0LIAFBAWohASADQS9qLQAAQQFxRQ1zIAMtADJBgAFxRQRAIANBMmohAiADEDVBACEAAkAgAygCOCIGRQ0AIAYoAigiBkUNACADIAYRAAAhAAsCQAJAIAAOFk1MSwEBAQEBAQEBAQEBAQEBAQEBAQABCyADQSk2AhwgAyABNgIUIANBrBk2AhAgA0EVNgIMQQAhAgx+CyADQQA2AhwgAyABNgIUIANB5Qs2AhAgA0ERNgIMQQAhAgx9C0EAIQACQCADKAI4IgJFDQAgAigCXCICRQ0AIAMgAhEAACEACyAARQ1ZIABBFUcNASADQQU2AhwgAyABNgIUIANBmxs2AhAgA0EVNgIMQQAhAgx8C0HLACECDGILQQAhAiADQQA2AhwgAyABNgIUIANBkA42AhAgA0EUNgIMDHoLIAMgAy8BMkGAAXI7ATIMOwsgASAERwRAIANBETYCCCADIAE2AgRBygAhAgxgC0HXACECDHgLIAEgBEYEQEHWACECDHgLAkACQAJAAkAgAS0AACIAQSByIAAgAEHBAGtB/wFxQRpJG0H/AXFB4wBrDhMAQEBAQEBAQEBAQEBAAUBAQAIDQAsgAUEBaiEBQcYAIQIMYQsgAUEBaiEBQccAIQIMYAsgAUEBaiEBQcgAIQIMXwsgAUEBaiEBQckAIQIMXgtB1QAhAiAEIAEiAEYNdiAEIAFrIAMoAgAiAWohBiAAIAFrQQVqIQcDQCABQZDIAGotAAAgAC0AACIFQSByIAUgBUHBAGtB/wFxQRpJG0H/AXFHDQhBBCABQQVGDQoaIAFBAWohASAEIABBAWoiAEcNAAsgAyAGNgIADHYLQdQAIQIgBCABIgBGDXUgBCABayADKAIAIgFqIQYgACABa0EPaiEHA0AgAUGAyABqLQAAIAAtAAAiBUEgciAFIAVBwQBrQf8BcUEaSRtB/wFxRw0HQQMgAUEPRg0JGiABQQFqIQEgBCAAQQFqIgBHDQALIAMgBjYCAAx1C0HTACECIAQgASIARg10IAQgAWsgAygCACIBaiEGIAAgAWtBDmohBwNAIAFB4scAai0AACAALQAAIgVBIHIgBSAFQcEAa0H/AXFBGkkbQf8BcUcNBiABQQ5GDQcgAUEBaiEBIAQgAEEBaiIARw0ACyADIAY2AgAMdAtB0gAhAiAEIAEiAEYNcyAEIAFrIAMoAgAiAWohBSAAIAFrQQFqIQYDQCABQeDHAGotAAAgAC0AACIHQSByIAcgB0HBAGtB/wFxQRpJG0H/AXFHDQUgAUEBRg0CIAFBAWohASAEIABBAWoiAEcNAAsgAyAFNgIADHMLIAEgBEYEQEHRACECDHMLAkACQCABLQAAIgBBIHIgACAAQcEAa0H/AXFBGkkbQf8BcUHuAGsOBwA5OTk5OQE5CyABQQFqIQFBwwAhAgxaCyABQQFqIQFBxAAhAgxZCyADQQA2AgAgBkEBaiEBQcUAIQIMWAtB0AAhAiAEIAEiAEYNcCAEIAFrIAMoAgAiAWohBiAAIAFrQQlqIQcDQCABQdbHAGotAAAgAC0AACIFQSByIAUgBUHBAGtB/wFxQRpJG0H/AXFHDQJBAiABQQlGDQQaIAFBAWohASAEIABBAWoiAEcNAAsgAyAGNgIADHALQc8AIQIgBCABIgBGDW8gBCABayADKAIAIgFqIQYgACABa0EFaiEHA0AgAUHQxwBqLQAAIAAtAAAiBUEgciAFIAVBwQBrQf8BcUEaSRtB/wFxRw0BIAFBBUYNAiABQQFqIQEgBCAAQQFqIgBHDQALIAMgBjYCAAxvCyAAIQEgA0EANgIADDMLQQELOgAsIANBADYCACAHQQFqIQELQS0hAgxSCwJAA0AgAS0AAEHQxQBqLQAAQQFHDQEgBCABQQFqIgFHDQALQc0AIQIMawtBwgAhAgxRCyABIARGBEBBzAAhAgxqCyABLQAAQTpGBEAgAygCBCEAIANBADYCBCADIAAgARAwIgBFDTMgA0HLADYCHCADIAA2AgwgAyABQQFqNgIUQQAhAgxqCyADQQA2AhwgAyABNgIUIANB5xE2AhAgA0EKNgIMQQAhAgxpCwJAAkAgAy0ALEECaw4CAAEnCyADQTNqLQAAQQJxRQ0mIAMtAC5BAnENJiADQQA2AhwgAyABNgIUIANBphQ2AhAgA0ELNgIMQQAhAgxpCyADLQAyQSBxRQ0lIAMtAC5BAnENJSADQQA2AhwgAyABNgIUIANBvRM2AhAgA0EPNgIMQQAhAgxoC0EAIQACQCADKAI4IgJFDQAgAigCSCICRQ0AIAMgAhEAACEACyAARQRAQcEAIQIMTwsgAEEVRwRAIANBADYCHCADIAE2AhQgA0GmDzYCECADQRw2AgxBACECDGgLIANBygA2AhwgAyABNgIUIANBhRw2AhAgA0EVNgIMQQAhAgxnCyABIARHBEAgASECA0AgBCACIgFrQRBOBEAgAUEQaiEC/Qz/////////////////////IAH9AAAAIg1BB/1sIA39DODg4ODg4ODg4ODg4ODg4OD9bv0MX19fX19fX19fX19fX19fX/0mIA39DAkJCQkJCQkJCQkJCQkJCQn9I/1Q/VL9ZEF/c2giAEEQRg0BIAAgAWohAQwYCyABIARGBEBBxAAhAgxpCyABLQAAQcDBAGotAABBAUcNFyAEIAFBAWoiAkcNAAtBxAAhAgxnC0HEACECDGYLIAEgBEcEQANAAkAgAS0AACIAQSByIAAgAEHBAGtB/wFxQRpJG0H/AXEiAEEJRg0AIABBIEYNAAJAAkACQAJAIABB4wBrDhMAAwMDAwMDAwEDAwMDAwMDAwMCAwsgAUEBaiEBQTYhAgxSCyABQQFqIQFBNyECDFELIAFBAWohAUE4IQIMUAsMFQsgBCABQQFqIgFHDQALQTwhAgxmC0E8IQIMZQsgASAERgRAQcgAIQIMZQsgA0ESNgIIIAMgATYCBAJAAkACQAJAAkAgAy0ALEEBaw4EFAABAgkLIAMtADJBIHENA0HgASECDE8LAkAgAy8BMiIAQQhxRQ0AIAMtAChBAUcNACADLQAuQQhxRQ0CCyADIABB9/sDcUGABHI7ATIMCwsgAyADLwEyQRByOwEyDAQLIANBADYCBCADIAEgARAxIgAEQCADQcEANgIcIAMgADYCDCADIAFBAWo2AhRBACECDGYLIAFBAWohAQxYCyADQQA2AhwgAyABNgIUIANB9BM2AhAgA0EENgIMQQAhAgxkC0HHACECIAEgBEYNYyADKAIAIgAgBCABa2ohBSABIABrQQZqIQYCQANAIABBwMUAai0AACABLQAAQSByRw0BIABBBkYNSiAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAxkCyADQQA2AgAMBQsCQCABIARHBEADQCABLQAAQcDDAGotAAAiAEEBRwRAIABBAkcNAyABQQFqIQEMBQsgBCABQQFqIgFHDQALQcUAIQIMZAtBxQAhAgxjCwsgA0EAOgAsDAELQQshAgxHC0E/IQIMRgsCQAJAA0AgAS0AACIAQSBHBEACQCAAQQprDgQDBQUDAAsgAEEsRg0DDAQLIAQgAUEBaiIBRw0AC0HGACECDGALIANBCDoALAwOCyADLQAoQQFHDQIgAy0ALkEIcQ0CIAMoAgQhACADQQA2AgQgAyAAIAEQMSIABEAgA0HCADYCHCADIAA2AgwgAyABQQFqNgIUQQAhAgxfCyABQQFqIQEMUAtBOyECDEQLAkADQCABLQAAIgBBIEcgAEEJR3ENASAEIAFBAWoiAUcNAAtBwwAhAgxdCwtBPCECDEILAkACQCABIARHBEADQCABLQAAIgBBIEcEQCAAQQprDgQDBAQDBAsgBCABQQFqIgFHDQALQT8hAgxdC0E/IQIMXAsgAyADLwEyQSByOwEyDAoLIAMoAgQhACADQQA2AgQgAyAAIAEQMSIARQ1OIANBPjYCHCADIAE2AhQgAyAANgIMQQAhAgxaCwJAIAEgBEcEQANAIAEtAABBwMMAai0AACIAQQFHBEAgAEECRg0DDAwLIAQgAUEBaiIBRw0AC0E3IQIMWwtBNyECDFoLIAFBAWohAQwEC0E7IQIgBCABIgBGDVggBCABayADKAIAIgFqIQYgACABa0EFaiEHAkADQCABQZDIAGotAAAgAC0AACIFQSByIAUgBUHBAGtB/wFxQRpJG0H/AXFHDQEgAUEFRgRAQQchAQw/CyABQQFqIQEgBCAAQQFqIgBHDQALIAMgBjYCAAxZCyADQQA2AgAgACEBDAULQTohAiAEIAEiAEYNVyAEIAFrIAMoAgAiAWohBiAAIAFrQQhqIQcCQANAIAFBtMEAai0AACAALQAAIgVBIHIgBSAFQcEAa0H/AXFBGkkbQf8BcUcNASABQQhGBEBBBSEBDD4LIAFBAWohASAEIABBAWoiAEcNAAsgAyAGNgIADFgLIANBADYCACAAIQEMBAtBOSECIAQgASIARg1WIAQgAWsgAygCACIBaiEGIAAgAWtBA2ohBwJAA0AgAUGwwQBqLQAAIAAtAAAiBUEgciAFIAVBwQBrQf8BcUEaSRtB/wFxRw0BIAFBA0YEQEEGIQEMPQsgAUEBaiEBIAQgAEEBaiIARw0ACyADIAY2AgAMVwsgA0EANgIAIAAhAQwDCwJAA0AgAS0AACIAQSBHBEAgAEEKaw4EBwQEBwILIAQgAUEBaiIBRw0AC0E4IQIMVgsgAEEsRw0BIAFBAWohAEEBIQECQAJAAkACQAJAIAMtACxBBWsOBAMBAgQACyAAIQEMBAtBAiEBDAELQQQhAQsgA0EBOgAsIAMgAy8BMiABcjsBMiAAIQEMAQsgAyADLwEyQQhyOwEyIAAhAQtBPiECDDsLIANBADoALAtBOSECDDkLIAEgBEYEQEE2IQIMUgsCQAJAAkACQAJAIAEtAABBCmsOBAACAgECCyADKAIEIQAgA0EANgIEIAMgACABEDEiAEUNAiADQTM2AhwgAyABNgIUIAMgADYCDEEAIQIMVQsgAygCBCEAIANBADYCBCADIAAgARAxIgBFBEAgAUEBaiEBDAYLIANBMjYCHCADIAA2AgwgAyABQQFqNgIUQQAhAgxUCyADLQAuQQFxBEBB3wEhAgw7CyADKAIEIQAgA0EANgIEIAMgACABEDEiAA0BDEkLQTQhAgw5CyADQTU2AhwgAyABNgIUIAMgADYCDEEAIQIMUQtBNSECDDcLIANBL2otAABBAXENACADQQA2AhwgAyABNgIUIANB6xY2AhAgA0EZNgIMQQAhAgxPC0EzIQIMNQsgASAERgRAQTIhAgxOCwJAIAEtAABBCkYEQCABQQFqIQEMAQsgA0EANgIcIAMgATYCFCADQZIXNgIQIANBAzYCDEEAIQIMTgtBMiECDDQLIAEgBEYEQEExIQIMTQsCQCABLQAAIgBBCUYNACAAQSBGDQBBASECAkAgAy0ALEEFaw4EBgQFAA0LIAMgAy8BMkEIcjsBMgwMCyADLQAuQQFxRQ0BIAMtACxBCEcNACADQQA6ACwLQT0hAgwyCyADQQA2AhwgAyABNgIUIANBwhY2AhAgA0EKNgIMQQAhAgxKC0ECIQIMAQtBBCECCyADQQE6ACwgAyADLwEyIAJyOwEyDAYLIAEgBEYEQEEwIQIMRwsgAS0AAEEKRgRAIAFBAWohAQwBCyADLQAuQQFxDQAgA0EANgIcIAMgATYCFCADQdwoNgIQIANBAjYCDEEAIQIMRgtBMCECDCwLIAFBAWohAUExIQIMKwsgASAERgRAQS8hAgxECyABLQAAIgBBCUcgAEEgR3FFBEAgAUEBaiEBIAMtAC5BAXENASADQQA2AhwgAyABNgIUIANBlxA2AhAgA0EKNgIMQQAhAgxEC0EBIQICQAJAAkACQAJAAkAgAy0ALEECaw4HBQQEAwECAAQLIAMgAy8BMkEIcjsBMgwDC0ECIQIMAQtBBCECCyADQQE6ACwgAyADLwEyIAJyOwEyC0EvIQIMKwsgA0EANgIcIAMgATYCFCADQYQTNgIQIANBCzYCDEEAIQIMQwtB4QEhAgwpCyABIARGBEBBLiECDEILIANBADYCBCADQRI2AgggAyABIAEQMSIADQELQS4hAgwnCyADQS02AhwgAyABNgIUIAMgADYCDEEAIQIMPwtBACEAAkAgAygCOCICRQ0AIAIoAkwiAkUNACADIAIRAAAhAAsgAEUNACAAQRVHDQEgA0HYADYCHCADIAE2AhQgA0GzGzYCECADQRU2AgxBACECDD4LQcwAIQIMJAsgA0EANgIcIAMgATYCFCADQbMONgIQIANBHTYCDEEAIQIMPAsgASAERgRAQc4AIQIMPAsgAS0AACIAQSBGDQIgAEE6Rg0BCyADQQA6ACxBCSECDCELIAMoAgQhACADQQA2AgQgAyAAIAEQMCIADQEMAgsgAy0ALkEBcQRAQd4BIQIMIAsgAygCBCEAIANBADYCBCADIAAgARAwIgBFDQIgA0EqNgIcIAMgADYCDCADIAFBAWo2AhRBACECDDgLIANBywA2AhwgAyAANgIMIAMgAUEBajYCFEEAIQIMNwsgAUEBaiEBQcAAIQIMHQsgAUEBaiEBDCwLIAEgBEYEQEErIQIMNQsCQCABLQAAQQpGBEAgAUEBaiEBDAELIAMtAC5BwABxRQ0GCyADLQAyQYABcQRAQQAhAAJAIAMoAjgiAkUNACACKAJcIgJFDQAgAyACEQAAIQALIABFDRIgAEEVRgRAIANBBTYCHCADIAE2AhQgA0GbGzYCECADQRU2AgxBACECDDYLIANBADYCHCADIAE2AhQgA0GQDjYCECADQRQ2AgxBACECDDULIANBMmohAiADEDVBACEAAkAgAygCOCIGRQ0AIAYoAigiBkUNACADIAYRAAAhAAsgAA4WAgEABAQEBAQEBAQEBAQEBAQEBAQEAwQLIANBAToAMAsgAiACLwEAQcAAcjsBAAtBKyECDBgLIANBKTYCHCADIAE2AhQgA0GsGTYCECADQRU2AgxBACECDDALIANBADYCHCADIAE2AhQgA0HlCzYCECADQRE2AgxBACECDC8LIANBADYCHCADIAE2AhQgA0GlCzYCECADQQI2AgxBACECDC4LQQEhByADLwEyIgVBCHFFBEAgAykDIEIAUiEHCwJAIAMtADAEQEEBIQAgAy0AKUEFRg0BIAVBwABxRSAHcUUNAQsCQCADLQAoIgJBAkYEQEEBIQAgAy8BNCIGQeUARg0CQQAhACAFQcAAcQ0CIAZB5ABGDQIgBkHmAGtBAkkNAiAGQcwBRg0CIAZBsAJGDQIMAQtBACEAIAVBwABxDQELQQIhACAFQQhxDQAgBUGABHEEQAJAIAJBAUcNACADLQAuQQpxDQBBBSEADAILQQQhAAwBCyAFQSBxRQRAIAMQNkEAR0ECdCEADAELQQBBAyADKQMgUBshAAsgAEEBaw4FAgAHAQMEC0ERIQIMEwsgA0EBOgAxDCkLQQAhAgJAIAMoAjgiAEUNACAAKAIwIgBFDQAgAyAAEQAAIQILIAJFDSYgAkEVRgRAIANBAzYCHCADIAE2AhQgA0HSGzYCECADQRU2AgxBACECDCsLQQAhAiADQQA2AhwgAyABNgIUIANB3Q42AhAgA0ESNgIMDCoLIANBADYCHCADIAE2AhQgA0H5IDYCECADQQ82AgxBACECDCkLQQAhAAJAIAMoAjgiAkUNACACKAIwIgJFDQAgAyACEQAAIQALIAANAQtBDiECDA4LIABBFUYEQCADQQI2AhwgAyABNgIUIANB0hs2AhAgA0EVNgIMQQAhAgwnCyADQQA2AhwgAyABNgIUIANB3Q42AhAgA0ESNgIMQQAhAgwmC0EqIQIMDAsgASAERwRAIANBCTYCCCADIAE2AgRBKSECDAwLQSYhAgwkCyADIAMpAyAiDCAEIAFrrSIKfSILQgAgCyAMWBs3AyAgCiAMVARAQSUhAgwkCyADKAIEIQAgA0EANgIEIAMgACABIAynaiIBEDIiAEUNACADQQU2AhwgAyABNgIUIAMgADYCDEEAIQIMIwtBDyECDAkLQgAhCgJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCABLQAAQTBrDjcXFgABAgMEBQYHFBQUFBQUFAgJCgsMDRQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUDg8QERITFAtCAiEKDBYLQgMhCgwVC0IEIQoMFAtCBSEKDBMLQgYhCgwSC0IHIQoMEQtCCCEKDBALQgkhCgwPC0IKIQoMDgtCCyEKDA0LQgwhCgwMC0INIQoMCwtCDiEKDAoLQg8hCgwJC0IKIQoMCAtCCyEKDAcLQgwhCgwGC0INIQoMBQtCDiEKDAQLQg8hCgwDCyADQQA2AhwgAyABNgIUIANBnxU2AhAgA0EMNgIMQQAhAgwhCyABIARGBEBBIiECDCELQgAhCgJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgAS0AAEEwaw43FRQAAQIDBAUGBxYWFhYWFhYICQoLDA0WFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFg4PEBESExYLQgIhCgwUC0IDIQoMEwtCBCEKDBILQgUhCgwRC0IGIQoMEAtCByEKDA8LQgghCgwOC0IJIQoMDQtCCiEKDAwLQgshCgwLC0IMIQoMCgtCDSEKDAkLQg4hCgwIC0IPIQoMBwtCCiEKDAYLQgshCgwFC0IMIQoMBAtCDSEKDAMLQg4hCgwCC0IPIQoMAQtCASEKCyABQQFqIQEgAykDICILQv//////////D1gEQCADIAtCBIYgCoQ3AyAMAgsgA0EANgIcIAMgATYCFCADQbUJNgIQIANBDDYCDEEAIQIMHgtBJyECDAQLQSghAgwDCyADIAE6ACwgA0EANgIAIAdBAWohAUEMIQIMAgsgA0EANgIAIAZBAWohAUEKIQIMAQsgAUEBaiEBQQghAgwACwALQQAhAiADQQA2AhwgAyABNgIUIANBsjg2AhAgA0EINgIMDBcLQQAhAiADQQA2AhwgAyABNgIUIANBgxE2AhAgA0EJNgIMDBYLQQAhAiADQQA2AhwgAyABNgIUIANB3wo2AhAgA0EJNgIMDBULQQAhAiADQQA2AhwgAyABNgIUIANB7RA2AhAgA0EJNgIMDBQLQQAhAiADQQA2AhwgAyABNgIUIANB0hE2AhAgA0EJNgIMDBMLQQAhAiADQQA2AhwgAyABNgIUIANBsjg2AhAgA0EINgIMDBILQQAhAiADQQA2AhwgAyABNgIUIANBgxE2AhAgA0EJNgIMDBELQQAhAiADQQA2AhwgAyABNgIUIANB3wo2AhAgA0EJNgIMDBALQQAhAiADQQA2AhwgAyABNgIUIANB7RA2AhAgA0EJNgIMDA8LQQAhAiADQQA2AhwgAyABNgIUIANB0hE2AhAgA0EJNgIMDA4LQQAhAiADQQA2AhwgAyABNgIUIANBuRc2AhAgA0EPNgIMDA0LQQAhAiADQQA2AhwgAyABNgIUIANBuRc2AhAgA0EPNgIMDAwLQQAhAiADQQA2AhwgAyABNgIUIANBmRM2AhAgA0ELNgIMDAsLQQAhAiADQQA2AhwgAyABNgIUIANBnQk2AhAgA0ELNgIMDAoLQQAhAiADQQA2AhwgAyABNgIUIANBlxA2AhAgA0EKNgIMDAkLQQAhAiADQQA2AhwgAyABNgIUIANBsRA2AhAgA0EKNgIMDAgLQQAhAiADQQA2AhwgAyABNgIUIANBux02AhAgA0ECNgIMDAcLQQAhAiADQQA2AhwgAyABNgIUIANBlhY2AhAgA0ECNgIMDAYLQQAhAiADQQA2AhwgAyABNgIUIANB+Rg2AhAgA0ECNgIMDAULQQAhAiADQQA2AhwgAyABNgIUIANBxBg2AhAgA0ECNgIMDAQLIANBAjYCHCADIAE2AhQgA0GpHjYCECADQRY2AgxBACECDAMLQd4AIQIgASAERg0CIAlBCGohByADKAIAIQUCQAJAIAEgBEcEQCAFQZbIAGohCCAEIAVqIAFrIQYgBUF/c0EKaiIFIAFqIQADQCABLQAAIAgtAABHBEBBAiEIDAMLIAVFBEBBACEIIAAhAQwDCyAFQQFrIQUgCEEBaiEIIAQgAUEBaiIBRw0ACyAGIQUgBCEBCyAHQQE2AgAgAyAFNgIADAELIANBADYCACAHIAg2AgALIAcgATYCBCAJKAIMIQACQAJAIAkoAghBAWsOAgQBAAsgA0EANgIcIANBwh42AhAgA0EXNgIMIAMgAEEBajYCFEEAIQIMAwsgA0EANgIcIAMgADYCFCADQdceNgIQIANBCTYCDEEAIQIMAgsgASAERgRAQSghAgwCCyADQQk2AgggAyABNgIEQSchAgwBCyABIARGBEBBASECDAELA0ACQAJAAkAgAS0AAEEKaw4EAAEBAAELIAFBAWohAQwBCyABQQFqIQEgAy0ALkEgcQ0AQQAhAiADQQA2AhwgAyABNgIUIANBoSE2AhAgA0EFNgIMDAILQQEhAiABIARHDQALCyAJQRBqJAAgAkUEQCADKAIMIQAMAQsgAyACNgIcQQAhACADKAIEIgFFDQAgAyABIAQgAygCCBEBACIBRQ0AIAMgBDYCFCADIAE2AgwgASEACyAAC74CAQJ/IABBADoAACAAQeQAaiIBQQFrQQA6AAAgAEEAOgACIABBADoAASABQQNrQQA6AAAgAUECa0EAOgAAIABBADoAAyABQQRrQQA6AABBACAAa0EDcSIBIABqIgBBADYCAEHkACABa0F8cSICIABqIgFBBGtBADYCAAJAIAJBCUkNACAAQQA2AgggAEEANgIEIAFBCGtBADYCACABQQxrQQA2AgAgAkEZSQ0AIABBADYCGCAAQQA2AhQgAEEANgIQIABBADYCDCABQRBrQQA2AgAgAUEUa0EANgIAIAFBGGtBADYCACABQRxrQQA2AgAgAiAAQQRxQRhyIgJrIgFBIEkNACAAIAJqIQADQCAAQgA3AxggAEIANwMQIABCADcDCCAAQgA3AwAgAEEgaiEAIAFBIGsiAUEfSw0ACwsLVgEBfwJAIAAoAgwNAAJAAkACQAJAIAAtADEOAwEAAwILIAAoAjgiAUUNACABKAIwIgFFDQAgACABEQAAIgENAwtBAA8LAAsgAEHKGTYCEEEOIQELIAELGgAgACgCDEUEQCAAQd4fNgIQIABBFTYCDAsLFAAgACgCDEEVRgRAIABBADYCDAsLFAAgACgCDEEWRgRAIABBADYCDAsLBwAgACgCDAsHACAAKAIQCwkAIAAgATYCEAsHACAAKAIUCysAAkAgAEEnTw0AQv//////CSAArYhCAYNQDQAgAEECdEHQOGooAgAPCwALFwAgAEEvTwRAAAsgAEECdEHsOWooAgALvwkBAX9B9C0hAQJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIABB5ABrDvQDY2IAAWFhYWFhYQIDBAVhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhBgcICQoLDA0OD2FhYWFhEGFhYWFhYWFhYWFhEWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYRITFBUWFxgZGhthYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhHB0eHyAhIiMkJSYnKCkqKywtLi8wMTIzNDU2YTc4OTphYWFhYWFhYTthYWE8YWFhYT0+P2FhYWFhYWFhQGFhQWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYUJDREVGR0hJSktMTU5PUFFSU2FhYWFhYWFhVFVWV1hZWlthXF1hYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFeYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhX2BhC0HqLA8LQZgmDwtB7TEPC0GgNw8LQckpDwtBtCkPC0GWLQ8LQesrDwtBojUPC0HbNA8LQeApDwtB4yQPC0HVJA8LQe4kDwtB5iUPC0HKNA8LQdA3DwtBqjUPC0H1LA8LQfYmDwtBgiIPC0HyMw8LQb4oDwtB5zcPC0HNIQ8LQcAhDwtBuCUPC0HLJQ8LQZYkDwtBjzQPC0HNNQ8LQd0qDwtB7jMPC0GcNA8LQZ4xDwtB9DUPC0HlIg8LQa8lDwtBmTEPC0GyNg8LQfk2DwtBxDIPC0HdLA8LQYIxDwtBwTEPC0GNNw8LQckkDwtB7DYPC0HnKg8LQcgjDwtB4iEPC0HJNw8LQaUiDwtBlCIPC0HbNg8LQd41DwtBhiYPC0G8Kw8LQYsyDwtBoCMPC0H2MA8LQYAsDwtBiSsPC0GkJg8LQfIjDwtBgSgPC0GrMg8LQesnDwtBwjYPC0GiJA8LQc8qDwtB3CMPC0GHJw8LQeQ0DwtBtyIPC0GtMQ8LQdUiDwtBrzQPC0HeJg8LQdYyDwtB9DQPC0GBOA8LQfQ3DwtBkjYPC0GdJw8LQYIpDwtBjSMPC0HXMQ8LQb01DwtBtDcPC0HYMA8LQbYnDwtBmjgPC0GnKg8LQcQnDwtBriMPC0H1Ig8LAAtByiYhAQsgAQsXACAAIAAvAS5B/v8DcSABQQBHcjsBLgsaACAAIAAvAS5B/f8DcSABQQBHQQF0cjsBLgsaACAAIAAvAS5B+/8DcSABQQBHQQJ0cjsBLgsaACAAIAAvAS5B9/8DcSABQQBHQQN0cjsBLgsaACAAIAAvAS5B7/8DcSABQQBHQQR0cjsBLgsaACAAIAAvAS5B3/8DcSABQQBHQQV0cjsBLgsaACAAIAAvAS5Bv/8DcSABQQBHQQZ0cjsBLgsaACAAIAAvAS5B//4DcSABQQBHQQd0cjsBLgsaACAAIAAvAS5B//0DcSABQQBHQQh0cjsBLgsaACAAIAAvAS5B//sDcSABQQBHQQl0cjsBLgs+AQJ/AkAgACgCOCIDRQ0AIAMoAgQiA0UNACAAIAEgAiABayADEQEAIgRBf0cNACAAQeESNgIQQRghBAsgBAs+AQJ/AkAgACgCOCIDRQ0AIAMoAggiA0UNACAAIAEgAiABayADEQEAIgRBf0cNACAAQfwRNgIQQRghBAsgBAs+AQJ/AkAgACgCOCIDRQ0AIAMoAgwiA0UNACAAIAEgAiABayADEQEAIgRBf0cNACAAQewKNgIQQRghBAsgBAs+AQJ/AkAgACgCOCIDRQ0AIAMoAhAiA0UNACAAIAEgAiABayADEQEAIgRBf0cNACAAQfoeNgIQQRghBAsgBAs+AQJ/AkAgACgCOCIDRQ0AIAMoAhQiA0UNACAAIAEgAiABayADEQEAIgRBf0cNACAAQcsQNgIQQRghBAsgBAs+AQJ/AkAgACgCOCIDRQ0AIAMoAhgiA0UNACAAIAEgAiABayADEQEAIgRBf0cNACAAQbcfNgIQQRghBAsgBAs+AQJ/AkAgACgCOCIDRQ0AIAMoAhwiA0UNACAAIAEgAiABayADEQEAIgRBf0cNACAAQb8VNgIQQRghBAsgBAs+AQJ/AkAgACgCOCIDRQ0AIAMoAiwiA0UNACAAIAEgAiABayADEQEAIgRBf0cNACAAQf4INgIQQRghBAsgBAs+AQJ/AkAgACgCOCIDRQ0AIAMoAiAiA0UNACAAIAEgAiABayADEQEAIgRBf0cNACAAQYwdNgIQQRghBAsgBAs+AQJ/AkAgACgCOCIDRQ0AIAMoAiQiA0UNACAAIAEgAiABayADEQEAIgRBf0cNACAAQeYVNgIQQRghBAsgBAs4ACAAAn8gAC8BMkEUcUEURgRAQQEgAC0AKEEBRg0BGiAALwE0QeUARgwBCyAALQApQQVGCzoAMAtZAQJ/AkAgAC0AKEEBRg0AIAAvATQiAUHkAGtB5ABJDQAgAUHMAUYNACABQbACRg0AIAAvATIiAEHAAHENAEEBIQIgAEGIBHFBgARGDQAgAEEocUUhAgsgAguMAQECfwJAAkACQCAALQAqRQ0AIAAtACtFDQAgAC8BMiIBQQJxRQ0BDAILIAAvATIiAUEBcUUNAQtBASECIAAtAChBAUYNACAALwE0IgBB5ABrQeQASQ0AIABBzAFGDQAgAEGwAkYNACABQcAAcQ0AQQAhAiABQYgEcUGABEYNACABQShxQQBHIQILIAILcwAgAEEQav0MAAAAAAAAAAAAAAAAAAAAAP0LAwAgAP0MAAAAAAAAAAAAAAAAAAAAAP0LAwAgAEEwav0MAAAAAAAAAAAAAAAAAAAAAP0LAwAgAEEgav0MAAAAAAAAAAAAAAAAAAAAAP0LAwAgAEH9ATYCHAsGACAAEDoLmi0BC38jAEEQayIKJABB3NUAKAIAIglFBEBBnNkAKAIAIgVFBEBBqNkAQn83AgBBoNkAQoCAhICAgMAANwIAQZzZACAKQQhqQXBxQdiq1aoFcyIFNgIAQbDZAEEANgIAQYDZAEEANgIAC0GE2QBBwNkENgIAQdTVAEHA2QQ2AgBB6NUAIAU2AgBB5NUAQX82AgBBiNkAQcCmAzYCAANAIAFBgNYAaiABQfTVAGoiAjYCACACIAFB7NUAaiIDNgIAIAFB+NUAaiADNgIAIAFBiNYAaiABQfzVAGoiAzYCACADIAI2AgAgAUGQ1gBqIAFBhNYAaiICNgIAIAIgAzYCACABQYzWAGogAjYCACABQSBqIgFBgAJHDQALQczZBEGBpgM2AgBB4NUAQazZACgCADYCAEHQ1QBBgKYDNgIAQdzVAEHI2QQ2AgBBzP8HQTg2AgBByNkEIQkLAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgAEHsAU0EQEHE1QAoAgAiBkEQIABBE2pBcHEgAEELSRsiBEEDdiIAdiIBQQNxBEACQCABQQFxIAByQQFzIgJBA3QiAEHs1QBqIgEgAEH01QBqKAIAIgAoAggiA0YEQEHE1QAgBkF+IAJ3cTYCAAwBCyABIAM2AgggAyABNgIMCyAAQQhqIQEgACACQQN0IgJBA3I2AgQgACACaiIAIAAoAgRBAXI2AgQMEQtBzNUAKAIAIgggBE8NASABBEACQEECIAB0IgJBACACa3IgASAAdHFoIgBBA3QiAkHs1QBqIgEgAkH01QBqKAIAIgIoAggiA0YEQEHE1QAgBkF+IAB3cSIGNgIADAELIAEgAzYCCCADIAE2AgwLIAIgBEEDcjYCBCAAQQN0IgAgBGshBSAAIAJqIAU2AgAgAiAEaiIEIAVBAXI2AgQgCARAIAhBeHFB7NUAaiEAQdjVACgCACEDAn9BASAIQQN2dCIBIAZxRQRAQcTVACABIAZyNgIAIAAMAQsgACgCCAsiASADNgIMIAAgAzYCCCADIAA2AgwgAyABNgIICyACQQhqIQFB2NUAIAQ2AgBBzNUAIAU2AgAMEQtByNUAKAIAIgtFDQEgC2hBAnRB9NcAaigCACIAKAIEQXhxIARrIQUgACECA0ACQCACKAIQIgFFBEAgAkEUaigCACIBRQ0BCyABKAIEQXhxIARrIgMgBUkhAiADIAUgAhshBSABIAAgAhshACABIQIMAQsLIAAoAhghCSAAKAIMIgMgAEcEQEHU1QAoAgAaIAMgACgCCCIBNgIIIAEgAzYCDAwQCyAAQRRqIgIoAgAiAUUEQCAAKAIQIgFFDQMgAEEQaiECCwNAIAIhByABIgNBFGoiAigCACIBDQAgA0EQaiECIAMoAhAiAQ0ACyAHQQA2AgAMDwtBfyEEIABBv39LDQAgAEETaiIBQXBxIQRByNUAKAIAIghFDQBBACAEayEFAkACQAJAAn9BACAEQYACSQ0AGkEfIARB////B0sNABogBEEmIAFBCHZnIgBrdkEBcSAAQQF0a0E+agsiBkECdEH01wBqKAIAIgJFBEBBACEBQQAhAwwBC0EAIQEgBEEZIAZBAXZrQQAgBkEfRxt0IQBBACEDA0ACQCACKAIEQXhxIARrIgcgBU8NACACIQMgByIFDQBBACEFIAIhAQwDCyABIAJBFGooAgAiByAHIAIgAEEddkEEcWpBEGooAgAiAkYbIAEgBxshASAAQQF0IQAgAg0ACwsgASADckUEQEEAIQNBAiAGdCIAQQAgAGtyIAhxIgBFDQMgAGhBAnRB9NcAaigCACEBCyABRQ0BCwNAIAEoAgRBeHEgBGsiAiAFSSEAIAIgBSAAGyEFIAEgAyAAGyEDIAEoAhAiAAR/IAAFIAFBFGooAgALIgENAAsLIANFDQAgBUHM1QAoAgAgBGtPDQAgAygCGCEHIAMgAygCDCIARwRAQdTVACgCABogACADKAIIIgE2AgggASAANgIMDA4LIANBFGoiAigCACIBRQRAIAMoAhAiAUUNAyADQRBqIQILA0AgAiEGIAEiAEEUaiICKAIAIgENACAAQRBqIQIgACgCECIBDQALIAZBADYCAAwNC0HM1QAoAgAiAyAETwRAQdjVACgCACEBAkAgAyAEayICQRBPBEAgASAEaiIAIAJBAXI2AgQgASADaiACNgIAIAEgBEEDcjYCBAwBCyABIANBA3I2AgQgASADaiIAIAAoAgRBAXI2AgRBACEAQQAhAgtBzNUAIAI2AgBB2NUAIAA2AgAgAUEIaiEBDA8LQdDVACgCACIDIARLBEAgBCAJaiIAIAMgBGsiAUEBcjYCBEHc1QAgADYCAEHQ1QAgATYCACAJIARBA3I2AgQgCUEIaiEBDA8LQQAhASAEAn9BnNkAKAIABEBBpNkAKAIADAELQajZAEJ/NwIAQaDZAEKAgISAgIDAADcCAEGc2QAgCkEMakFwcUHYqtWqBXM2AgBBsNkAQQA2AgBBgNkAQQA2AgBBgIAECyIAIARBxwBqIgVqIgZBACAAayIHcSICTwRAQbTZAEEwNgIADA8LAkBB/NgAKAIAIgFFDQBB9NgAKAIAIgggAmohACAAIAFNIAAgCEtxDQBBACEBQbTZAEEwNgIADA8LQYDZAC0AAEEEcQ0EAkACQCAJBEBBhNkAIQEDQCABKAIAIgAgCU0EQCAAIAEoAgRqIAlLDQMLIAEoAggiAQ0ACwtBABA7IgBBf0YNBSACIQZBoNkAKAIAIgFBAWsiAyAAcQRAIAIgAGsgACADakEAIAFrcWohBgsgBCAGTw0FIAZB/v///wdLDQVB/NgAKAIAIgMEQEH02AAoAgAiByAGaiEBIAEgB00NBiABIANLDQYLIAYQOyIBIABHDQEMBwsgBiADayAHcSIGQf7///8HSw0EIAYQOyEAIAAgASgCACABKAIEakYNAyAAIQELAkAgBiAEQcgAak8NACABQX9GDQBBpNkAKAIAIgAgBSAGa2pBACAAa3EiAEH+////B0sEQCABIQAMBwsgABA7QX9HBEAgACAGaiEGIAEhAAwHC0EAIAZrEDsaDAQLIAEiAEF/Rw0FDAMLQQAhAwwMC0EAIQAMCgsgAEF/Rw0CC0GA2QBBgNkAKAIAQQRyNgIACyACQf7///8HSw0BIAIQOyEAQQAQOyEBIABBf0YNASABQX9GDQEgACABTw0BIAEgAGsiBiAEQThqTQ0BC0H02ABB9NgAKAIAIAZqIgE2AgBB+NgAKAIAIAFJBEBB+NgAIAE2AgALAkACQAJAQdzVACgCACICBEBBhNkAIQEDQCAAIAEoAgAiAyABKAIEIgVqRg0CIAEoAggiAQ0ACwwCC0HU1QAoAgAiAUEARyAAIAFPcUUEQEHU1QAgADYCAAtBACEBQYjZACAGNgIAQYTZACAANgIAQeTVAEF/NgIAQejVAEGc2QAoAgA2AgBBkNkAQQA2AgADQCABQYDWAGogAUH01QBqIgI2AgAgAiABQezVAGoiAzYCACABQfjVAGogAzYCACABQYjWAGogAUH81QBqIgM2AgAgAyACNgIAIAFBkNYAaiABQYTWAGoiAjYCACACIAM2AgAgAUGM1gBqIAI2AgAgAUEgaiIBQYACRw0AC0F4IABrQQ9xIgEgAGoiAiAGQThrIgMgAWsiAUEBcjYCBEHg1QBBrNkAKAIANgIAQdDVACABNgIAQdzVACACNgIAIAAgA2pBODYCBAwCCyAAIAJNDQAgAiADSQ0AIAEoAgxBCHENAEF4IAJrQQ9xIgAgAmoiA0HQ1QAoAgAgBmoiByAAayIAQQFyNgIEIAEgBSAGajYCBEHg1QBBrNkAKAIANgIAQdDVACAANgIAQdzVACADNgIAIAIgB2pBODYCBAwBCyAAQdTVACgCAEkEQEHU1QAgADYCAAsgACAGaiEDQYTZACEBAkACQAJAA0AgAyABKAIARwRAIAEoAggiAQ0BDAILCyABLQAMQQhxRQ0BC0GE2QAhAQNAIAEoAgAiAyACTQRAIAMgASgCBGoiBSACSw0DCyABKAIIIQEMAAsACyABIAA2AgAgASABKAIEIAZqNgIEIABBeCAAa0EPcWoiCSAEQQNyNgIEIANBeCADa0EPcWoiBiAEIAlqIgRrIQEgAiAGRgRAQdzVACAENgIAQdDVAEHQ1QAoAgAgAWoiADYCACAEIABBAXI2AgQMCAtB2NUAKAIAIAZGBEBB2NUAIAQ2AgBBzNUAQczVACgCACABaiIANgIAIAQgAEEBcjYCBCAAIARqIAA2AgAMCAsgBigCBCIFQQNxQQFHDQYgBUF4cSEIIAVB/wFNBEAgBUEDdiEDIAYoAggiACAGKAIMIgJGBEBBxNUAQcTVACgCAEF+IAN3cTYCAAwHCyACIAA2AgggACACNgIMDAYLIAYoAhghByAGIAYoAgwiAEcEQCAAIAYoAggiAjYCCCACIAA2AgwMBQsgBkEUaiICKAIAIgVFBEAgBigCECIFRQ0EIAZBEGohAgsDQCACIQMgBSIAQRRqIgIoAgAiBQ0AIABBEGohAiAAKAIQIgUNAAsgA0EANgIADAQLQXggAGtBD3EiASAAaiIHIAZBOGsiAyABayIBQQFyNgIEIAAgA2pBODYCBCACIAVBNyAFa0EPcWpBP2siAyADIAJBEGpJGyIDQSM2AgRB4NUAQazZACgCADYCAEHQ1QAgATYCAEHc1QAgBzYCACADQRBqQYzZACkCADcCACADQYTZACkCADcCCEGM2QAgA0EIajYCAEGI2QAgBjYCAEGE2QAgADYCAEGQ2QBBADYCACADQSRqIQEDQCABQQc2AgAgBSABQQRqIgFLDQALIAIgA0YNACADIAMoAgRBfnE2AgQgAyADIAJrIgU2AgAgAiAFQQFyNgIEIAVB/wFNBEAgBUF4cUHs1QBqIQACf0HE1QAoAgAiAUEBIAVBA3Z0IgNxRQRAQcTVACABIANyNgIAIAAMAQsgACgCCAsiASACNgIMIAAgAjYCCCACIAA2AgwgAiABNgIIDAELQR8hASAFQf///wdNBEAgBUEmIAVBCHZnIgBrdkEBcSAAQQF0a0E+aiEBCyACIAE2AhwgAkIANwIQIAFBAnRB9NcAaiEAQcjVACgCACIDQQEgAXQiBnFFBEAgACACNgIAQcjVACADIAZyNgIAIAIgADYCGCACIAI2AgggAiACNgIMDAELIAVBGSABQQF2a0EAIAFBH0cbdCEBIAAoAgAhAwJAA0AgAyIAKAIEQXhxIAVGDQEgAUEddiEDIAFBAXQhASAAIANBBHFqQRBqIgYoAgAiAw0ACyAGIAI2AgAgAiAANgIYIAIgAjYCDCACIAI2AggMAQsgACgCCCIBIAI2AgwgACACNgIIIAJBADYCGCACIAA2AgwgAiABNgIIC0HQ1QAoAgAiASAETQ0AQdzVACgCACIAIARqIgIgASAEayIBQQFyNgIEQdDVACABNgIAQdzVACACNgIAIAAgBEEDcjYCBCAAQQhqIQEMCAtBACEBQbTZAEEwNgIADAcLQQAhAAsgB0UNAAJAIAYoAhwiAkECdEH01wBqIgMoAgAgBkYEQCADIAA2AgAgAA0BQcjVAEHI1QAoAgBBfiACd3E2AgAMAgsgB0EQQRQgBygCECAGRhtqIAA2AgAgAEUNAQsgACAHNgIYIAYoAhAiAgRAIAAgAjYCECACIAA2AhgLIAZBFGooAgAiAkUNACAAQRRqIAI2AgAgAiAANgIYCyABIAhqIQEgBiAIaiIGKAIEIQULIAYgBUF+cTYCBCABIARqIAE2AgAgBCABQQFyNgIEIAFB/wFNBEAgAUF4cUHs1QBqIQACf0HE1QAoAgAiAkEBIAFBA3Z0IgFxRQRAQcTVACABIAJyNgIAIAAMAQsgACgCCAsiASAENgIMIAAgBDYCCCAEIAA2AgwgBCABNgIIDAELQR8hBSABQf///wdNBEAgAUEmIAFBCHZnIgBrdkEBcSAAQQF0a0E+aiEFCyAEIAU2AhwgBEIANwIQIAVBAnRB9NcAaiEAQcjVACgCACICQQEgBXQiA3FFBEAgACAENgIAQcjVACACIANyNgIAIAQgADYCGCAEIAQ2AgggBCAENgIMDAELIAFBGSAFQQF2a0EAIAVBH0cbdCEFIAAoAgAhAAJAA0AgACICKAIEQXhxIAFGDQEgBUEddiEAIAVBAXQhBSACIABBBHFqQRBqIgMoAgAiAA0ACyADIAQ2AgAgBCACNgIYIAQgBDYCDCAEIAQ2AggMAQsgAigCCCIAIAQ2AgwgAiAENgIIIARBADYCGCAEIAI2AgwgBCAANgIICyAJQQhqIQEMAgsCQCAHRQ0AAkAgAygCHCIBQQJ0QfTXAGoiAigCACADRgRAIAIgADYCACAADQFByNUAIAhBfiABd3EiCDYCAAwCCyAHQRBBFCAHKAIQIANGG2ogADYCACAARQ0BCyAAIAc2AhggAygCECIBBEAgACABNgIQIAEgADYCGAsgA0EUaigCACIBRQ0AIABBFGogATYCACABIAA2AhgLAkAgBUEPTQRAIAMgBCAFaiIAQQNyNgIEIAAgA2oiACAAKAIEQQFyNgIEDAELIAMgBGoiAiAFQQFyNgIEIAMgBEEDcjYCBCACIAVqIAU2AgAgBUH/AU0EQCAFQXhxQezVAGohAAJ/QcTVACgCACIBQQEgBUEDdnQiBXFFBEBBxNUAIAEgBXI2AgAgAAwBCyAAKAIICyIBIAI2AgwgACACNgIIIAIgADYCDCACIAE2AggMAQtBHyEBIAVB////B00EQCAFQSYgBUEIdmciAGt2QQFxIABBAXRrQT5qIQELIAIgATYCHCACQgA3AhAgAUECdEH01wBqIQBBASABdCIEIAhxRQRAIAAgAjYCAEHI1QAgBCAIcjYCACACIAA2AhggAiACNgIIIAIgAjYCDAwBCyAFQRkgAUEBdmtBACABQR9HG3QhASAAKAIAIQQCQANAIAQiACgCBEF4cSAFRg0BIAFBHXYhBCABQQF0IQEgACAEQQRxakEQaiIGKAIAIgQNAAsgBiACNgIAIAIgADYCGCACIAI2AgwgAiACNgIIDAELIAAoAggiASACNgIMIAAgAjYCCCACQQA2AhggAiAANgIMIAIgATYCCAsgA0EIaiEBDAELAkAgCUUNAAJAIAAoAhwiAUECdEH01wBqIgIoAgAgAEYEQCACIAM2AgAgAw0BQcjVACALQX4gAXdxNgIADAILIAlBEEEUIAkoAhAgAEYbaiADNgIAIANFDQELIAMgCTYCGCAAKAIQIgEEQCADIAE2AhAgASADNgIYCyAAQRRqKAIAIgFFDQAgA0EUaiABNgIAIAEgAzYCGAsCQCAFQQ9NBEAgACAEIAVqIgFBA3I2AgQgACABaiIBIAEoAgRBAXI2AgQMAQsgACAEaiIHIAVBAXI2AgQgACAEQQNyNgIEIAUgB2ogBTYCACAIBEAgCEF4cUHs1QBqIQFB2NUAKAIAIQMCf0EBIAhBA3Z0IgIgBnFFBEBBxNUAIAIgBnI2AgAgAQwBCyABKAIICyICIAM2AgwgASADNgIIIAMgATYCDCADIAI2AggLQdjVACAHNgIAQczVACAFNgIACyAAQQhqIQELIApBEGokACABC0MAIABFBEA/AEEQdA8LAkAgAEH//wNxDQAgAEEASA0AIABBEHZAACIAQX9GBEBBtNkAQTA2AgBBfw8LIABBEHQPCwALC5lCIgBBgAgLDQEAAAAAAAAAAgAAAAMAQZgICwUEAAAABQBBqAgLCQYAAAAHAAAACABB5AgLwjJJbnZhbGlkIGNoYXIgaW4gdXJsIHF1ZXJ5AFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fYm9keQBDb250ZW50LUxlbmd0aCBvdmVyZmxvdwBDaHVuayBzaXplIG92ZXJmbG93AEludmFsaWQgbWV0aG9kIGZvciBIVFRQL3gueCByZXF1ZXN0AEludmFsaWQgbWV0aG9kIGZvciBSVFNQL3gueCByZXF1ZXN0AEV4cGVjdGVkIFNPVVJDRSBtZXRob2QgZm9yIElDRS94LnggcmVxdWVzdABJbnZhbGlkIGNoYXIgaW4gdXJsIGZyYWdtZW50IHN0YXJ0AEV4cGVjdGVkIGRvdABTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3N0YXR1cwBJbnZhbGlkIHJlc3BvbnNlIHN0YXR1cwBFeHBlY3RlZCBMRiBhZnRlciBoZWFkZXJzAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMAVXNlciBjYWxsYmFjayBlcnJvcgBgb25fcmVzZXRgIGNhbGxiYWNrIGVycm9yAGBvbl9jaHVua19oZWFkZXJgIGNhbGxiYWNrIGVycm9yAGBvbl9tZXNzYWdlX2JlZ2luYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlYCBjYWxsYmFjayBlcnJvcgBgb25fc3RhdHVzX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fdmVyc2lvbl9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX3VybF9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX3Byb3RvY29sX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9oZWFkZXJfdmFsdWVfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9tZXNzYWdlX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fbWV0aG9kX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25faGVhZGVyX2ZpZWxkX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfZXh0ZW5zaW9uX25hbWVgIGNhbGxiYWNrIGVycm9yAFVuZXhwZWN0ZWQgY2hhciBpbiB1cmwgc2VydmVyAEludmFsaWQgaGVhZGVyIHZhbHVlIGNoYXIASW52YWxpZCBoZWFkZXIgZmllbGQgY2hhcgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3ZlcnNpb24ASW52YWxpZCBtaW5vciB2ZXJzaW9uAEludmFsaWQgbWFqb3IgdmVyc2lvbgBFeHBlY3RlZCBzcGFjZSBhZnRlciB2ZXJzaW9uAEV4cGVjdGVkIENSTEYgYWZ0ZXIgdmVyc2lvbgBJbnZhbGlkIEhUVFAgdmVyc2lvbgBJbnZhbGlkIGhlYWRlciB0b2tlbgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3VybABJbnZhbGlkIGNoYXJhY3RlcnMgaW4gdXJsAFVuZXhwZWN0ZWQgc3RhcnQgY2hhciBpbiB1cmwARG91YmxlIEAgaW4gdXJsAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fcHJvdG9jb2wARW1wdHkgQ29udGVudC1MZW5ndGgASW52YWxpZCBjaGFyYWN0ZXIgaW4gQ29udGVudC1MZW5ndGgAVHJhbnNmZXItRW5jb2RpbmcgY2FuJ3QgYmUgcHJlc2VudCB3aXRoIENvbnRlbnQtTGVuZ3RoAER1cGxpY2F0ZSBDb250ZW50LUxlbmd0aABJbnZhbGlkIGNoYXIgaW4gdXJsIHBhdGgAQ29udGVudC1MZW5ndGggY2FuJ3QgYmUgcHJlc2VudCB3aXRoIFRyYW5zZmVyLUVuY29kaW5nAE1pc3NpbmcgZXhwZWN0ZWQgQ1IgYWZ0ZXIgY2h1bmsgc2l6ZQBFeHBlY3RlZCBMRiBhZnRlciBjaHVuayBzaXplAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIHNpemUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfdmFsdWUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9jaHVua19leHRlbnNpb25fdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyB2YWx1ZQBVbmV4cGVjdGVkIHdoaXRlc3BhY2UgYWZ0ZXIgaGVhZGVyIHZhbHVlAE1pc3NpbmcgZXhwZWN0ZWQgQ1IgYWZ0ZXIgaGVhZGVyIHZhbHVlAE1pc3NpbmcgZXhwZWN0ZWQgTEYgYWZ0ZXIgaGVhZGVyIHZhbHVlAEludmFsaWQgYFRyYW5zZmVyLUVuY29kaW5nYCBoZWFkZXIgdmFsdWUATWlzc2luZyBleHBlY3RlZCBDUiBhZnRlciBjaHVuayBleHRlbnNpb24gdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyBxdW90ZSB2YWx1ZQBJbnZhbGlkIHF1b3RlZC1wYWlyIGluIGNodW5rIGV4dGVuc2lvbnMgcXVvdGVkIHZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgcXVvdGVkIHZhbHVlAFBhdXNlZCBieSBvbl9oZWFkZXJzX2NvbXBsZXRlAEludmFsaWQgRU9GIHN0YXRlAG9uX3Jlc2V0IHBhdXNlAG9uX2NodW5rX2hlYWRlciBwYXVzZQBvbl9tZXNzYWdlX2JlZ2luIHBhdXNlAG9uX2NodW5rX2V4dGVuc2lvbl92YWx1ZSBwYXVzZQBvbl9zdGF0dXNfY29tcGxldGUgcGF1c2UAb25fdmVyc2lvbl9jb21wbGV0ZSBwYXVzZQBvbl91cmxfY29tcGxldGUgcGF1c2UAb25fcHJvdG9jb2xfY29tcGxldGUgcGF1c2UAb25fY2h1bmtfY29tcGxldGUgcGF1c2UAb25faGVhZGVyX3ZhbHVlX2NvbXBsZXRlIHBhdXNlAG9uX21lc3NhZ2VfY29tcGxldGUgcGF1c2UAb25fbWV0aG9kX2NvbXBsZXRlIHBhdXNlAG9uX2hlYWRlcl9maWVsZF9jb21wbGV0ZSBwYXVzZQBvbl9jaHVua19leHRlbnNpb25fbmFtZSBwYXVzZQBVbmV4cGVjdGVkIHNwYWNlIGFmdGVyIHN0YXJ0IGxpbmUATWlzc2luZyBleHBlY3RlZCBDUiBhZnRlciByZXNwb25zZSBsaW5lAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fY2h1bmtfZXh0ZW5zaW9uX25hbWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyBuYW1lAE1pc3NpbmcgZXhwZWN0ZWQgQ1IgYWZ0ZXIgY2h1bmsgZXh0ZW5zaW9uIG5hbWUASW52YWxpZCBzdGF0dXMgY29kZQBQYXVzZSBvbiBDT05ORUNUL1VwZ3JhZGUAUGF1c2Ugb24gUFJJL1VwZ3JhZGUARXhwZWN0ZWQgSFRUUC8yIENvbm5lY3Rpb24gUHJlZmFjZQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX21ldGhvZABFeHBlY3RlZCBzcGFjZSBhZnRlciBtZXRob2QAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfZmllbGQAUGF1c2VkAEludmFsaWQgd29yZCBlbmNvdW50ZXJlZABJbnZhbGlkIG1ldGhvZCBlbmNvdW50ZXJlZABNaXNzaW5nIGV4cGVjdGVkIENSIGFmdGVyIGNodW5rIGRhdGEARXhwZWN0ZWQgTEYgYWZ0ZXIgY2h1bmsgZGF0YQBVbmV4cGVjdGVkIGNoYXIgaW4gdXJsIHNjaGVtYQBSZXF1ZXN0IGhhcyBpbnZhbGlkIGBUcmFuc2Zlci1FbmNvZGluZ2AARGF0YSBhZnRlciBgQ29ubmVjdGlvbjogY2xvc2VgAFNXSVRDSF9QUk9YWQBVU0VfUFJPWFkATUtBQ1RJVklUWQBVTlBST0NFU1NBQkxFX0VOVElUWQBRVUVSWQBDT1BZAE1PVkVEX1BFUk1BTkVOVExZAFRPT19FQVJMWQBOT1RJRlkARkFJTEVEX0RFUEVOREVOQ1kAQkFEX0dBVEVXQVkAUExBWQBQVVQAQ0hFQ0tPVVQAR0FURVdBWV9USU1FT1VUAFJFUVVFU1RfVElNRU9VVABORVRXT1JLX0NPTk5FQ1RfVElNRU9VVABDT05ORUNUSU9OX1RJTUVPVVQATE9HSU5fVElNRU9VVABORVRXT1JLX1JFQURfVElNRU9VVABQT1NUAE1JU0RJUkVDVEVEX1JFUVVFU1QAQ0xJRU5UX0NMT1NFRF9SRVFVRVNUAENMSUVOVF9DTE9TRURfTE9BRF9CQUxBTkNFRF9SRVFVRVNUAEJBRF9SRVFVRVNUAEhUVFBfUkVRVUVTVF9TRU5UX1RPX0hUVFBTX1BPUlQAUkVQT1JUAElNX0FfVEVBUE9UAFJFU0VUX0NPTlRFTlQATk9fQ09OVEVOVABQQVJUSUFMX0NPTlRFTlQASFBFX0lOVkFMSURfQ09OU1RBTlQASFBFX0NCX1JFU0VUAEdFVABIUEVfU1RSSUNUAENPTkZMSUNUAFRFTVBPUkFSWV9SRURJUkVDVABQRVJNQU5FTlRfUkVESVJFQ1QAQ09OTkVDVABNVUxUSV9TVEFUVVMASFBFX0lOVkFMSURfU1RBVFVTAFRPT19NQU5ZX1JFUVVFU1RTAEVBUkxZX0hJTlRTAFVOQVZBSUxBQkxFX0ZPUl9MRUdBTF9SRUFTT05TAE9QVElPTlMAU1dJVENISU5HX1BST1RPQ09MUwBWQVJJQU5UX0FMU09fTkVHT1RJQVRFUwBNVUxUSVBMRV9DSE9JQ0VTAElOVEVSTkFMX1NFUlZFUl9FUlJPUgBXRUJfU0VSVkVSX1VOS05PV05fRVJST1IAUkFJTEdVTl9FUlJPUgBJREVOVElUWV9QUk9WSURFUl9BVVRIRU5USUNBVElPTl9FUlJPUgBTU0xfQ0VSVElGSUNBVEVfRVJST1IASU5WQUxJRF9YX0ZPUldBUkRFRF9GT1IAU0VUX1BBUkFNRVRFUgBHRVRfUEFSQU1FVEVSAEhQRV9VU0VSAFNFRV9PVEhFUgBIUEVfQ0JfQ0hVTktfSEVBREVSAEV4cGVjdGVkIExGIGFmdGVyIENSAE1LQ0FMRU5EQVIAU0VUVVAAV0VCX1NFUlZFUl9JU19ET1dOAFRFQVJET1dOAEhQRV9DTE9TRURfQ09OTkVDVElPTgBIRVVSSVNUSUNfRVhQSVJBVElPTgBESVNDT05ORUNURURfT1BFUkFUSU9OAE5PTl9BVVRIT1JJVEFUSVZFX0lORk9STUFUSU9OAEhQRV9JTlZBTElEX1ZFUlNJT04ASFBFX0NCX01FU1NBR0VfQkVHSU4AU0lURV9JU19GUk9aRU4ASFBFX0lOVkFMSURfSEVBREVSX1RPS0VOAElOVkFMSURfVE9LRU4ARk9SQklEREVOAEVOSEFOQ0VfWU9VUl9DQUxNAEhQRV9JTlZBTElEX1VSTABCTE9DS0VEX0JZX1BBUkVOVEFMX0NPTlRST0wATUtDT0wAQUNMAEhQRV9JTlRFUk5BTABSRVFVRVNUX0hFQURFUl9GSUVMRFNfVE9PX0xBUkdFX1VOT0ZGSUNJQUwASFBFX09LAFVOTElOSwBVTkxPQ0sAUFJJAFJFVFJZX1dJVEgASFBFX0lOVkFMSURfQ09OVEVOVF9MRU5HVEgASFBFX1VORVhQRUNURURfQ09OVEVOVF9MRU5HVEgARkxVU0gAUFJPUFBBVENIAE0tU0VBUkNIAFVSSV9UT09fTE9ORwBQUk9DRVNTSU5HAE1JU0NFTExBTkVPVVNfUEVSU0lTVEVOVF9XQVJOSU5HAE1JU0NFTExBTkVPVVNfV0FSTklORwBIUEVfSU5WQUxJRF9UUkFOU0ZFUl9FTkNPRElORwBFeHBlY3RlZCBDUkxGAEhQRV9JTlZBTElEX0NIVU5LX1NJWkUATU9WRQBDT05USU5VRQBIUEVfQ0JfU1RBVFVTX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJTX0NPTVBMRVRFAEhQRV9DQl9WRVJTSU9OX0NPTVBMRVRFAEhQRV9DQl9VUkxfQ09NUExFVEUASFBFX0NCX1BST1RPQ09MX0NPTVBMRVRFAEhQRV9DQl9DSFVOS19DT01QTEVURQBIUEVfQ0JfSEVBREVSX1ZBTFVFX0NPTVBMRVRFAEhQRV9DQl9DSFVOS19FWFRFTlNJT05fVkFMVUVfQ09NUExFVEUASFBFX0NCX0NIVU5LX0VYVEVOU0lPTl9OQU1FX0NPTVBMRVRFAEhQRV9DQl9NRVNTQUdFX0NPTVBMRVRFAEhQRV9DQl9NRVRIT0RfQ09NUExFVEUASFBFX0NCX0hFQURFUl9GSUVMRF9DT01QTEVURQBERUxFVEUASFBFX0lOVkFMSURfRU9GX1NUQVRFAElOVkFMSURfU1NMX0NFUlRJRklDQVRFAFBBVVNFAE5PX1JFU1BPTlNFAFVOU1VQUE9SVEVEX01FRElBX1RZUEUAR09ORQBOT1RfQUNDRVBUQUJMRQBTRVJWSUNFX1VOQVZBSUxBQkxFAFJBTkdFX05PVF9TQVRJU0ZJQUJMRQBPUklHSU5fSVNfVU5SRUFDSEFCTEUAUkVTUE9OU0VfSVNfU1RBTEUAUFVSR0UATUVSR0UAUkVRVUVTVF9IRUFERVJfRklFTERTX1RPT19MQVJHRQBSRVFVRVNUX0hFQURFUl9UT09fTEFSR0UAUEFZTE9BRF9UT09fTEFSR0UASU5TVUZGSUNJRU5UX1NUT1JBR0UASFBFX1BBVVNFRF9VUEdSQURFAEhQRV9QQVVTRURfSDJfVVBHUkFERQBTT1VSQ0UAQU5OT1VOQ0UAVFJBQ0UASFBFX1VORVhQRUNURURfU1BBQ0UAREVTQ1JJQkUAVU5TVUJTQ1JJQkUAUkVDT1JEAEhQRV9JTlZBTElEX01FVEhPRABOT1RfRk9VTkQAUFJPUEZJTkQAVU5CSU5EAFJFQklORABVTkFVVEhPUklaRUQATUVUSE9EX05PVF9BTExPV0VEAEhUVFBfVkVSU0lPTl9OT1RfU1VQUE9SVEVEAEFMUkVBRFlfUkVQT1JURUQAQUNDRVBURUQATk9UX0lNUExFTUVOVEVEAExPT1BfREVURUNURUQASFBFX0NSX0VYUEVDVEVEAEhQRV9MRl9FWFBFQ1RFRABDUkVBVEVEAElNX1VTRUQASFBFX1BBVVNFRABUSU1FT1VUX09DQ1VSRUQAUEFZTUVOVF9SRVFVSVJFRABQUkVDT05ESVRJT05fUkVRVUlSRUQAUFJPWFlfQVVUSEVOVElDQVRJT05fUkVRVUlSRUQATkVUV09SS19BVVRIRU5USUNBVElPTl9SRVFVSVJFRABMRU5HVEhfUkVRVUlSRUQAU1NMX0NFUlRJRklDQVRFX1JFUVVJUkVEAFVQR1JBREVfUkVRVUlSRUQAUEFHRV9FWFBJUkVEAFBSRUNPTkRJVElPTl9GQUlMRUQARVhQRUNUQVRJT05fRkFJTEVEAFJFVkFMSURBVElPTl9GQUlMRUQAU1NMX0hBTkRTSEFLRV9GQUlMRUQATE9DS0VEAFRSQU5TRk9STUFUSU9OX0FQUExJRUQATk9UX01PRElGSUVEAE5PVF9FWFRFTkRFRABCQU5EV0lEVEhfTElNSVRfRVhDRUVERUQAU0lURV9JU19PVkVSTE9BREVEAEhFQUQARXhwZWN0ZWQgSFRUUC8sIFJUU1AvIG9yIElDRS8A5xUAAK8VAACkEgAAkhoAACYWAACeFAAA2xkAAHkVAAB+EgAA/hQAADYVAAALFgAA2BYAAPMSAABCGAAArBYAABIVAAAUFwAA7xcAAEgUAABxFwAAshoAAGsZAAB+GQAANRQAAIIaAABEFwAA/RYAAB4YAACHFwAAqhkAAJMSAAAHGAAALBcAAMoXAACkFwAA5xUAAOcVAABYFwAAOxgAAKASAAAtHAAAwxEAAEgRAADeEgAAQhMAAKQZAAD9EAAA9xUAAKUVAADvFgAA+BkAAEoWAABWFgAA9RUAAAoaAAAIGgAAARoAAKsVAABCEgAA1xAAAEwRAAAFGQAAVBYAAB4RAADKGQAAyBkAAE4WAAD/GAAAcRQAAPAVAADuFQAAlBkAAPwVAAC/GQAAmxkAAHwUAABDEQAAcBgAAJUUAAAnFAAAGRQAANUSAADUGQAARBYAAPcQAEG5OwsBAQBB0DsL4AEBAQIBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQBBuj0LBAEAAAIAQdE9C14DBAMDAwMDAAADAwADAwADAwMDAwMDAwMDAAUAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAwADAEG6PwsEAQAAAgBB0T8LXgMAAwMDAwMAAAMDAAMDAAMDAwMDAwMDAwMABAAFAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwADAAMAQbDBAAsNbG9zZWVlcC1hbGl2ZQBBycEACwEBAEHgwQAL4AEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQBBycMACwEBAEHgwwAL5wEBAQEBAQEBAQEBAQECAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAWNodW5rZWQAQfHFAAteAQABAQEBAQAAAQEAAQEAAQEBAQEBAQEBAQAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEAAQBB0McACyFlY3Rpb25lbnQtbGVuZ3Rob25yb3h5LWNvbm5lY3Rpb24AQYDIAAsgcmFuc2Zlci1lbmNvZGluZ3BncmFkZQ0KDQpTTQ0KDQoAQanIAAsFAQIAAQMAQcDIAAtfBAUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUAQanKAAsFAQIAAQMAQcDKAAtfBAUFBgUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUAQanMAAsEAQAAAQBBwcwAC14CAgACAgICAgICAgICAgICAgICAgICAgICAgICAgIAAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAEGpzgALBQECAAEDAEHAzgALXwQFAAAFBQUFBQUFBQUFBQYFBQUFBQUFBQUFBQUABQAHCAUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQAFAAUABQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUAAAAFAEGp0AALBQEBAAEBAEHA0AALAQEAQdrQAAtBAgAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAQanSAAsFAQEAAQEAQcDSAAsBAQBBytIACwYCAAAAAAIAQeHSAAs6AwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwBBoNQAC50BTk9VTkNFRUNLT1VUTkVDVEVURUNSSUJFTFVTSEVURUFEU0VBUkNIUkdFQ1RJVklUWUxFTkRBUlZFT1RJRllQVElPTlNDSFNFQVlTVEFUQ0hHRVVFUllPUkRJUkVDVE9SVFJDSFBBUkFNRVRFUlVSQ0VCU0NSSUJFQVJET1dOQUNFSU5ETktDS1VCU0NSSUJFVFRQQ0VUU1BBRFRQLw==' - const result = new Date(Date.UTC(year, monthIdx, day, hour, minute, second)) - return result.getUTCDay() === weekday ? result : undefined -} +let wasmBuffer -module.exports = { - parseHttpDate -} +Object.defineProperty(module, 'exports', { + get: () => { + return wasmBuffer + ? wasmBuffer + : (wasmBuffer = Buffer.from(wasmBase64, 'base64')) + } +}) /***/ }), -/***/ 9797: -/***/ ((module) => { - -"use strict"; - - -/** - * @template {*} T - * @typedef {Object} DeferredPromise - * @property {Promise} promise - * @property {(value?: T) => void} resolve - * @property {(reason?: any) => void} reject - */ - -/** - * @template {*} T - * @returns {DeferredPromise} An object containing a promise and its resolve/reject methods. - */ -function createDeferredPromise () { - let res - let rej - const promise = new Promise((resolve, reject) => { - res = resolve - rej = reject - }) +/***/ 9054: +/***/ ((__unused_webpack_module, exports) => { - return { promise, resolve: res, reject: rej } -} -module.exports = { - createDeferredPromise +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.enumToMap = enumToMap; +function enumToMap(obj, filter = [], exceptions = []) { + const emptyFilter = (filter?.length ?? 0) === 0; + const emptyExceptions = (exceptions?.length ?? 0) === 0; + return Object.fromEntries(Object.entries(obj).filter(([, value]) => { + return (typeof value === 'number' && + (emptyFilter || filter.includes(value)) && + (emptyExceptions || !exceptions.includes(value))); + })); } /***/ }), -/***/ 1422: +/***/ 839: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -/** @typedef {`node:${string}`} NodeModuleName */ +const { kClients } = __nccwpck_require__(8261) +const Agent = __nccwpck_require__(9959) +const { + kAgent, + kMockAgentSet, + kMockAgentGet, + kDispatches, + kIsMockActive, + kNetConnect, + kGetNetConnect, + kOptions, + kFactory, + kMockAgentRegisterCallHistory, + kMockAgentIsCallHistoryEnabled, + kMockAgentAddCallHistoryLog, + kMockAgentMockCallHistoryInstance, + kMockAgentAcceptsNonStandardSearchParameters, + kMockCallHistoryAddLog, + kIgnoreTrailingSlash +} = __nccwpck_require__(9823) +const MockClient = __nccwpck_require__(5627) +const MockPool = __nccwpck_require__(6466) +const { matchValue, normalizeSearchParams, buildAndValidateMockOptions, normalizeOrigin } = __nccwpck_require__(5427) +const { InvalidArgumentError, UndiciError } = __nccwpck_require__(5093) +const Dispatcher = __nccwpck_require__(5085) +const PendingInterceptorsFormatter = __nccwpck_require__(2272) +const { MockCallHistory } = __nccwpck_require__(3285) -/** @type {Record any>} */ -const lazyLoaders = { - __proto__: null, - 'node:crypto': () => __nccwpck_require__(7598), - 'node:sqlite': () => __nccwpck_require__(99), - 'node:worker_threads': () => __nccwpck_require__(5919), - 'node:zlib': () => __nccwpck_require__(8522) -} +class MockAgent extends Dispatcher { + constructor (opts = {}) { + super(opts) -/** - * @param {NodeModuleName} moduleName - * @returns {boolean} - */ -function detectRuntimeFeatureByNodeModule (moduleName) { - try { - lazyLoaders[moduleName]() - return true - } catch (err) { - if (err.code !== 'ERR_UNKNOWN_BUILTIN_MODULE' && err.code !== 'ERR_NO_CRYPTO') { - throw err + const mockOptions = buildAndValidateMockOptions(opts) + + this[kNetConnect] = true + this[kIsMockActive] = true + this[kMockAgentIsCallHistoryEnabled] = mockOptions.enableCallHistory ?? false + this[kMockAgentAcceptsNonStandardSearchParameters] = mockOptions.acceptNonStandardSearchParameters ?? false + this[kIgnoreTrailingSlash] = mockOptions.ignoreTrailingSlash ?? false + + // Instantiate Agent and encapsulate + if (opts?.agent && typeof opts.agent.dispatch !== 'function') { + throw new InvalidArgumentError('Argument opts.agent must implement Agent') + } + const agent = opts?.agent ? opts.agent : new Agent(opts) + this[kAgent] = agent + + this[kClients] = agent[kClients] + this[kOptions] = mockOptions + + if (this[kMockAgentIsCallHistoryEnabled]) { + this[kMockAgentRegisterCallHistory]() } - return false } -} -/** - * @param {NodeModuleName} moduleName - * @param {string} property - * @returns {boolean} - */ -function detectRuntimeFeatureByExportedProperty (moduleName, property) { - const module = lazyLoaders[moduleName]() - return typeof module[property] !== 'undefined' -} + get (origin) { + // Normalize origin to handle URL objects and case-insensitive hostnames + const normalizedOrigin = normalizeOrigin(origin) + const originKey = this[kIgnoreTrailingSlash] ? normalizedOrigin.replace(/\/$/, '') : normalizedOrigin -const runtimeFeaturesByExportedProperty = /** @type {const} */ (['markAsUncloneable', 'zstd']) + let dispatcher = this[kMockAgentGet](originKey) -/** @type {Record} */ -const exportedPropertyLookup = { - markAsUncloneable: ['node:worker_threads', 'markAsUncloneable'], - zstd: ['node:zlib', 'createZstdDecompress'] -} + if (!dispatcher) { + dispatcher = this[kFactory](originKey) + this[kMockAgentSet](originKey, dispatcher) + } + return dispatcher + } -/** @typedef {typeof runtimeFeaturesByExportedProperty[number]} RuntimeFeatureByExportedProperty */ + dispatch (opts, handler) { + opts.origin = normalizeOrigin(opts.origin) -const runtimeFeaturesAsNodeModule = /** @type {const} */ (['crypto', 'sqlite']) -/** @typedef {typeof runtimeFeaturesAsNodeModule[number]} RuntimeFeatureByNodeModule */ + // Call MockAgent.get to perform additional setup before dispatching as normal + this.get(opts.origin) -const features = /** @type {const} */ ([ - ...runtimeFeaturesAsNodeModule, - ...runtimeFeaturesByExportedProperty -]) + this[kMockAgentAddCallHistoryLog](opts) -/** @typedef {typeof features[number]} Feature */ + const acceptNonStandardSearchParameters = this[kMockAgentAcceptsNonStandardSearchParameters] -/** - * @param {Feature} feature - * @returns {boolean} - */ -function detectRuntimeFeature (feature) { - if (runtimeFeaturesAsNodeModule.includes(/** @type {RuntimeFeatureByNodeModule} */ (feature))) { - return detectRuntimeFeatureByNodeModule(`node:${feature}`) - } else if (runtimeFeaturesByExportedProperty.includes(/** @type {RuntimeFeatureByExportedProperty} */ (feature))) { - const [moduleName, property] = exportedPropertyLookup[feature] - return detectRuntimeFeatureByExportedProperty(moduleName, property) - } - throw new TypeError(`unknown feature: ${feature}`) -} + const dispatchOpts = { ...opts } -/** - * @class - * @name RuntimeFeatures - */ -class RuntimeFeatures { - /** @type {Map} */ - #map = new Map() + if (acceptNonStandardSearchParameters && dispatchOpts.path) { + const [path, searchParams] = dispatchOpts.path.split('?') + const normalizedSearchParams = normalizeSearchParams(searchParams, acceptNonStandardSearchParameters) + dispatchOpts.path = `${path}?${normalizedSearchParams}` + } - /** - * Clears all cached feature detections. - */ - clear () { - this.#map.clear() + return this[kAgent].dispatch(dispatchOpts, handler) } - /** - * @param {Feature} feature - * @returns {boolean} - */ - has (feature) { - return ( - this.#map.get(feature) ?? this.#detectRuntimeFeature(feature) - ) + async close () { + this.clearCallHistory() + await this[kAgent].close() + this[kClients].clear() } - /** - * @param {Feature} feature - * @param {boolean} value - */ - set (feature, value) { - if (features.includes(feature) === false) { - throw new TypeError(`unknown feature: ${feature}`) - } - this.#map.set(feature, value) + deactivate () { + this[kIsMockActive] = false } - /** - * @param {Feature} feature - * @returns {boolean} - */ - #detectRuntimeFeature (feature) { - const result = detectRuntimeFeature(feature) - this.#map.set(feature, result) - return result + activate () { + this[kIsMockActive] = true } -} -const instance = new RuntimeFeatures() + enableNetConnect (matcher) { + if (typeof matcher === 'string' || typeof matcher === 'function' || matcher instanceof RegExp) { + if (Array.isArray(this[kNetConnect])) { + this[kNetConnect].push(matcher) + } else { + this[kNetConnect] = [matcher] + } + } else if (typeof matcher === 'undefined') { + this[kNetConnect] = true + } else { + throw new InvalidArgumentError('Unsupported matcher. Must be one of String|Function|RegExp.') + } + } -module.exports.runtimeFeatures = instance -module.exports["default"] = instance + disableNetConnect () { + this[kNetConnect] = false + } + enableCallHistory () { + this[kMockAgentIsCallHistoryEnabled] = true -/***/ }), + return this + } -/***/ 7755: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + disableCallHistory () { + this[kMockAgentIsCallHistoryEnabled] = false -"use strict"; + return this + } + getCallHistory () { + return this[kMockAgentMockCallHistoryInstance] + } -const { - kConnected, - kPending, - kRunning, - kSize, - kFree, - kQueued -} = __nccwpck_require__(9562) + clearCallHistory () { + if (this[kMockAgentMockCallHistoryInstance] !== undefined) { + this[kMockAgentMockCallHistoryInstance].clear() + } + } -class ClientStats { - constructor (client) { - this.connected = client[kConnected] - this.pending = client[kPending] - this.running = client[kRunning] - this.size = client[kSize] + // This is required to bypass issues caused by using global symbols - see: + // https://github.com/nodejs/undici/issues/1447 + get isMockActive () { + return this[kIsMockActive] } -} -class PoolStats { - constructor (pool) { - this.connected = pool[kConnected] - this.free = pool[kFree] - this.pending = pool[kPending] - this.queued = pool[kQueued] - this.running = pool[kRunning] - this.size = pool[kSize] + [kMockAgentRegisterCallHistory] () { + if (this[kMockAgentMockCallHistoryInstance] === undefined) { + this[kMockAgentMockCallHistoryInstance] = new MockCallHistory() + } } -} -module.exports = { ClientStats, PoolStats } + [kMockAgentAddCallHistoryLog] (opts) { + if (this[kMockAgentIsCallHistoryEnabled]) { + // additional setup when enableCallHistory class method is used after mockAgent instantiation + this[kMockAgentRegisterCallHistory]() + // add call history log on every call (intercepted or not) + this[kMockAgentMockCallHistoryInstance][kMockCallHistoryAddLog](opts) + } + } -/***/ }), + [kMockAgentSet] (origin, dispatcher) { + this[kClients].set(origin, { count: 0, dispatcher }) + } -/***/ 7280: -/***/ ((module) => { + [kFactory] (origin) { + const mockOptions = Object.assign({ agent: this }, this[kOptions]) + return this[kOptions] && this[kOptions].connections === 1 + ? new MockClient(origin, mockOptions) + : new MockPool(origin, mockOptions) + } -"use strict"; + [kMockAgentGet] (origin) { + // First check if we can immediately find it + const result = this[kClients].get(origin) + if (result?.dispatcher) { + return result.dispatcher + } + // If the origin is not a string create a dummy parent pool and return to user + if (typeof origin !== 'string') { + const dispatcher = this[kFactory]('http://localhost:9999') + this[kMockAgentSet](origin, dispatcher) + return dispatcher + } -/** - * This module offers an optimized timer implementation designed for scenarios - * where high precision is not critical. - * - * The timer achieves faster performance by using a low-resolution approach, - * with an accuracy target of within 500ms. This makes it particularly useful - * for timers with delays of 1 second or more, where exact timing is less - * crucial. - * - * It's important to note that Node.js timers are inherently imprecise, as - * delays can occur due to the event loop being blocked by other operations. - * Consequently, timers may trigger later than their scheduled time. - */ + // If we match, create a pool and assign the same dispatches + for (const [keyMatcher, result] of Array.from(this[kClients])) { + if (result && typeof keyMatcher !== 'string' && matchValue(keyMatcher, origin)) { + const dispatcher = this[kFactory](origin) + this[kMockAgentSet](origin, dispatcher) + dispatcher[kDispatches] = result.dispatcher[kDispatches] + return dispatcher + } + } + } -/** - * The fastNow variable contains the internal fast timer clock value. - * - * @type {number} - */ -let fastNow = 0 + [kGetNetConnect] () { + return this[kNetConnect] + } -/** - * RESOLUTION_MS represents the target resolution time in milliseconds. - * - * @type {number} - * @default 1000 - */ -const RESOLUTION_MS = 1e3 + pendingInterceptors () { + const mockAgentClients = this[kClients] -/** - * TICK_MS defines the desired interval in milliseconds between each tick. - * The target value is set to half the resolution time, minus 1 ms, to account - * for potential event loop overhead. - * - * @type {number} - * @default 499 - */ -const TICK_MS = (RESOLUTION_MS >> 1) - 1 + return Array.from(mockAgentClients.entries()) + .flatMap(([origin, result]) => result.dispatcher[kDispatches].map(dispatch => ({ ...dispatch, origin }))) + .filter(({ pending }) => pending) + } -/** - * fastNowTimeout is a Node.js timer used to manage and process - * the FastTimers stored in the `fastTimers` array. - * - * @type {NodeJS.Timeout} - */ -let fastNowTimeout + assertNoPendingInterceptors ({ pendingInterceptorsFormatter = new PendingInterceptorsFormatter() } = {}) { + const pending = this.pendingInterceptors() -/** - * The kFastTimer symbol is used to identify FastTimer instances. - * - * @type {Symbol} - */ -const kFastTimer = Symbol('kFastTimer') + if (pending.length === 0) { + return + } -/** - * The fastTimers array contains all active FastTimers. - * - * @type {FastTimer[]} - */ -const fastTimers = [] + throw new UndiciError( + pending.length === 1 + ? `1 interceptor is pending:\n\n${pendingInterceptorsFormatter.format(pending)}`.trim() + : `${pending.length} interceptors are pending:\n\n${pendingInterceptorsFormatter.format(pending)}`.trim() + ) + } +} -/** - * These constants represent the various states of a FastTimer. - */ +module.exports = MockAgent -/** - * The `NOT_IN_LIST` constant indicates that the FastTimer is not included - * in the `fastTimers` array. Timers with this status will not be processed - * during the next tick by the `onTick` function. - * - * A FastTimer can be re-added to the `fastTimers` array by invoking the - * `refresh` method on the FastTimer instance. - * - * @type {-2} - */ -const NOT_IN_LIST = -2 -/** - * The `TO_BE_CLEARED` constant indicates that the FastTimer is scheduled - * for removal from the `fastTimers` array. A FastTimer in this state will - * be removed in the next tick by the `onTick` function and will no longer - * be processed. - * - * This status is also set when the `clear` method is called on the FastTimer instance. - * - * @type {-1} - */ -const TO_BE_CLEARED = -1 +/***/ }), -/** - * The `PENDING` constant signifies that the FastTimer is awaiting processing - * in the next tick by the `onTick` function. Timers with this status will have - * their `_idleStart` value set and their status updated to `ACTIVE` in the next tick. - * - * @type {0} - */ -const PENDING = 0 +/***/ 3285: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -/** - * The `ACTIVE` constant indicates that the FastTimer is active and waiting - * for its timer to expire. During the next tick, the `onTick` function will - * check if the timer has expired, and if so, it will execute the associated callback. - * - * @type {1} - */ -const ACTIVE = 1 -/** - * The onTick function processes the fastTimers array. - * - * @returns {void} - */ -function onTick () { - /** - * Increment the fastNow value by the TICK_MS value, despite the actual time - * that has passed since the last tick. This approach ensures independence - * from the system clock and delays caused by a blocked event loop. - * - * @type {number} - */ - fastNow += TICK_MS - /** - * The `idx` variable is used to iterate over the `fastTimers` array. - * Expired timers are removed by replacing them with the last element in the array. - * Consequently, `idx` is only incremented when the current element is not removed. - * - * @type {number} - */ - let idx = 0 +const { kMockCallHistoryAddLog } = __nccwpck_require__(9823) +const { InvalidArgumentError } = __nccwpck_require__(5093) - /** - * The len variable will contain the length of the fastTimers array - * and will be decremented when a FastTimer should be removed from the - * fastTimers array. - * - * @type {number} - */ - let len = fastTimers.length +function handleFilterCallsWithOptions (criteria, options, handler, store) { + switch (options.operator) { + case 'OR': + store.push(...handler(criteria)) - while (idx < len) { - /** - * @type {FastTimer} - */ - const timer = fastTimers[idx] + return store + case 'AND': + return handler.call({ logs: store }, criteria) + default: + // guard -- should never happens because buildAndValidateFilterCallsOptions is called before + throw new InvalidArgumentError('options.operator must to be a case insensitive string equal to \'OR\' or \'AND\'') + } +} - // If the timer is in the ACTIVE state and the timer has expired, it will - // be processed in the next tick. - if (timer._state === PENDING) { - // Set the _idleStart value to the fastNow value minus the TICK_MS value - // to account for the time the timer was in the PENDING state. - timer._idleStart = fastNow - TICK_MS - timer._state = ACTIVE - } else if ( - timer._state === ACTIVE && - fastNow >= timer._idleStart + timer._idleTimeout - ) { - timer._state = TO_BE_CLEARED - timer._idleStart = -1 - timer._onTimeout(timer._timerArg) - } +function buildAndValidateFilterCallsOptions (options = {}) { + const finalOptions = {} - if (timer._state === TO_BE_CLEARED) { - timer._state = NOT_IN_LIST + if ('operator' in options) { + if (typeof options.operator !== 'string' || (options.operator.toUpperCase() !== 'OR' && options.operator.toUpperCase() !== 'AND')) { + throw new InvalidArgumentError('options.operator must to be a case insensitive string equal to \'OR\' or \'AND\'') + } - // Move the last element to the current index and decrement len if it is - // not the only element in the array. - if (--len !== 0) { - fastTimers[idx] = fastTimers[len] - } - } else { - ++idx + return { + ...finalOptions, + operator: options.operator.toUpperCase() } } - // Set the length of the fastTimers array to the new length and thus - // removing the excess FastTimers elements from the array. - fastTimers.length = len + return finalOptions +} - // If there are still active FastTimers in the array, refresh the Timer. - // If there are no active FastTimers, the timer will be refreshed again - // when a new FastTimer is instantiated. - if (fastTimers.length !== 0) { - refreshTimeout() +function makeFilterCalls (parameterName) { + return (parameterValue) => { + if (typeof parameterValue === 'string' || parameterValue == null) { + return this.logs.filter((log) => { + return log[parameterName] === parameterValue + }) + } + if (parameterValue instanceof RegExp) { + return this.logs.filter((log) => { + return parameterValue.test(log[parameterName]) + }) + } + + throw new InvalidArgumentError(`${parameterName} parameter should be one of string, regexp, undefined or null`) } } +function computeUrlWithMaybeSearchParameters (requestInit) { + // path can contains query url parameters + // or query can contains query url parameters + try { + const url = new URL(requestInit.path, requestInit.origin) -function refreshTimeout () { - // If the fastNowTimeout is already set and the Timer has the refresh()- - // method available, call it to refresh the timer. - // Some timer objects returned by setTimeout may not have a .refresh() - // method (e.g. mocked timers in tests). - if (fastNowTimeout?.refresh) { - fastNowTimeout.refresh() - // fastNowTimeout is not instantiated yet or refresh is not availabe, - // create a new Timer. - } else { - clearTimeout(fastNowTimeout) - fastNowTimeout = setTimeout(onTick, TICK_MS) - // If the Timer has an unref method, call it to allow the process to exit, - // if there are no other active handles. When using fake timers or mocked - // environments (like Jest), .unref() may not be defined, - fastNowTimeout?.unref() + // requestInit.path contains query url parameters + // requestInit.query is then undefined + if (url.search.length !== 0) { + return url + } + + // requestInit.query can be populated here + url.search = new URLSearchParams(requestInit.query).toString() + + return url + } catch (error) { + throw new InvalidArgumentError('An error occurred when computing MockCallHistoryLog.url', { cause: error }) } } -/** - * The `FastTimer` class is a data structure designed to store and manage - * timer information. - */ -class FastTimer { - [kFastTimer] = true +class MockCallHistoryLog { + constructor (requestInit = {}) { + this.body = requestInit.body + this.headers = requestInit.headers + this.method = requestInit.method - /** - * The state of the timer, which can be one of the following: - * - NOT_IN_LIST (-2) - * - TO_BE_CLEARED (-1) - * - PENDING (0) - * - ACTIVE (1) - * - * @type {-2|-1|0|1} - * @private - */ - _state = NOT_IN_LIST + const url = computeUrlWithMaybeSearchParameters(requestInit) - /** - * The number of milliseconds to wait before calling the callback. - * - * @type {number} - * @private - */ - _idleTimeout = -1 + this.fullUrl = url.toString() + this.origin = url.origin + this.path = url.pathname + this.searchParams = Object.fromEntries(url.searchParams) + this.protocol = url.protocol + this.host = url.host + this.port = url.port + this.hash = url.hash + } - /** - * The time in milliseconds when the timer was started. This value is used to - * calculate when the timer should expire. - * - * @type {number} - * @default -1 - * @private - */ - _idleStart = -1 + toMap () { + return new Map([ + ['protocol', this.protocol], + ['host', this.host], + ['port', this.port], + ['origin', this.origin], + ['path', this.path], + ['hash', this.hash], + ['searchParams', this.searchParams], + ['fullUrl', this.fullUrl], + ['method', this.method], + ['body', this.body], + ['headers', this.headers]] + ) + } - /** - * The function to be executed when the timer expires. - * @type {Function} - * @private - */ - _onTimeout + toString () { + const options = { betweenKeyValueSeparator: '->', betweenPairSeparator: '|' } + let result = '' - /** - * The argument to be passed to the callback when the timer expires. - * - * @type {*} - * @private - */ - _timerArg + this.toMap().forEach((value, key) => { + if (typeof value === 'string' || value === undefined || value === null) { + result = `${result}${key}${options.betweenKeyValueSeparator}${value}${options.betweenPairSeparator}` + } + if ((typeof value === 'object' && value !== null) || Array.isArray(value)) { + result = `${result}${key}${options.betweenKeyValueSeparator}${JSON.stringify(value)}${options.betweenPairSeparator}` + } + // maybe miss something for non Record / Array headers and searchParams here + }) - /** - * @constructor - * @param {Function} callback A function to be executed after the timer - * expires. - * @param {number} delay The time, in milliseconds that the timer should wait - * before the specified function or code is executed. - * @param {*} arg - */ - constructor (callback, delay, arg) { - this._onTimeout = callback - this._idleTimeout = delay - this._timerArg = arg + // delete last betweenPairSeparator + return result.slice(0, -1) + } +} - this.refresh() +class MockCallHistory { + logs = [] + + calls () { + return this.logs } - /** - * Sets the timer's start time to the current time, and reschedules the timer - * to call its callback at the previously specified duration adjusted to the - * current time. - * Using this on a timer that has already called its callback will reactivate - * the timer. - * - * @returns {void} - */ - refresh () { - // In the special case that the timer is not in the list of active timers, - // add it back to the array to be processed in the next tick by the onTick - // function. - if (this._state === NOT_IN_LIST) { - fastTimers.push(this) + firstCall () { + return this.logs.at(0) + } + + lastCall () { + return this.logs.at(-1) + } + + nthCall (number) { + if (typeof number !== 'number') { + throw new InvalidArgumentError('nthCall must be called with a number') + } + if (!Number.isInteger(number)) { + throw new InvalidArgumentError('nthCall must be called with an integer') + } + if (Math.sign(number) !== 1) { + throw new InvalidArgumentError('nthCall must be called with a positive value. use firstCall or lastCall instead') } - // If the timer is the only active timer, refresh the fastNowTimeout for - // better resolution. - if (!fastNowTimeout || fastTimers.length === 1) { - refreshTimeout() + // non zero based index. this is more human readable + return this.logs.at(number - 1) + } + + filterCalls (criteria, options) { + // perf + if (this.logs.length === 0) { + return this.logs + } + if (typeof criteria === 'function') { + return this.logs.filter(criteria) + } + if (criteria instanceof RegExp) { + return this.logs.filter((log) => { + return criteria.test(log.toString()) + }) } + if (typeof criteria === 'object' && criteria !== null) { + // no criteria - returning all logs + if (Object.keys(criteria).length === 0) { + return this.logs + } - // Setting the state to PENDING will cause the timer to be reset in the - // next tick by the onTick function. - this._state = PENDING + const finalOptions = { operator: 'OR', ...buildAndValidateFilterCallsOptions(options) } + + let maybeDuplicatedLogsFiltered = [] + if ('protocol' in criteria) { + maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.protocol, finalOptions, this.filterCallsByProtocol, maybeDuplicatedLogsFiltered) + } + if ('host' in criteria) { + maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.host, finalOptions, this.filterCallsByHost, maybeDuplicatedLogsFiltered) + } + if ('port' in criteria) { + maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.port, finalOptions, this.filterCallsByPort, maybeDuplicatedLogsFiltered) + } + if ('origin' in criteria) { + maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.origin, finalOptions, this.filterCallsByOrigin, maybeDuplicatedLogsFiltered) + } + if ('path' in criteria) { + maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.path, finalOptions, this.filterCallsByPath, maybeDuplicatedLogsFiltered) + } + if ('hash' in criteria) { + maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.hash, finalOptions, this.filterCallsByHash, maybeDuplicatedLogsFiltered) + } + if ('fullUrl' in criteria) { + maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.fullUrl, finalOptions, this.filterCallsByFullUrl, maybeDuplicatedLogsFiltered) + } + if ('method' in criteria) { + maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.method, finalOptions, this.filterCallsByMethod, maybeDuplicatedLogsFiltered) + } + + const uniqLogsFiltered = [...new Set(maybeDuplicatedLogsFiltered)] + + return uniqLogsFiltered + } + + throw new InvalidArgumentError('criteria parameter should be one of function, regexp, or object') } - /** - * The `clear` method cancels the timer, preventing it from executing. - * - * @returns {void} - * @private - */ + filterCallsByProtocol = makeFilterCalls.call(this, 'protocol') + + filterCallsByHost = makeFilterCalls.call(this, 'host') + + filterCallsByPort = makeFilterCalls.call(this, 'port') + + filterCallsByOrigin = makeFilterCalls.call(this, 'origin') + + filterCallsByPath = makeFilterCalls.call(this, 'path') + + filterCallsByHash = makeFilterCalls.call(this, 'hash') + + filterCallsByFullUrl = makeFilterCalls.call(this, 'fullUrl') + + filterCallsByMethod = makeFilterCalls.call(this, 'method') + clear () { - // Set the state to TO_BE_CLEARED to mark the timer for removal in the next - // tick by the onTick function. - this._state = TO_BE_CLEARED + this.logs = [] + } - // Reset the _idleStart value to -1 to indicate that the timer is no longer - // active. - this._idleStart = -1 + [kMockCallHistoryAddLog] (requestInit) { + const log = new MockCallHistoryLog(requestInit) + + this.logs.push(log) + + return log } -} -/** - * This module exports a setTimeout and clearTimeout function that can be - * used as a drop-in replacement for the native functions. - */ -module.exports = { - /** - * The setTimeout() method sets a timer which executes a function once the - * timer expires. - * @param {Function} callback A function to be executed after the timer - * expires. - * @param {number} delay The time, in milliseconds that the timer should - * wait before the specified function or code is executed. - * @param {*} [arg] An optional argument to be passed to the callback function - * when the timer expires. - * @returns {NodeJS.Timeout|FastTimer} - */ - setTimeout (callback, delay, arg) { - // If the delay is less than or equal to the RESOLUTION_MS value return a - // native Node.js Timer instance. - return delay <= RESOLUTION_MS - ? setTimeout(callback, delay, arg) - : new FastTimer(callback, delay, arg) - }, - /** - * The clearTimeout method cancels an instantiated Timer previously created - * by calling setTimeout. - * - * @param {NodeJS.Timeout|FastTimer} timeout - */ - clearTimeout (timeout) { - // If the timeout is a FastTimer, call its own clear method. - if (timeout[kFastTimer]) { - /** - * @type {FastTimer} - */ - timeout.clear() - // Otherwise it is an instance of a native NodeJS.Timeout, so call the - // Node.js native clearTimeout function. - } else { - clearTimeout(timeout) + * [Symbol.iterator] () { + for (const log of this.calls()) { + yield log } - }, - /** - * The setFastTimeout() method sets a fastTimer which executes a function once - * the timer expires. - * @param {Function} callback A function to be executed after the timer - * expires. - * @param {number} delay The time, in milliseconds that the timer should - * wait before the specified function or code is executed. - * @param {*} [arg] An optional argument to be passed to the callback function - * when the timer expires. - * @returns {FastTimer} - */ - setFastTimeout (callback, delay, arg) { - return new FastTimer(callback, delay, arg) - }, - /** - * The clearTimeout method cancels an instantiated FastTimer previously - * created by calling setFastTimeout. - * - * @param {FastTimer} timeout - */ - clearFastTimeout (timeout) { - timeout.clear() - }, - /** - * The now method returns the value of the internal fast timer clock. - * - * @returns {number} - */ - now () { - return fastNow - }, - /** - * Trigger the onTick function to process the fastTimers array. - * Exported for testing purposes only. - * Marking as deprecated to discourage any use outside of testing. - * @deprecated - * @param {number} [delay=0] The delay in milliseconds to add to the now value. - */ - tick (delay = 0) { - fastNow += delay - RESOLUTION_MS + 1 - onTick() - onTick() - }, - /** - * Reset FastTimers. - * Exported for testing purposes only. - * Marking as deprecated to discourage any use outside of testing. - * @deprecated - */ - reset () { - fastNow = 0 - fastTimers.length = 0 - clearTimeout(fastNowTimeout) - fastNowTimeout = null - }, - /** - * Exporting for testing purposes only. - * Marking as deprecated to discourage any use outside of testing. - * @deprecated - */ - kFastTimer + } } +module.exports.MockCallHistory = MockCallHistory +module.exports.MockCallHistoryLog = MockCallHistoryLog + /***/ }), -/***/ 6769: +/***/ 5627: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -const assert = __nccwpck_require__(4589) - -const { kConstruct } = __nccwpck_require__(9562) -const { urlEquals, getFieldValues } = __nccwpck_require__(55) -const { kEnumerableProperty, isDisturbed } = __nccwpck_require__(983) -const { webidl } = __nccwpck_require__(2318) -const { cloneResponse, fromInnerResponse, getResponseState } = __nccwpck_require__(9294) -const { Request, fromInnerRequest, getRequestState } = __nccwpck_require__(8140) -const { fetching } = __nccwpck_require__(6377) -const { urlIsHttpHttpsScheme, readAllBytes } = __nccwpck_require__(8913) -const { createDeferredPromise } = __nccwpck_require__(9797) +const { promisify } = __nccwpck_require__(7975) +const Client = __nccwpck_require__(1115) +const { buildMockDispatch } = __nccwpck_require__(5427) +const { + kDispatches, + kMockAgent, + kClose, + kOriginalClose, + kOrigin, + kOriginalDispatch, + kConnected, + kIgnoreTrailingSlash +} = __nccwpck_require__(9823) +const { MockInterceptor } = __nccwpck_require__(3085) +const Symbols = __nccwpck_require__(8261) +const { InvalidArgumentError } = __nccwpck_require__(5093) /** - * @see https://w3c.github.io/ServiceWorker/#dfn-cache-batch-operation - * @typedef {Object} CacheBatchOperation - * @property {'delete' | 'put'} type - * @property {any} request - * @property {any} response - * @property {import('../../../types/cache').CacheQueryOptions} options + * MockClient provides an API that extends the Client to influence the mockDispatches. */ +class MockClient extends Client { + constructor (origin, opts) { + if (!opts || !opts.agent || typeof opts.agent.dispatch !== 'function') { + throw new InvalidArgumentError('Argument opts.agent must implement Agent') + } -/** - * @see https://w3c.github.io/ServiceWorker/#dfn-request-response-list - * @typedef {[any, any][]} requestResponseList - */ + super(origin, opts) + + this[kMockAgent] = opts.agent + this[kOrigin] = origin + this[kIgnoreTrailingSlash] = opts.ignoreTrailingSlash ?? false + this[kDispatches] = [] + this[kConnected] = 1 + this[kOriginalDispatch] = this.dispatch + this[kOriginalClose] = this.close.bind(this) + + this.dispatch = buildMockDispatch.call(this) + this.close = this[kClose] + } + + get [Symbols.kConnected] () { + return this[kConnected] + } -class Cache { /** - * @see https://w3c.github.io/ServiceWorker/#dfn-relevant-request-response-list - * @type {requestResponseList} + * Sets up the base interceptor for mocking replies from undici. */ - #relevantRequestResponseList + intercept (opts) { + return new MockInterceptor( + opts && { ignoreTrailingSlash: this[kIgnoreTrailingSlash], ...opts }, + this[kDispatches] + ) + } - constructor () { - if (arguments[0] !== kConstruct) { - webidl.illegalConstructor() - } + cleanMocks () { + this[kDispatches] = [] + } - webidl.util.markAsUncloneable(this) - this.#relevantRequestResponseList = arguments[1] + async [kClose] () { + await promisify(this[kOriginalClose])() + this[kConnected] = 0 + this[kMockAgent][Symbols.kClients].delete(this[kOrigin]) } +} - async match (request, options = {}) { - webidl.brandCheck(this, Cache) +module.exports = MockClient - const prefix = 'Cache.match' - webidl.argumentLengthCheck(arguments, 1, prefix) - request = webidl.converters.RequestInfo(request) - options = webidl.converters.CacheQueryOptions(options, prefix, 'options') +/***/ }), - const p = this.#internalMatchAll(request, options, 1) +/***/ 3831: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - if (p.length === 0) { - return - } - return p[0] - } - async matchAll (request = undefined, options = {}) { - webidl.brandCheck(this, Cache) +const { UndiciError } = __nccwpck_require__(5093) - const prefix = 'Cache.matchAll' - if (request !== undefined) request = webidl.converters.RequestInfo(request) - options = webidl.converters.CacheQueryOptions(options, prefix, 'options') +const kMockNotMatchedError = Symbol.for('undici.error.UND_MOCK_ERR_MOCK_NOT_MATCHED') - return this.#internalMatchAll(request, options) +/** + * The request does not match any registered mock dispatches. + */ +class MockNotMatchedError extends UndiciError { + constructor (message) { + super(message) + this.name = 'MockNotMatchedError' + this.message = message || 'The request does not match any registered mock dispatches' + this.code = 'UND_MOCK_ERR_MOCK_NOT_MATCHED' } - async add (request) { - webidl.brandCheck(this, Cache) - - const prefix = 'Cache.add' - webidl.argumentLengthCheck(arguments, 1, prefix) + static [Symbol.hasInstance] (instance) { + return instance && instance[kMockNotMatchedError] === true + } - request = webidl.converters.RequestInfo(request) + get [kMockNotMatchedError] () { + return true + } +} - // 1. - const requests = [request] +module.exports = { + MockNotMatchedError +} - // 2. - const responseArrayPromise = this.addAll(requests) - // 3. - return await responseArrayPromise - } +/***/ }), - async addAll (requests) { - webidl.brandCheck(this, Cache) +/***/ 3085: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - const prefix = 'Cache.addAll' - webidl.argumentLengthCheck(arguments, 1, prefix) - // 1. - const responsePromises = [] - // 2. - const requestList = [] +const { getResponseData, buildKey, addMockDispatch } = __nccwpck_require__(5427) +const { + kDispatches, + kDispatchKey, + kDefaultHeaders, + kDefaultTrailers, + kContentLength, + kMockDispatch, + kIgnoreTrailingSlash +} = __nccwpck_require__(9823) +const { InvalidArgumentError } = __nccwpck_require__(5093) +const { serializePathWithQuery } = __nccwpck_require__(2550) - // 3. - for (let request of requests) { - if (request === undefined) { - throw webidl.errors.conversionFailed({ - prefix, - argument: 'Argument 1', - types: ['undefined is not allowed'] - }) - } +/** + * Defines the scope API for an interceptor reply + */ +class MockScope { + constructor (mockDispatch) { + this[kMockDispatch] = mockDispatch + } - request = webidl.converters.RequestInfo(request) + /** + * Delay a reply by a set amount in ms. + */ + delay (waitInMs) { + if (typeof waitInMs !== 'number' || !Number.isInteger(waitInMs) || waitInMs <= 0) { + throw new InvalidArgumentError('waitInMs must be a valid integer > 0') + } - if (typeof request === 'string') { - continue - } + this[kMockDispatch].delay = waitInMs + return this + } - // 3.1 - const r = getRequestState(request) + /** + * For a defined reply, never mark as consumed. + */ + persist () { + this[kMockDispatch].persist = true + return this + } - // 3.2 - if (!urlIsHttpHttpsScheme(r.url) || r.method !== 'GET') { - throw webidl.errors.exception({ - header: prefix, - message: 'Expected http/s scheme when method is not GET.' - }) - } + /** + * Allow one to define a reply for a set amount of matching requests. + */ + times (repeatTimes) { + if (typeof repeatTimes !== 'number' || !Number.isInteger(repeatTimes) || repeatTimes <= 0) { + throw new InvalidArgumentError('repeatTimes must be a valid integer > 0') } - // 4. - /** @type {ReturnType[]} */ - const fetchControllers = [] - - // 5. - for (const request of requests) { - // 5.1 - const r = getRequestState(new Request(request)) - - // 5.2 - if (!urlIsHttpHttpsScheme(r.url)) { - throw webidl.errors.exception({ - header: prefix, - message: 'Expected http/s scheme.' - }) - } - - // 5.4 - r.initiator = 'fetch' - r.destination = 'subresource' - - // 5.5 - requestList.push(r) - - // 5.6 - const responsePromise = createDeferredPromise() - - // 5.7 - fetchControllers.push(fetching({ - request: r, - processResponse (response) { - // 1. - if (response.type === 'error' || response.status === 206 || response.status < 200 || response.status > 299) { - responsePromise.reject(webidl.errors.exception({ - header: 'Cache.addAll', - message: 'Received an invalid status code or the request failed.' - })) - } else if (response.headersList.contains('vary')) { // 2. - // 2.1 - const fieldValues = getFieldValues(response.headersList.get('vary')) - - // 2.2 - for (const fieldValue of fieldValues) { - // 2.2.1 - if (fieldValue === '*') { - responsePromise.reject(webidl.errors.exception({ - header: 'Cache.addAll', - message: 'invalid vary field value' - })) - - for (const controller of fetchControllers) { - controller.abort() - } - - return - } - } - } - }, - processResponseEndOfBody (response) { - // 1. - if (response.aborted) { - responsePromise.reject(new DOMException('aborted', 'AbortError')) - return - } - - // 2. - responsePromise.resolve(response) - } - })) + this[kMockDispatch].times = repeatTimes + return this + } +} - // 5.8 - responsePromises.push(responsePromise.promise) +/** + * Defines an interceptor for a Mock + */ +class MockInterceptor { + constructor (opts, mockDispatches) { + if (typeof opts !== 'object') { + throw new InvalidArgumentError('opts must be an object') } - - // 6. - const p = Promise.all(responsePromises) - - // 7. - const responses = await p - - // 7.1 - const operations = [] - - // 7.2 - let index = 0 - - // 7.3 - for (const response of responses) { - // 7.3.1 - /** @type {CacheBatchOperation} */ - const operation = { - type: 'put', // 7.3.2 - request: requestList[index], // 7.3.3 - response // 7.3.4 - } - - operations.push(operation) // 7.3.5 - - index++ // 7.3.6 + if (typeof opts.path === 'undefined') { + throw new InvalidArgumentError('opts.path must be defined') } - - // 7.5 - const cacheJobPromise = createDeferredPromise() - - // 7.6.1 - let errorData = null - - // 7.6.2 - try { - this.#batchCacheOperations(operations) - } catch (e) { - errorData = e + if (typeof opts.method === 'undefined') { + opts.method = 'GET' } - - // 7.6.3 - queueMicrotask(() => { - // 7.6.3.1 - if (errorData === null) { - cacheJobPromise.resolve(undefined) + // See https://github.com/nodejs/undici/issues/1245 + // As per RFC 3986, clients are not supposed to send URI + // fragments to servers when they retrieve a document, + if (typeof opts.path === 'string') { + if (opts.query) { + opts.path = serializePathWithQuery(opts.path, opts.query) } else { - // 7.6.3.2 - cacheJobPromise.reject(errorData) + // Matches https://github.com/nodejs/undici/blob/main/lib/web/fetch/index.js#L1811 + const parsedURL = new URL(opts.path, 'data://') + opts.path = parsedURL.pathname + parsedURL.search } - }) + } + if (typeof opts.method === 'string') { + opts.method = opts.method.toUpperCase() + } - // 7.7 - return cacheJobPromise.promise + this[kDispatchKey] = buildKey(opts) + this[kDispatches] = mockDispatches + this[kIgnoreTrailingSlash] = opts.ignoreTrailingSlash ?? false + this[kDefaultHeaders] = {} + this[kDefaultTrailers] = {} + this[kContentLength] = false } - async put (request, response) { - webidl.brandCheck(this, Cache) - - const prefix = 'Cache.put' - webidl.argumentLengthCheck(arguments, 2, prefix) - - request = webidl.converters.RequestInfo(request) - response = webidl.converters.Response(response, prefix, 'response') + createMockScopeDispatchData ({ statusCode, data, responseOptions }) { + const responseData = getResponseData(data) + const contentLength = this[kContentLength] ? { 'content-length': responseData.length } : {} + const headers = { ...this[kDefaultHeaders], ...contentLength, ...responseOptions.headers } + const trailers = { ...this[kDefaultTrailers], ...responseOptions.trailers } - // 1. - let innerRequest = null + return { statusCode, data, headers, trailers } + } - // 2. - if (webidl.is.Request(request)) { - innerRequest = getRequestState(request) - } else { // 3. - innerRequest = getRequestState(new Request(request)) + validateReplyParameters (replyParameters) { + if (typeof replyParameters.statusCode === 'undefined') { + throw new InvalidArgumentError('statusCode must be defined') } - - // 4. - if (!urlIsHttpHttpsScheme(innerRequest.url) || innerRequest.method !== 'GET') { - throw webidl.errors.exception({ - header: prefix, - message: 'Expected an http/s scheme when method is not GET' - }) + if (typeof replyParameters.responseOptions !== 'object' || replyParameters.responseOptions === null) { + throw new InvalidArgumentError('responseOptions must be an object') } + } - // 5. - const innerResponse = getResponseState(response) - - // 6. - if (innerResponse.status === 206) { - throw webidl.errors.exception({ - header: prefix, - message: 'Got 206 status' - }) - } + /** + * Mock an undici request with a defined reply. + */ + reply (replyOptionsCallbackOrStatusCode) { + // Values of reply aren't available right now as they + // can only be available when the reply callback is invoked. + if (typeof replyOptionsCallbackOrStatusCode === 'function') { + // We'll first wrap the provided callback in another function, + // this function will properly resolve the data from the callback + // when invoked. + const wrappedDefaultsCallback = (opts) => { + // Our reply options callback contains the parameter for statusCode, data and options. + const resolvedData = replyOptionsCallbackOrStatusCode(opts) - // 7. - if (innerResponse.headersList.contains('vary')) { - // 7.1. - const fieldValues = getFieldValues(innerResponse.headersList.get('vary')) + // Check if it is in the right format + if (typeof resolvedData !== 'object' || resolvedData === null) { + throw new InvalidArgumentError('reply options callback must return an object') + } - // 7.2. - for (const fieldValue of fieldValues) { - // 7.2.1 - if (fieldValue === '*') { - throw webidl.errors.exception({ - header: prefix, - message: 'Got * vary field value' - }) + const replyParameters = { data: '', responseOptions: {}, ...resolvedData } + this.validateReplyParameters(replyParameters) + // Since the values can be obtained immediately we return them + // from this higher order function that will be resolved later. + return { + ...this.createMockScopeDispatchData(replyParameters) } } - } - // 8. - if (innerResponse.body && (isDisturbed(innerResponse.body.stream) || innerResponse.body.stream.locked)) { - throw webidl.errors.exception({ - header: prefix, - message: 'Response body is locked or disturbed' - }) + // Add usual dispatch data, but this time set the data parameter to function that will eventually provide data. + const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], wrappedDefaultsCallback, { ignoreTrailingSlash: this[kIgnoreTrailingSlash] }) + return new MockScope(newMockDispatch) } - // 9. - const clonedResponse = cloneResponse(innerResponse) - - // 10. - const bodyReadPromise = createDeferredPromise() - - // 11. - if (innerResponse.body != null) { - // 11.1 - const stream = innerResponse.body.stream - - // 11.2 - const reader = stream.getReader() - - // 11.3 - readAllBytes(reader, bodyReadPromise.resolve, bodyReadPromise.reject) - } else { - bodyReadPromise.resolve(undefined) + // We can have either one or three parameters, if we get here, + // we should have 1-3 parameters. So we spread the arguments of + // this function to obtain the parameters, since replyData will always + // just be the statusCode. + const replyParameters = { + statusCode: replyOptionsCallbackOrStatusCode, + data: arguments[1] === undefined ? '' : arguments[1], + responseOptions: arguments[2] === undefined ? {} : arguments[2] } + this.validateReplyParameters(replyParameters) - // 12. - /** @type {CacheBatchOperation[]} */ - const operations = [] + // Send in-already provided data like usual + const dispatchData = this.createMockScopeDispatchData(replyParameters) + const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], dispatchData, { ignoreTrailingSlash: this[kIgnoreTrailingSlash] }) + return new MockScope(newMockDispatch) + } - // 13. - /** @type {CacheBatchOperation} */ - const operation = { - type: 'put', // 14. - request: innerRequest, // 15. - response: clonedResponse // 16. + /** + * Mock an undici request with a defined error. + */ + replyWithError (error) { + if (typeof error === 'undefined') { + throw new InvalidArgumentError('error must be defined') } - // 17. - operations.push(operation) - - // 19. - const bytes = await bodyReadPromise.promise + const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], { error }, { ignoreTrailingSlash: this[kIgnoreTrailingSlash] }) + return new MockScope(newMockDispatch) + } - if (clonedResponse.body != null) { - clonedResponse.body.source = bytes + /** + * Set default reply headers on the interceptor for subsequent replies + */ + defaultReplyHeaders (headers) { + if (typeof headers === 'undefined') { + throw new InvalidArgumentError('headers must be defined') } - // 19.1 - const cacheJobPromise = createDeferredPromise() - - // 19.2.1 - let errorData = null + this[kDefaultHeaders] = headers + return this + } - // 19.2.2 - try { - this.#batchCacheOperations(operations) - } catch (e) { - errorData = e + /** + * Set default reply trailers on the interceptor for subsequent replies + */ + defaultReplyTrailers (trailers) { + if (typeof trailers === 'undefined') { + throw new InvalidArgumentError('trailers must be defined') } - // 19.2.3 - queueMicrotask(() => { - // 19.2.3.1 - if (errorData === null) { - cacheJobPromise.resolve() - } else { // 19.2.3.2 - cacheJobPromise.reject(errorData) - } - }) - - return cacheJobPromise.promise + this[kDefaultTrailers] = trailers + return this } - async delete (request, options = {}) { - webidl.brandCheck(this, Cache) + /** + * Set reply content length header for replies on the interceptor + */ + replyContentLength () { + this[kContentLength] = true + return this + } +} - const prefix = 'Cache.delete' - webidl.argumentLengthCheck(arguments, 1, prefix) +module.exports.MockInterceptor = MockInterceptor +module.exports.MockScope = MockScope - request = webidl.converters.RequestInfo(request) - options = webidl.converters.CacheQueryOptions(options, prefix, 'options') - /** - * @type {Request} - */ - let r = null +/***/ }), - if (webidl.is.Request(request)) { - r = getRequestState(request) +/***/ 6466: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - if (r.method !== 'GET' && !options.ignoreMethod) { - return false - } - } else { - assert(typeof request === 'string') - r = getRequestState(new Request(request)) - } - /** @type {CacheBatchOperation[]} */ - const operations = [] +const { promisify } = __nccwpck_require__(7975) +const Pool = __nccwpck_require__(8034) +const { buildMockDispatch } = __nccwpck_require__(5427) +const { + kDispatches, + kMockAgent, + kClose, + kOriginalClose, + kOrigin, + kOriginalDispatch, + kConnected, + kIgnoreTrailingSlash +} = __nccwpck_require__(9823) +const { MockInterceptor } = __nccwpck_require__(3085) +const Symbols = __nccwpck_require__(8261) +const { InvalidArgumentError } = __nccwpck_require__(5093) - /** @type {CacheBatchOperation} */ - const operation = { - type: 'delete', - request: r, - options +/** + * MockPool provides an API that extends the Pool to influence the mockDispatches. + */ +class MockPool extends Pool { + constructor (origin, opts) { + if (!opts || !opts.agent || typeof opts.agent.dispatch !== 'function') { + throw new InvalidArgumentError('Argument opts.agent must implement Agent') } - operations.push(operation) - - const cacheJobPromise = createDeferredPromise() - - let errorData = null - let requestResponses + super(origin, opts) - try { - requestResponses = this.#batchCacheOperations(operations) - } catch (e) { - errorData = e - } + this[kMockAgent] = opts.agent + this[kOrigin] = origin + this[kIgnoreTrailingSlash] = opts.ignoreTrailingSlash ?? false + this[kDispatches] = [] + this[kConnected] = 1 + this[kOriginalDispatch] = this.dispatch + this[kOriginalClose] = this.close.bind(this) - queueMicrotask(() => { - if (errorData === null) { - cacheJobPromise.resolve(!!requestResponses?.length) - } else { - cacheJobPromise.reject(errorData) - } - }) + this.dispatch = buildMockDispatch.call(this) + this.close = this[kClose] + } - return cacheJobPromise.promise + get [Symbols.kConnected] () { + return this[kConnected] } /** - * @see https://w3c.github.io/ServiceWorker/#dom-cache-keys - * @param {any} request - * @param {import('../../../types/cache').CacheQueryOptions} options - * @returns {Promise} + * Sets up the base interceptor for mocking replies from undici. */ - async keys (request = undefined, options = {}) { - webidl.brandCheck(this, Cache) + intercept (opts) { + return new MockInterceptor( + opts && { ignoreTrailingSlash: this[kIgnoreTrailingSlash], ...opts }, + this[kDispatches] + ) + } - const prefix = 'Cache.keys' + cleanMocks () { + this[kDispatches] = [] + } - if (request !== undefined) request = webidl.converters.RequestInfo(request) - options = webidl.converters.CacheQueryOptions(options, prefix, 'options') + async [kClose] () { + await promisify(this[kOriginalClose])() + this[kConnected] = 0 + this[kMockAgent][Symbols.kClients].delete(this[kOrigin]) + } +} - // 1. - let r = null +module.exports = MockPool - // 2. - if (request !== undefined) { - // 2.1 - if (webidl.is.Request(request)) { - // 2.1.1 - r = getRequestState(request) - // 2.1.2 - if (r.method !== 'GET' && !options.ignoreMethod) { - return [] - } - } else if (typeof request === 'string') { // 2.2 - r = getRequestState(new Request(request)) - } - } +/***/ }), - // 4. - const promise = createDeferredPromise() +/***/ 9823: +/***/ ((module) => { - // 5. - // 5.1 - const requests = [] - // 5.2 - if (request === undefined) { - // 5.2.1 - for (const requestResponse of this.#relevantRequestResponseList) { - // 5.2.1.1 - requests.push(requestResponse[0]) - } - } else { // 5.3 - // 5.3.1 - const requestResponses = this.#queryCache(r, options) - // 5.3.2 - for (const requestResponse of requestResponses) { - // 5.3.2.1 - requests.push(requestResponse[0]) - } - } +module.exports = { + kAgent: Symbol('agent'), + kOptions: Symbol('options'), + kFactory: Symbol('factory'), + kDispatches: Symbol('dispatches'), + kDispatchKey: Symbol('dispatch key'), + kDefaultHeaders: Symbol('default headers'), + kDefaultTrailers: Symbol('default trailers'), + kContentLength: Symbol('content length'), + kMockAgent: Symbol('mock agent'), + kMockAgentSet: Symbol('mock agent set'), + kMockAgentGet: Symbol('mock agent get'), + kMockDispatch: Symbol('mock dispatch'), + kClose: Symbol('close'), + kOriginalClose: Symbol('original agent close'), + kOriginalDispatch: Symbol('original dispatch'), + kOrigin: Symbol('origin'), + kIsMockActive: Symbol('is mock active'), + kNetConnect: Symbol('net connect'), + kGetNetConnect: Symbol('get net connect'), + kConnected: Symbol('connected'), + kIgnoreTrailingSlash: Symbol('ignore trailing slash'), + kMockAgentMockCallHistoryInstance: Symbol('mock agent mock call history name'), + kMockAgentRegisterCallHistory: Symbol('mock agent register mock call history'), + kMockAgentAddCallHistoryLog: Symbol('mock agent add call history log'), + kMockAgentIsCallHistoryEnabled: Symbol('mock agent is call history enabled'), + kMockAgentAcceptsNonStandardSearchParameters: Symbol('mock agent accepts non standard search parameters'), + kMockCallHistoryAddLog: Symbol('mock call history add log') +} - // 5.4 - queueMicrotask(() => { - // 5.4.1 - const requestList = [] - // 5.4.2 - for (const request of requests) { - const requestObject = fromInnerRequest( - request, - undefined, - new AbortController().signal, - 'immutable' - ) - // 5.4.2.1 - requestList.push(requestObject) - } +/***/ }), - // 5.4.3 - promise.resolve(Object.freeze(requestList)) - }) +/***/ 5427: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - return promise.promise + + +const { MockNotMatchedError } = __nccwpck_require__(3831) +const { + kDispatches, + kMockAgent, + kOriginalDispatch, + kOrigin, + kGetNetConnect +} = __nccwpck_require__(9823) +const { serializePathWithQuery } = __nccwpck_require__(2550) +const { STATUS_CODES } = __nccwpck_require__(7067) +const { + types: { + isPromise } +} = __nccwpck_require__(7975) +const { InvalidArgumentError } = __nccwpck_require__(5093) - /** - * @see https://w3c.github.io/ServiceWorker/#batch-cache-operations-algorithm - * @param {CacheBatchOperation[]} operations - * @returns {requestResponseList} - */ - #batchCacheOperations (operations) { - // 1. - const cache = this.#relevantRequestResponseList +function matchValue (match, value) { + if (typeof match === 'string') { + return match === value + } + if (match instanceof RegExp) { + return match.test(value) + } + if (typeof match === 'function') { + return match(value) === true + } + return false +} - // 2. - const backupCache = [...cache] +function lowerCaseEntries (headers) { + return Object.fromEntries( + Object.entries(headers).map(([headerName, headerValue]) => { + return [headerName.toLocaleLowerCase(), headerValue] + }) + ) +} - // 3. - const addedItems = [] +/** + * @param {import('../../index').Headers|string[]|Record} headers + * @param {string} key + */ +function getHeaderByName (headers, key) { + if (Array.isArray(headers)) { + for (let i = 0; i < headers.length; i += 2) { + if (headers[i].toLocaleLowerCase() === key.toLocaleLowerCase()) { + return headers[i + 1] + } + } - // 4.1 - const resultList = [] + return undefined + } else if (typeof headers.get === 'function') { + return headers.get(key) + } else { + return lowerCaseEntries(headers)[key.toLocaleLowerCase()] + } +} - try { - // 4.2 - for (const operation of operations) { - // 4.2.1 - if (operation.type !== 'delete' && operation.type !== 'put') { - throw webidl.errors.exception({ - header: 'Cache.#batchCacheOperations', - message: 'operation type does not match "delete" or "put"' - }) - } +/** @param {string[]} headers */ +function buildHeadersFromArray (headers) { // fetch HeadersList + const clone = headers.slice() + const entries = [] + for (let index = 0; index < clone.length; index += 2) { + entries.push([clone[index], clone[index + 1]]) + } + return Object.fromEntries(entries) +} - // 4.2.2 - if (operation.type === 'delete' && operation.response != null) { - throw webidl.errors.exception({ - header: 'Cache.#batchCacheOperations', - message: 'delete operation should not have an associated response' - }) - } +function matchHeaders (mockDispatch, headers) { + if (typeof mockDispatch.headers === 'function') { + if (Array.isArray(headers)) { // fetch HeadersList + headers = buildHeadersFromArray(headers) + } + return mockDispatch.headers(headers ? lowerCaseEntries(headers) : {}) + } + if (typeof mockDispatch.headers === 'undefined') { + return true + } + if (typeof headers !== 'object' || typeof mockDispatch.headers !== 'object') { + return false + } - // 4.2.3 - if (this.#queryCache(operation.request, operation.options, addedItems).length) { - throw new DOMException('???', 'InvalidStateError') - } + for (const [matchHeaderName, matchHeaderValue] of Object.entries(mockDispatch.headers)) { + const headerValue = getHeaderByName(headers, matchHeaderName) - // 4.2.4 - let requestResponses + if (!matchValue(matchHeaderValue, headerValue)) { + return false + } + } + return true +} - // 4.2.5 - if (operation.type === 'delete') { - // 4.2.5.1 - requestResponses = this.#queryCache(operation.request, operation.options) +function normalizeSearchParams (query) { + if (typeof query !== 'string') { + return query + } - // TODO: the spec is wrong, this is needed to pass WPTs - if (requestResponses.length === 0) { - return [] - } + const originalQp = new URLSearchParams(query) + const normalizedQp = new URLSearchParams() - // 4.2.5.2 - for (const requestResponse of requestResponses) { - const idx = cache.indexOf(requestResponse) - assert(idx !== -1) + for (let [key, value] of originalQp.entries()) { + key = key.replace('[]', '') - // 4.2.5.2.1 - cache.splice(idx, 1) - } - } else if (operation.type === 'put') { // 4.2.6 - // 4.2.6.1 - if (operation.response == null) { - throw webidl.errors.exception({ - header: 'Cache.#batchCacheOperations', - message: 'put operation should have an associated response' - }) - } + const valueRepresentsString = /^(['"]).*\1$/.test(value) + if (valueRepresentsString) { + normalizedQp.append(key, value) + continue + } - // 4.2.6.2 - const r = operation.request + if (value.includes(',')) { + const values = value.split(',') + for (const v of values) { + normalizedQp.append(key, v) + } + continue + } - // 4.2.6.3 - if (!urlIsHttpHttpsScheme(r.url)) { - throw webidl.errors.exception({ - header: 'Cache.#batchCacheOperations', - message: 'expected http or https scheme' - }) - } + normalizedQp.append(key, value) + } - // 4.2.6.4 - if (r.method !== 'GET') { - throw webidl.errors.exception({ - header: 'Cache.#batchCacheOperations', - message: 'not get method' - }) - } + return normalizedQp +} - // 4.2.6.5 - if (operation.options != null) { - throw webidl.errors.exception({ - header: 'Cache.#batchCacheOperations', - message: 'options must not be defined' - }) - } +function safeUrl (path) { + if (typeof path !== 'string') { + return path + } + const pathSegments = path.split('?', 3) + if (pathSegments.length !== 2) { + return path + } - // 4.2.6.6 - requestResponses = this.#queryCache(operation.request) + const qp = new URLSearchParams(pathSegments.pop()) + qp.sort() + return [...pathSegments, qp.toString()].join('?') +} - // 4.2.6.7 - for (const requestResponse of requestResponses) { - const idx = cache.indexOf(requestResponse) - assert(idx !== -1) +function matchKey (mockDispatch, { path, method, body, headers }) { + const pathMatch = matchValue(mockDispatch.path, path) + const methodMatch = matchValue(mockDispatch.method, method) + const bodyMatch = typeof mockDispatch.body !== 'undefined' ? matchValue(mockDispatch.body, body) : true + const headersMatch = matchHeaders(mockDispatch, headers) + return pathMatch && methodMatch && bodyMatch && headersMatch +} - // 4.2.6.7.1 - cache.splice(idx, 1) - } +function getResponseData (data) { + if (Buffer.isBuffer(data)) { + return data + } else if (data instanceof Uint8Array) { + return data + } else if (data instanceof ArrayBuffer) { + return data + } else if (typeof data === 'object') { + return JSON.stringify(data) + } else if (data) { + return data.toString() + } else { + return '' + } +} - // 4.2.6.8 - cache.push([operation.request, operation.response]) +function getMockDispatch (mockDispatches, key) { + const basePath = key.query ? serializePathWithQuery(key.path, key.query) : key.path + const resolvedPath = typeof basePath === 'string' ? safeUrl(basePath) : basePath - // 4.2.6.10 - addedItems.push([operation.request, operation.response]) - } + const resolvedPathWithoutTrailingSlash = removeTrailingSlash(resolvedPath) - // 4.2.7 - resultList.push([operation.request, operation.response]) - } + // Match path + let matchedMockDispatches = mockDispatches + .filter(({ consumed }) => !consumed) + .filter(({ path, ignoreTrailingSlash }) => { + return ignoreTrailingSlash + ? matchValue(removeTrailingSlash(safeUrl(path)), resolvedPathWithoutTrailingSlash) + : matchValue(safeUrl(path), resolvedPath) + }) + if (matchedMockDispatches.length === 0) { + throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`) + } - // 4.3 - return resultList - } catch (e) { // 5. - // 5.1 - this.#relevantRequestResponseList.length = 0 + // Match method + matchedMockDispatches = matchedMockDispatches.filter(({ method }) => matchValue(method, key.method)) + if (matchedMockDispatches.length === 0) { + throw new MockNotMatchedError(`Mock dispatch not matched for method '${key.method}' on path '${resolvedPath}'`) + } - // 5.2 - this.#relevantRequestResponseList = backupCache + // Match body + matchedMockDispatches = matchedMockDispatches.filter(({ body }) => typeof body !== 'undefined' ? matchValue(body, key.body) : true) + if (matchedMockDispatches.length === 0) { + throw new MockNotMatchedError(`Mock dispatch not matched for body '${key.body}' on path '${resolvedPath}'`) + } - // 5.3 - throw e - } + // Match headers + matchedMockDispatches = matchedMockDispatches.filter((mockDispatch) => matchHeaders(mockDispatch, key.headers)) + if (matchedMockDispatches.length === 0) { + const headers = typeof key.headers === 'object' ? JSON.stringify(key.headers) : key.headers + throw new MockNotMatchedError(`Mock dispatch not matched for headers '${headers}' on path '${resolvedPath}'`) } - /** - * @see https://w3c.github.io/ServiceWorker/#query-cache - * @param {any} requestQuery - * @param {import('../../../types/cache').CacheQueryOptions} options - * @param {requestResponseList} targetStorage - * @returns {requestResponseList} - */ - #queryCache (requestQuery, options, targetStorage) { - /** @type {requestResponseList} */ - const resultList = [] + return matchedMockDispatches[0] +} - const storage = targetStorage ?? this.#relevantRequestResponseList +function addMockDispatch (mockDispatches, key, data, opts) { + const baseData = { timesInvoked: 0, times: 1, persist: false, consumed: false, ...opts } + const replyData = typeof data === 'function' ? { callback: data } : { ...data } + const newMockDispatch = { ...baseData, ...key, pending: true, data: { error: null, ...replyData } } + mockDispatches.push(newMockDispatch) + return newMockDispatch +} - for (const requestResponse of storage) { - const [cachedRequest, cachedResponse] = requestResponse - if (this.#requestMatchesCachedItem(requestQuery, cachedRequest, cachedResponse, options)) { - resultList.push(requestResponse) - } +function deleteMockDispatch (mockDispatches, key) { + const index = mockDispatches.findIndex(dispatch => { + if (!dispatch.consumed) { + return false } + return matchKey(dispatch, key) + }) + if (index !== -1) { + mockDispatches.splice(index, 1) + } +} - return resultList +/** + * @param {string} path Path to remove trailing slash from + */ +function removeTrailingSlash (path) { + while (path.endsWith('/')) { + path = path.slice(0, -1) } - /** - * @see https://w3c.github.io/ServiceWorker/#request-matches-cached-item-algorithm - * @param {any} requestQuery - * @param {any} request - * @param {any | null} response - * @param {import('../../../types/cache').CacheQueryOptions | undefined} options - * @returns {boolean} - */ - #requestMatchesCachedItem (requestQuery, request, response = null, options) { - // if (options?.ignoreMethod === false && request.method === 'GET') { - // return false - // } + if (path.length === 0) { + path = '/' + } - const queryURL = new URL(requestQuery.url) + return path +} - const cachedURL = new URL(request.url) +function buildKey (opts) { + const { path, method, body, headers, query } = opts - if (options?.ignoreSearch) { - cachedURL.search = '' + return { + path, + method, + body, + headers, + query + } +} - queryURL.search = '' +function generateKeyValues (data) { + const keys = Object.keys(data) + const result = [] + for (let i = 0; i < keys.length; ++i) { + const key = keys[i] + const value = data[key] + const name = Buffer.from(`${key}`) + if (Array.isArray(value)) { + for (let j = 0; j < value.length; ++j) { + result.push(name, Buffer.from(`${value[j]}`)) + } + } else { + result.push(name, Buffer.from(`${value}`)) } + } + return result +} - if (!urlEquals(queryURL, cachedURL, true)) { - return false - } +/** + * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Status + * @param {number} statusCode + */ +function getStatusText (statusCode) { + return STATUS_CODES[statusCode] || 'unknown' +} - if ( - response == null || - options?.ignoreVary || - !response.headersList.contains('vary') - ) { - return true - } +async function getResponse (body) { + const buffers = [] + for await (const data of body) { + buffers.push(data) + } + return Buffer.concat(buffers).toString('utf8') +} - const fieldValues = getFieldValues(response.headersList.get('vary')) +/** + * Mock dispatch function used to simulate undici dispatches + */ +function mockDispatch (opts, handler) { + // Get mock dispatch from built key + const key = buildKey(opts) + const mockDispatch = getMockDispatch(this[kDispatches], key) - for (const fieldValue of fieldValues) { - if (fieldValue === '*') { - return false - } + mockDispatch.timesInvoked++ - const requestValue = request.headersList.get(fieldValue) - const queryValue = requestQuery.headersList.get(fieldValue) + // Here's where we resolve a callback if a callback is present for the dispatch data. + if (mockDispatch.data.callback) { + mockDispatch.data = { ...mockDispatch.data, ...mockDispatch.data.callback(opts) } + } - // If one has the header and the other doesn't, or one has - // a different value than the other, return false - if (requestValue !== queryValue) { - return false - } - } + // Parse mockDispatch data + const { data: { statusCode, data, headers, trailers, error }, delay, persist } = mockDispatch + const { timesInvoked, times } = mockDispatch + + // If it's used up and not persistent, mark as consumed + mockDispatch.consumed = !persist && timesInvoked >= times + mockDispatch.pending = timesInvoked < times + // If specified, trigger dispatch error + if (error !== null) { + deleteMockDispatch(this[kDispatches], key) + handler.onError(error) return true } - #internalMatchAll (request, options, maxResponses = Infinity) { - // 1. - let r = null + // Track whether the request has been aborted + let aborted = false + let timer = null - // 2. - if (request !== undefined) { - if (webidl.is.Request(request)) { - // 2.1.1 - r = getRequestState(request) + function abort (err) { + if (aborted) { + return + } + aborted = true - // 2.1.2 - if (r.method !== 'GET' && !options.ignoreMethod) { - return [] - } - } else if (typeof request === 'string') { - // 2.2.1 - r = getRequestState(new Request(request)) - } + // Clear the pending delayed response if any + if (timer !== null) { + clearTimeout(timer) + timer = null } - // 5. - // 5.1 - const responses = [] + // Notify the handler of the abort + handler.onError(err) + } - // 5.2 - if (request === undefined) { - // 5.2.1 - for (const requestResponse of this.#relevantRequestResponseList) { - responses.push(requestResponse[1]) - } - } else { // 5.3 - // 5.3.1 - const requestResponses = this.#queryCache(r, options) + // Call onConnect to allow the handler to register the abort callback + handler.onConnect?.(abort, null) - // 5.3.2 - for (const requestResponse of requestResponses) { - responses.push(requestResponse[1]) - } + // Handle the request with a delay if necessary + if (typeof delay === 'number' && delay > 0) { + timer = setTimeout(() => { + timer = null + handleReply(this[kDispatches]) + }, delay) + } else { + handleReply(this[kDispatches]) + } + + function handleReply (mockDispatches, _data = data) { + // Don't send response if the request was aborted + if (aborted) { + return } - // 5.4 - // We don't implement CORs so we don't need to loop over the responses, yay! + // fetch's HeadersList is a 1D string array + const optsHeaders = Array.isArray(opts.headers) + ? buildHeadersFromArray(opts.headers) + : opts.headers + const body = typeof _data === 'function' + ? _data({ ...opts, headers: optsHeaders }) + : _data - // 5.5.1 - const responseList = [] + // util.types.isPromise is likely needed for jest. + if (isPromise(body)) { + // If handleReply is asynchronous, throwing an error + // in the callback will reject the promise, rather than + // synchronously throw the error, which breaks some tests. + // Rather, we wait for the callback to resolve if it is a + // promise, and then re-run handleReply with the new body. + return body.then((newData) => handleReply(mockDispatches, newData)) + } - // 5.5.2 - for (const response of responses) { - // 5.5.2.1 - const responseObject = fromInnerResponse(cloneResponse(response), 'immutable') + // Check again if aborted after async body resolution + if (aborted) { + return + } - responseList.push(responseObject) + const responseData = getResponseData(body) + const responseHeaders = generateKeyValues(headers) + const responseTrailers = generateKeyValues(trailers) - if (responseList.length >= maxResponses) { - break + handler.onHeaders?.(statusCode, responseHeaders, resume, getStatusText(statusCode)) + handler.onData?.(Buffer.from(responseData)) + handler.onComplete?.(responseTrailers) + deleteMockDispatch(mockDispatches, key) + } + + function resume () {} + + return true +} + +function buildMockDispatch () { + const agent = this[kMockAgent] + const origin = this[kOrigin] + const originalDispatch = this[kOriginalDispatch] + + return function dispatch (opts, handler) { + if (agent.isMockActive) { + try { + mockDispatch.call(this, opts, handler) + } catch (error) { + if (error.code === 'UND_MOCK_ERR_MOCK_NOT_MATCHED') { + const netConnect = agent[kGetNetConnect]() + if (netConnect === false) { + throw new MockNotMatchedError(`${error.message}: subsequent request to origin ${origin} was not allowed (net.connect disabled)`) + } + if (checkNetConnect(netConnect, origin)) { + originalDispatch.call(this, opts, handler) + } else { + throw new MockNotMatchedError(`${error.message}: subsequent request to origin ${origin} was not allowed (net.connect is not enabled for this origin)`) + } + } else { + throw error + } } + } else { + originalDispatch.call(this, opts, handler) } + } +} - // 6. - return Object.freeze(responseList) +function checkNetConnect (netConnect, origin) { + const url = new URL(origin) + if (netConnect === true) { + return true + } else if (Array.isArray(netConnect) && netConnect.some((matcher) => matchValue(matcher, url.host))) { + return true } + return false } -Object.defineProperties(Cache.prototype, { - [Symbol.toStringTag]: { - value: 'Cache', - configurable: true - }, - match: kEnumerableProperty, - matchAll: kEnumerableProperty, - add: kEnumerableProperty, - addAll: kEnumerableProperty, - put: kEnumerableProperty, - delete: kEnumerableProperty, - keys: kEnumerableProperty -}) +function normalizeOrigin (origin) { + if (typeof origin !== 'string' && !(origin instanceof URL)) { + return origin + } -const cacheQueryOptionConverters = [ - { - key: 'ignoreSearch', - converter: webidl.converters.boolean, - defaultValue: () => false - }, - { - key: 'ignoreMethod', - converter: webidl.converters.boolean, - defaultValue: () => false - }, - { - key: 'ignoreVary', - converter: webidl.converters.boolean, - defaultValue: () => false + if (origin instanceof URL) { + return origin.origin } -] -webidl.converters.CacheQueryOptions = webidl.dictionaryConverter(cacheQueryOptionConverters) + return origin.toLowerCase() +} -webidl.converters.MultiCacheQueryOptions = webidl.dictionaryConverter([ - ...cacheQueryOptionConverters, - { - key: 'cacheName', - converter: webidl.converters.DOMString +function buildAndValidateMockOptions (opts) { + const { agent, ...mockOptions } = opts + + if ('enableCallHistory' in mockOptions && typeof mockOptions.enableCallHistory !== 'boolean') { + throw new InvalidArgumentError('options.enableCallHistory must to be a boolean') } -]) -webidl.converters.Response = webidl.interfaceConverter( - webidl.is.Response, - 'Response' -) + if ('acceptNonStandardSearchParameters' in mockOptions && typeof mockOptions.acceptNonStandardSearchParameters !== 'boolean') { + throw new InvalidArgumentError('options.acceptNonStandardSearchParameters must to be a boolean') + } -webidl.converters['sequence'] = webidl.sequenceConverter( - webidl.converters.RequestInfo -) + if ('ignoreTrailingSlash' in mockOptions && typeof mockOptions.ignoreTrailingSlash !== 'boolean') { + throw new InvalidArgumentError('options.ignoreTrailingSlash must to be a boolean') + } + + return mockOptions +} module.exports = { - Cache + getResponseData, + getMockDispatch, + addMockDispatch, + deleteMockDispatch, + buildKey, + generateKeyValues, + matchValue, + getResponse, + getStatusText, + mockDispatch, + buildMockDispatch, + checkNetConnect, + buildAndValidateMockOptions, + getHeaderByName, + buildHeadersFromArray, + normalizeSearchParams, + normalizeOrigin } /***/ }), -/***/ 7456: +/***/ 2272: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -const { Cache } = __nccwpck_require__(6769) -const { webidl } = __nccwpck_require__(2318) -const { kEnumerableProperty } = __nccwpck_require__(983) -const { kConstruct } = __nccwpck_require__(9562) +const { Transform } = __nccwpck_require__(7075) +const { Console } = __nccwpck_require__(7540) -class CacheStorage { - /** - * @see https://w3c.github.io/ServiceWorker/#dfn-relevant-name-to-cache-map - * @type {Map ({ + Method: method, + Origin: origin, + Path: path, + 'Status code': statusCode, + Persistent: persist ? PERSISTENT : NOT_PERSISTENT, + Invocations: timesInvoked, + Remaining: persist ? Infinity : times - timesInvoked + })) - // 1. - if (options.cacheName != null) { - // 1.1.1.1 - if (this.#caches.has(options.cacheName)) { - // 1.1.1.1.1 - const cacheList = this.#caches.get(options.cacheName) - const cache = new Cache(kConstruct, cacheList) + this.logger.table(withPrettyHeaders) + return this.transform.read().toString() + } +} - return await cache.match(request, options) - } - } else { // 2. - // 2.2 - for (const cacheList of this.#caches.values()) { - const cache = new Cache(kConstruct, cacheList) - // 2.2.1.2 - const response = await cache.match(request, options) +/***/ }), - if (response !== undefined) { - return response - } - } - } - } +/***/ 4357: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - /** - * @see https://w3c.github.io/ServiceWorker/#cache-storage-has - * @param {string} cacheName - * @returns {Promise} - */ - async has (cacheName) { - webidl.brandCheck(this, CacheStorage) - const prefix = 'CacheStorage.has' - webidl.argumentLengthCheck(arguments, 1, prefix) - cacheName = webidl.converters.DOMString(cacheName, prefix, 'cacheName') +const Agent = __nccwpck_require__(9959) +const MockAgent = __nccwpck_require__(839) +const { SnapshotRecorder } = __nccwpck_require__(8212) +const WrapHandler = __nccwpck_require__(6444) +const { InvalidArgumentError, UndiciError } = __nccwpck_require__(5093) +const { validateSnapshotMode } = __nccwpck_require__(9661) - // 2.1.1 - // 2.2 - return this.#caches.has(cacheName) - } +const kSnapshotRecorder = Symbol('kSnapshotRecorder') +const kSnapshotMode = Symbol('kSnapshotMode') +const kSnapshotPath = Symbol('kSnapshotPath') +const kSnapshotLoaded = Symbol('kSnapshotLoaded') +const kRealAgent = Symbol('kRealAgent') - /** - * @see https://w3c.github.io/ServiceWorker/#dom-cachestorage-open - * @param {string} cacheName - * @returns {Promise} - */ - async open (cacheName) { - webidl.brandCheck(this, CacheStorage) +// Static flag to ensure warning is only emitted once per process +let warningEmitted = false - const prefix = 'CacheStorage.open' - webidl.argumentLengthCheck(arguments, 1, prefix) +class SnapshotAgent extends MockAgent { + constructor (opts = {}) { + // Emit experimental warning only once + if (!warningEmitted) { + process.emitWarning( + 'SnapshotAgent is experimental and subject to change', + 'ExperimentalWarning' + ) + warningEmitted = true + } - cacheName = webidl.converters.DOMString(cacheName, prefix, 'cacheName') + const { + mode = 'record', + snapshotPath = null, + ...mockAgentOpts + } = opts - // 2.1 - if (this.#caches.has(cacheName)) { - // await caches.open('v1') !== await caches.open('v1') + super(mockAgentOpts) - // 2.1.1 - const cache = this.#caches.get(cacheName) + validateSnapshotMode(mode) - // 2.1.1.1 - return new Cache(kConstruct, cache) + // Validate snapshotPath is provided when required + if ((mode === 'playback' || mode === 'update') && !snapshotPath) { + throw new InvalidArgumentError(`snapshotPath is required when mode is '${mode}'`) } - // 2.2 - const cache = [] + this[kSnapshotMode] = mode + this[kSnapshotPath] = snapshotPath - // 2.3 - this.#caches.set(cacheName, cache) + this[kSnapshotRecorder] = new SnapshotRecorder({ + snapshotPath: this[kSnapshotPath], + mode: this[kSnapshotMode], + maxSnapshots: opts.maxSnapshots, + autoFlush: opts.autoFlush, + flushInterval: opts.flushInterval, + matchHeaders: opts.matchHeaders, + ignoreHeaders: opts.ignoreHeaders, + excludeHeaders: opts.excludeHeaders, + matchBody: opts.matchBody, + matchQuery: opts.matchQuery, + caseSensitive: opts.caseSensitive, + shouldRecord: opts.shouldRecord, + shouldPlayback: opts.shouldPlayback, + excludeUrls: opts.excludeUrls + }) + this[kSnapshotLoaded] = false - // 2.4 - return new Cache(kConstruct, cache) + // For recording/update mode, we need a real agent to make actual requests + // For playback mode, we need a real agent if there are excluded URLs + if (this[kSnapshotMode] === 'record' || this[kSnapshotMode] === 'update' || + (this[kSnapshotMode] === 'playback' && opts.excludeUrls && opts.excludeUrls.length > 0)) { + this[kRealAgent] = new Agent(opts) + } + + // Auto-load snapshots in playback/update mode + if ((this[kSnapshotMode] === 'playback' || this[kSnapshotMode] === 'update') && this[kSnapshotPath]) { + this.loadSnapshots().catch(() => { + // Ignore load errors - file might not exist yet + }) + } } - /** - * @see https://w3c.github.io/ServiceWorker/#cache-storage-delete - * @param {string} cacheName - * @returns {Promise} - */ - async delete (cacheName) { - webidl.brandCheck(this, CacheStorage) + dispatch (opts, handler) { + handler = WrapHandler.wrap(handler) + const mode = this[kSnapshotMode] - const prefix = 'CacheStorage.delete' - webidl.argumentLengthCheck(arguments, 1, prefix) + // Check if URL should be excluded (pass through without mocking/recording) + if (this[kSnapshotRecorder].isUrlExcluded(opts)) { + // Real agent is guaranteed by constructor when excludeUrls is configured + return this[kRealAgent].dispatch(opts, handler) + } - cacheName = webidl.converters.DOMString(cacheName, prefix, 'cacheName') + if (mode === 'playback' || mode === 'update') { + // Ensure snapshots are loaded + if (!this[kSnapshotLoaded]) { + // Need to load asynchronously, delegate to async version + return this.#asyncDispatch(opts, handler) + } - return this.#caches.delete(cacheName) + // Try to find existing snapshot (synchronous) + const snapshot = this[kSnapshotRecorder].findSnapshot(opts) + + if (snapshot) { + // Use recorded response (synchronous) + return this.#replaySnapshot(snapshot, handler) + } else if (mode === 'update') { + // Make real request and record it (async required) + return this.#recordAndReplay(opts, handler) + } else { + // Playback mode but no snapshot found + const error = new UndiciError(`No snapshot found for ${opts.method || 'GET'} ${opts.path}`) + if (handler.onError) { + handler.onError(error) + return + } + throw error + } + } else if (mode === 'record') { + // Record mode - make real request and save response (async required) + return this.#recordAndReplay(opts, handler) + } } /** - * @see https://w3c.github.io/ServiceWorker/#cache-storage-keys - * @returns {Promise} + * Async version of dispatch for when we need to load snapshots first */ - async keys () { - webidl.brandCheck(this, CacheStorage) - - // 2.1 - const keys = this.#caches.keys() - - // 2.2 - return [...keys] + async #asyncDispatch (opts, handler) { + await this.loadSnapshots() + return this.dispatch(opts, handler) } -} -Object.defineProperties(CacheStorage.prototype, { - [Symbol.toStringTag]: { - value: 'CacheStorage', - configurable: true - }, - match: kEnumerableProperty, - has: kEnumerableProperty, - open: kEnumerableProperty, - delete: kEnumerableProperty, - keys: kEnumerableProperty -}) + /** + * Records a real request and replays the response + */ + #recordAndReplay (opts, handler) { + const responseData = { + statusCode: null, + headers: {}, + trailers: {}, + body: [] + } -module.exports = { - CacheStorage -} + const self = this // Capture 'this' context for use within nested handler callbacks + const recordingHandler = { + onRequestStart (controller, context) { + return handler.onRequestStart(controller, { ...context, history: this.history }) + }, -/***/ }), + onRequestUpgrade (controller, statusCode, headers, socket) { + return handler.onRequestUpgrade(controller, statusCode, headers, socket) + }, -/***/ 55: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + onResponseStart (controller, statusCode, headers, statusMessage) { + responseData.statusCode = statusCode + responseData.headers = headers + return handler.onResponseStart(controller, statusCode, headers, statusMessage) + }, -"use strict"; + onResponseData (controller, chunk) { + responseData.body.push(chunk) + return handler.onResponseData(controller, chunk) + }, + onResponseEnd (controller, trailers) { + responseData.trailers = trailers -const assert = __nccwpck_require__(4589) -const { URLSerializer } = __nccwpck_require__(9425) -const { isValidHeaderName } = __nccwpck_require__(8913) + // Record the interaction using captured 'self' context (fire and forget) + const responseBody = Buffer.concat(responseData.body) + self[kSnapshotRecorder].record(opts, { + statusCode: responseData.statusCode, + headers: responseData.headers, + body: responseBody, + trailers: responseData.trailers + }) + .then(() => handler.onResponseEnd(controller, trailers)) + .catch((error) => handler.onResponseError(controller, error)) + } + } -/** - * @see https://url.spec.whatwg.org/#concept-url-equals - * @param {URL} A - * @param {URL} B - * @param {boolean | undefined} excludeFragment - * @returns {boolean} - */ -function urlEquals (A, B, excludeFragment = false) { - const serializedA = URLSerializer(A, excludeFragment) + // Use composed agent if available (includes interceptors), otherwise use real agent + const agent = this[kRealAgent] + return agent.dispatch(opts, recordingHandler) + } - const serializedB = URLSerializer(B, excludeFragment) + /** + * Replays a recorded response + * + * @param {Object} snapshot - The recorded snapshot to replay. + * @param {Object} handler - The handler to call with the response data. + * @returns {void} + */ + #replaySnapshot (snapshot, handler) { + try { + const { response } = snapshot - return serializedA === serializedB -} + const controller = { + pause () { }, + resume () { }, + abort (reason) { + this.aborted = true + this.reason = reason + }, -/** - * @see https://github.com/chromium/chromium/blob/694d20d134cb553d8d89e5500b9148012b1ba299/content/browser/cache_storage/cache_storage_cache.cc#L260-L262 - * @param {string} header - */ -function getFieldValues (header) { - assert(header !== null) + aborted: false, + paused: false + } - const values = [] + handler.onRequestStart(controller) - for (let value of header.split(',')) { - value = value.trim() + handler.onResponseStart(controller, response.statusCode, response.headers) - if (isValidHeaderName(value)) { - values.push(value) + // Body is always stored as base64 string + const body = Buffer.from(response.body, 'base64') + handler.onResponseData(controller, body) + + handler.onResponseEnd(controller, response.trailers) + } catch (error) { + handler.onError?.(error) } } - return values -} + /** + * Loads snapshots from file + * + * @param {string} [filePath] - Optional file path to load snapshots from. + * @returns {Promise} - Resolves when snapshots are loaded. + */ + async loadSnapshots (filePath) { + await this[kSnapshotRecorder].loadSnapshots(filePath || this[kSnapshotPath]) + this[kSnapshotLoaded] = true -module.exports = { - urlEquals, - getFieldValues -} + // In playback mode, set up MockAgent interceptors for all snapshots + if (this[kSnapshotMode] === 'playback') { + this.#setupMockInterceptors() + } + } + + /** + * Saves snapshots to file + * + * @param {string} [filePath] - Optional file path to save snapshots to. + * @returns {Promise} - Resolves when snapshots are saved. + */ + async saveSnapshots (filePath) { + return this[kSnapshotRecorder].saveSnapshots(filePath || this[kSnapshotPath]) + } + + /** + * Sets up MockAgent interceptors based on recorded snapshots. + * + * This method creates MockAgent interceptors for each recorded snapshot, + * allowing the SnapshotAgent to fall back to MockAgent's standard intercept + * mechanism in playback mode. Each interceptor is configured to persist + * (remain active for multiple requests) and responds with the recorded + * response data. + * + * Called automatically when loading snapshots in playback mode. + * + * @returns {void} + */ + #setupMockInterceptors () { + for (const snapshot of this[kSnapshotRecorder].getSnapshots()) { + const { request, responses, response } = snapshot + const url = new URL(request.url) + const mockPool = this.get(url.origin) -/***/ }), + // Handle both new format (responses array) and legacy format (response object) + const responseData = responses ? responses[0] : response + if (!responseData) continue -/***/ 483: -/***/ ((module) => { + mockPool.intercept({ + path: url.pathname + url.search, + method: request.method, + headers: request.headers, + body: request.body + }).reply(responseData.statusCode, responseData.body, { + headers: responseData.headers, + trailers: responseData.trailers + }).persist() + } + } -"use strict"; + /** + * Gets the snapshot recorder + * @return {SnapshotRecorder} - The snapshot recorder instance + */ + getRecorder () { + return this[kSnapshotRecorder] + } + /** + * Gets the current mode + * @return {import('./snapshot-utils').SnapshotMode} - The current snapshot mode + */ + getMode () { + return this[kSnapshotMode] + } -// https://wicg.github.io/cookie-store/#cookie-maximum-attribute-value-size -const maxAttributeValueSize = 1024 + /** + * Clears all snapshots + * @returns {void} + */ + clearSnapshots () { + this[kSnapshotRecorder].clear() + } -// https://wicg.github.io/cookie-store/#cookie-maximum-name-value-pair-size -const maxNameValuePairSize = 4096 + /** + * Resets call counts for all snapshots (useful for test cleanup) + * @returns {void} + */ + resetCallCounts () { + this[kSnapshotRecorder].resetCallCounts() + } -module.exports = { - maxAttributeValueSize, - maxNameValuePairSize + /** + * Deletes a specific snapshot by request options + * @param {import('./snapshot-recorder').SnapshotRequestOptions} requestOpts - Request options to identify the snapshot + * @return {Promise} - Returns true if the snapshot was deleted, false if not found + */ + deleteSnapshot (requestOpts) { + return this[kSnapshotRecorder].deleteSnapshot(requestOpts) + } + + /** + * Gets information about a specific snapshot + * @returns {import('./snapshot-recorder').SnapshotInfo|null} - Snapshot information or null if not found + */ + getSnapshotInfo (requestOpts) { + return this[kSnapshotRecorder].getSnapshotInfo(requestOpts) + } + + /** + * Replaces all snapshots with new data (full replacement) + * @param {Array<{hash: string; snapshot: import('./snapshot-recorder').SnapshotEntryshotEntry}>|Record} snapshotData - New snapshot data to replace existing snapshots + * @returns {void} + */ + replaceSnapshots (snapshotData) { + this[kSnapshotRecorder].replaceSnapshots(snapshotData) + } + + /** + * Closes the agent, saving snapshots and cleaning up resources. + * + * @returns {Promise} + */ + async close () { + await this[kSnapshotRecorder].close() + await this[kRealAgent]?.close() + await super.close() + } } +module.exports = SnapshotAgent + /***/ }), -/***/ 2178: +/***/ 8212: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -const { parseSetCookie } = __nccwpck_require__(9969) -const { stringify } = __nccwpck_require__(76) -const { webidl } = __nccwpck_require__(2318) -const { Headers } = __nccwpck_require__(8447) +const { writeFile, readFile, mkdir } = __nccwpck_require__(1455) +const { dirname, resolve } = __nccwpck_require__(6760) +const { setTimeout, clearTimeout } = __nccwpck_require__(7997) +const { InvalidArgumentError, UndiciError } = __nccwpck_require__(5093) +const { hashId, isUrlExcludedFactory, normalizeHeaders, createHeaderFilters } = __nccwpck_require__(9661) -const brandChecks = webidl.brandCheckMultiple([Headers, globalThis.Headers].filter(Boolean)) +/** + * @typedef {Object} SnapshotRequestOptions + * @property {string} method - HTTP method (e.g. 'GET', 'POST', etc.) + * @property {string} path - Request path + * @property {string} origin - Request origin (base URL) + * @property {import('./snapshot-utils').Headers|import('./snapshot-utils').UndiciHeaders} headers - Request headers + * @property {import('./snapshot-utils').NormalizedHeaders} _normalizedHeaders - Request headers as a lowercase object + * @property {string|Buffer} [body] - Request body (optional) + */ /** - * @typedef {Object} Cookie - * @property {string} name - * @property {string} value - * @property {Date|number} [expires] - * @property {number} [maxAge] - * @property {string} [domain] - * @property {string} [path] - * @property {boolean} [secure] - * @property {boolean} [httpOnly] - * @property {'Strict'|'Lax'|'None'} [sameSite] - * @property {string[]} [unparsed] + * @typedef {Object} SnapshotEntryRequest + * @property {string} method - HTTP method (e.g. 'GET', 'POST', etc.) + * @property {string} url - Full URL of the request + * @property {import('./snapshot-utils').NormalizedHeaders} headers - Normalized headers as a lowercase object + * @property {string|Buffer} [body] - Request body (optional) */ /** - * @param {Headers} headers - * @returns {Record} + * @typedef {Object} SnapshotEntryResponse + * @property {number} statusCode - HTTP status code of the response + * @property {import('./snapshot-utils').NormalizedHeaders} headers - Normalized response headers as a lowercase object + * @property {string} body - Response body as a base64url encoded string + * @property {Object} [trailers] - Optional response trailers */ -function getCookies (headers) { - webidl.argumentLengthCheck(arguments, 1, 'getCookies') - brandChecks(headers) +/** + * @typedef {Object} SnapshotEntry + * @property {SnapshotEntryRequest} request - The request object + * @property {Array} responses - Array of response objects + * @property {number} callCount - Number of times this snapshot has been called + * @property {string} timestamp - ISO timestamp of when the snapshot was created + */ - const cookie = headers.get('cookie') +/** + * @typedef {Object} SnapshotRecorderMatchOptions + * @property {Array} [matchHeaders=[]] - Headers to match (empty array means match all headers) + * @property {Array} [ignoreHeaders=[]] - Headers to ignore for matching + * @property {Array} [excludeHeaders=[]] - Headers to exclude from matching + * @property {boolean} [matchBody=true] - Whether to match request body + * @property {boolean} [matchQuery=true] - Whether to match query properties + * @property {boolean} [caseSensitive=false] - Whether header matching is case-sensitive + */ - /** @type {Record} */ - const out = {} +/** + * @typedef {Object} SnapshotRecorderOptions + * @property {string} [snapshotPath] - Path to save/load snapshots + * @property {import('./snapshot-utils').SnapshotMode} [mode='record'] - Mode: 'record' or 'playback' + * @property {number} [maxSnapshots=Infinity] - Maximum number of snapshots to keep + * @property {boolean} [autoFlush=false] - Whether to automatically flush snapshots to disk + * @property {number} [flushInterval=30000] - Auto-flush interval in milliseconds (default: 30 seconds) + * @property {Array} [excludeUrls=[]] - URLs to exclude from recording + * @property {function} [shouldRecord=null] - Function to filter requests for recording + * @property {function} [shouldPlayback=null] - Function to filter requests + */ - if (!cookie) { - return out - } +/** + * @typedef {Object} SnapshotFormattedRequest + * @property {string} method - HTTP method (e.g. 'GET', 'POST', etc.) + * @property {string} url - Full URL of the request (with query parameters if matchQuery is true) + * @property {import('./snapshot-utils').NormalizedHeaders} headers - Normalized headers as a lowercase object + * @property {string} body - Request body (optional, only if matchBody is true) + */ - for (const piece of cookie.split(';')) { - const [name, ...value] = piece.split('=') +/** + * @typedef {Object} SnapshotInfo + * @property {string} hash - Hash key for the snapshot + * @property {SnapshotEntryRequest} request - The request object + * @property {number} responseCount - Number of responses recorded for this request + * @property {number} callCount - Number of times this snapshot has been called + * @property {string} timestamp - ISO timestamp of when the snapshot was created + */ - out[name.trim()] = value.join('=') +/** + * Formats a request for consistent snapshot storage + * Caches normalized headers to avoid repeated processing + * + * @param {SnapshotRequestOptions} opts - Request options + * @param {import('./snapshot-utils').HeaderFilters} headerFilters - Cached header sets for performance + * @param {SnapshotRecorderMatchOptions} [matchOptions] - Matching options for headers and body + * @returns {SnapshotFormattedRequest} - Formatted request object + */ +function formatRequestKey (opts, headerFilters, matchOptions = {}) { + const url = new URL(opts.path, opts.origin) + + // Cache normalized headers if not already done + const normalized = opts._normalizedHeaders || normalizeHeaders(opts.headers) + if (!opts._normalizedHeaders) { + opts._normalizedHeaders = normalized } - return out + return { + method: opts.method || 'GET', + url: matchOptions.matchQuery !== false ? url.toString() : `${url.origin}${url.pathname}`, + headers: filterHeadersForMatching(normalized, headerFilters, matchOptions), + body: matchOptions.matchBody !== false && opts.body ? String(opts.body) : '' + } } /** - * @param {Headers} headers - * @param {string} name - * @param {{ path?: string, domain?: string }|undefined} attributes - * @returns {void} + * Filters headers based on matching configuration + * + * @param {import('./snapshot-utils').Headers} headers - Headers to filter + * @param {import('./snapshot-utils').HeaderFilters} headerFilters - Cached sets for ignore, exclude, and match headers + * @param {SnapshotRecorderMatchOptions} [matchOptions] - Matching options for headers */ -function deleteCookie (headers, name, attributes) { - brandChecks(headers) +function filterHeadersForMatching (headers, headerFilters, matchOptions = {}) { + if (!headers || typeof headers !== 'object') return {} - const prefix = 'deleteCookie' - webidl.argumentLengthCheck(arguments, 2, prefix) + const { + caseSensitive = false + } = matchOptions - name = webidl.converters.DOMString(name, prefix, 'name') - attributes = webidl.converters.DeleteCookieAttributes(attributes) + const filtered = {} + const { ignore, exclude, match } = headerFilters - // Matches behavior of - // https://github.com/denoland/deno_std/blob/63827b16330b82489a04614027c33b7904e08be5/http/cookie.ts#L278 - setCookie(headers, { - name, - value: '', - expires: new Date(0), - ...attributes - }) -} + for (const [key, value] of Object.entries(headers)) { + const headerKey = caseSensitive ? key : key.toLowerCase() -/** - * @param {Headers} headers - * @returns {Cookie[]} - */ -function getSetCookies (headers) { - webidl.argumentLengthCheck(arguments, 1, 'getSetCookies') + // Skip if in exclude list (for security) + if (exclude.has(headerKey)) continue - brandChecks(headers) + // Skip if in ignore list (for matching) + if (ignore.has(headerKey)) continue - const cookies = headers.getSetCookie() + // If matchHeaders is specified, only include those headers + if (match.size !== 0) { + if (!match.has(headerKey)) continue + } - if (!cookies) { - return [] + filtered[headerKey] = value } - return cookies.map((pair) => parseSetCookie(pair)) + return filtered } /** - * Parses a cookie string - * @param {string} cookie + * Filters headers for storage (only excludes sensitive headers) + * + * @param {import('./snapshot-utils').Headers} headers - Headers to filter + * @param {import('./snapshot-utils').HeaderFilters} headerFilters - Cached sets for ignore, exclude, and match headers + * @param {SnapshotRecorderMatchOptions} [matchOptions] - Matching options for headers */ -function parseCookie (cookie) { - cookie = webidl.converters.DOMString(cookie) - - return parseSetCookie(cookie) -} +function filterHeadersForStorage (headers, headerFilters, matchOptions = {}) { + if (!headers || typeof headers !== 'object') return {} -/** - * @param {Headers} headers - * @param {Cookie} cookie - * @returns {void} - */ -function setCookie (headers, cookie) { - webidl.argumentLengthCheck(arguments, 2, 'setCookie') + const { + caseSensitive = false + } = matchOptions - brandChecks(headers) + const filtered = {} + const { exclude: excludeSet } = headerFilters - cookie = webidl.converters.Cookie(cookie) + for (const [key, value] of Object.entries(headers)) { + const headerKey = caseSensitive ? key : key.toLowerCase() - const str = stringify(cookie) + // Skip if in exclude list (for security) + if (excludeSet.has(headerKey)) continue - if (str) { - headers.append('set-cookie', str, true) + filtered[headerKey] = value } -} -webidl.converters.DeleteCookieAttributes = webidl.dictionaryConverter([ - { - converter: webidl.nullableConverter(webidl.converters.DOMString), - key: 'path', - defaultValue: () => null - }, - { - converter: webidl.nullableConverter(webidl.converters.DOMString), - key: 'domain', - defaultValue: () => null - } -]) + return filtered +} -webidl.converters.Cookie = webidl.dictionaryConverter([ - { - converter: webidl.converters.DOMString, - key: 'name' - }, - { - converter: webidl.converters.DOMString, - key: 'value' - }, - { - converter: webidl.nullableConverter((value) => { - if (typeof value === 'number') { - return webidl.converters['unsigned long long'](value) - } +/** + * Creates a hash key for request matching + * Properly orders headers to avoid conflicts and uses crypto hashing when available + * + * @param {SnapshotFormattedRequest} formattedRequest - Request object + * @returns {string} - Base64url encoded hash of the request + */ +function createRequestHash (formattedRequest) { + const parts = [ + formattedRequest.method, + formattedRequest.url + ] - return new Date(value) - }), - key: 'expires', - defaultValue: () => null - }, - { - converter: webidl.nullableConverter(webidl.converters['long long']), - key: 'maxAge', - defaultValue: () => null - }, - { - converter: webidl.nullableConverter(webidl.converters.DOMString), - key: 'domain', - defaultValue: () => null - }, - { - converter: webidl.nullableConverter(webidl.converters.DOMString), - key: 'path', - defaultValue: () => null - }, - { - converter: webidl.nullableConverter(webidl.converters.boolean), - key: 'secure', - defaultValue: () => null - }, - { - converter: webidl.nullableConverter(webidl.converters.boolean), - key: 'httpOnly', - defaultValue: () => null - }, - { - converter: webidl.converters.USVString, - key: 'sameSite', - allowedValues: ['Strict', 'Lax', 'None'] - }, - { - converter: webidl.sequenceConverter(webidl.converters.DOMString), - key: 'unparsed', - defaultValue: () => [] - } -]) + // Process headers in a deterministic way to avoid conflicts + if (formattedRequest.headers && typeof formattedRequest.headers === 'object') { + const headerKeys = Object.keys(formattedRequest.headers).sort() + for (const key of headerKeys) { + const values = Array.isArray(formattedRequest.headers[key]) + ? formattedRequest.headers[key] + : [formattedRequest.headers[key]] -module.exports = { - getCookies, - deleteCookie, - getSetCookies, - setCookie, - parseCookie -} + // Add header name + parts.push(key) + // Add all values for this header, sorted for consistency + for (const value of values.sort()) { + parts.push(String(value)) + } + } + } -/***/ }), + // Add body + parts.push(formattedRequest.body) -/***/ 9969: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + const content = parts.join('|') -"use strict"; + return hashId(content) +} +class SnapshotRecorder { + /** @type {NodeJS.Timeout | null} */ + #flushTimeout -const { collectASequenceOfCodePointsFast } = __nccwpck_require__(3883) -const { maxNameValuePairSize, maxAttributeValueSize } = __nccwpck_require__(483) -const { isCTLExcludingHtab } = __nccwpck_require__(76) -const assert = __nccwpck_require__(4589) -const { unescape: qsUnescape } = __nccwpck_require__(1792) + /** @type {import('./snapshot-utils').IsUrlExcluded} */ + #isUrlExcluded -/** - * @description Parses the field-value attributes of a set-cookie header string. - * @see https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4 - * @param {string} header - * @returns {import('./index').Cookie|null} if the header is invalid, null will be returned - */ -function parseSetCookie (header) { - // 1. If the set-cookie-string contains a %x00-08 / %x0A-1F / %x7F - // character (CTL characters excluding HTAB): Abort these steps and - // ignore the set-cookie-string entirely. - if (isCTLExcludingHtab(header)) { - return null - } + /** @type {Map} */ + #snapshots = new Map() - let nameValuePair = '' - let unparsedAttributes = '' - let name = '' - let value = '' + /** @type {string|undefined} */ + #snapshotPath - // 2. If the set-cookie-string contains a %x3B (";") character: - if (header.includes(';')) { - // 1. The name-value-pair string consists of the characters up to, - // but not including, the first %x3B (";"), and the unparsed- - // attributes consist of the remainder of the set-cookie-string - // (including the %x3B (";") in question). - const position = { position: 0 } + /** @type {number} */ + #maxSnapshots = Infinity - nameValuePair = collectASequenceOfCodePointsFast(';', header, position) - unparsedAttributes = header.slice(position.position) - } else { - // Otherwise: + /** @type {boolean} */ + #autoFlush = false - // 1. The name-value-pair string consists of all the characters - // contained in the set-cookie-string, and the unparsed- - // attributes is the empty string. - nameValuePair = header - } + /** @type {import('./snapshot-utils').HeaderFilters} */ + #headerFilters - // 3. If the name-value-pair string lacks a %x3D ("=") character, then - // the name string is empty, and the value string is the value of - // name-value-pair. - if (!nameValuePair.includes('=')) { - value = nameValuePair - } else { - // Otherwise, the name string consists of the characters up to, but - // not including, the first %x3D ("=") character, and the (possibly - // empty) value string consists of the characters after the first - // %x3D ("=") character. - const position = { position: 0 } - name = collectASequenceOfCodePointsFast( - '=', - nameValuePair, - position - ) - value = nameValuePair.slice(position.position + 1) - } + /** + * Creates a new SnapshotRecorder instance + * @param {SnapshotRecorderOptions&SnapshotRecorderMatchOptions} [options={}] - Configuration options for the recorder + */ + constructor (options = {}) { + this.#snapshotPath = options.snapshotPath + this.#maxSnapshots = options.maxSnapshots || Infinity + this.#autoFlush = options.autoFlush || false + this.flushInterval = options.flushInterval || 30000 // 30 seconds default + this._flushTimer = null - // 4. Remove any leading or trailing WSP characters from the name - // string and the value string. - name = name.trim() - value = value.trim() + // Matching configuration + /** @type {Required} */ + this.matchOptions = { + matchHeaders: options.matchHeaders || [], // empty means match all headers + ignoreHeaders: options.ignoreHeaders || [], + excludeHeaders: options.excludeHeaders || [], + matchBody: options.matchBody !== false, // default: true + matchQuery: options.matchQuery !== false, // default: true + caseSensitive: options.caseSensitive || false + } - // 5. If the sum of the lengths of the name string and the value string - // is more than 4096 octets, abort these steps and ignore the set- - // cookie-string entirely. - if (name.length + value.length > maxNameValuePairSize) { - return null - } + // Cache processed header sets to avoid recreating them on every request + this.#headerFilters = createHeaderFilters(this.matchOptions) - // 6. The cookie-name is the name string, and the cookie-value is the - // value string. - // https://datatracker.ietf.org/doc/html/rfc6265 - // To maximize compatibility with user agents, servers that wish to - // store arbitrary data in a cookie-value SHOULD encode that data, for - // example, using Base64 [RFC4648]. - return { - name, value: qsUnescape(value), ...parseUnparsedAttributes(unparsedAttributes) - } -} + // Request filtering callbacks + this.shouldRecord = options.shouldRecord || (() => true) // function(requestOpts) -> boolean + this.shouldPlayback = options.shouldPlayback || (() => true) // function(requestOpts) -> boolean -/** - * Parses the remaining attributes of a set-cookie header - * @see https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4 - * @param {string} unparsedAttributes - * @param {Object.} [cookieAttributeList={}] - */ -function parseUnparsedAttributes (unparsedAttributes, cookieAttributeList = {}) { - // 1. If the unparsed-attributes string is empty, skip the rest of - // these steps. - if (unparsedAttributes.length === 0) { - return cookieAttributeList - } + // URL pattern filtering + this.#isUrlExcluded = isUrlExcludedFactory(options.excludeUrls) // Array of regex patterns or strings - // 2. Discard the first character of the unparsed-attributes (which - // will be a %x3B (";") character). - assert(unparsedAttributes[0] === ';') - unparsedAttributes = unparsedAttributes.slice(1) + // Start auto-flush timer if enabled + if (this.#autoFlush && this.#snapshotPath) { + this.#startAutoFlush() + } + } - let cookieAv = '' + /** + * Records a request-response interaction + * @param {SnapshotRequestOptions} requestOpts - Request options + * @param {SnapshotEntryResponse} response - Response data to record + * @return {Promise} - Resolves when the recording is complete + */ + async record (requestOpts, response) { + // Check if recording should be filtered out + if (!this.shouldRecord(requestOpts)) { + return // Skip recording + } - // 3. If the remaining unparsed-attributes contains a %x3B (";") - // character: - if (unparsedAttributes.includes(';')) { - // 1. Consume the characters of the unparsed-attributes up to, but - // not including, the first %x3B (";") character. - cookieAv = collectASequenceOfCodePointsFast( - ';', - unparsedAttributes, - { position: 0 } - ) - unparsedAttributes = unparsedAttributes.slice(cookieAv.length) - } else { - // Otherwise: + // Check URL exclusion patterns + if (this.isUrlExcluded(requestOpts)) { + return // Skip recording + } - // 1. Consume the remainder of the unparsed-attributes. - cookieAv = unparsedAttributes - unparsedAttributes = '' - } + const request = formatRequestKey(requestOpts, this.#headerFilters, this.matchOptions) + const hash = createRequestHash(request) - // Let the cookie-av string be the characters consumed in this step. + // Extract response data - always store body as base64 + const normalizedHeaders = normalizeHeaders(response.headers) - let attributeName = '' - let attributeValue = '' + /** @type {SnapshotEntryResponse} */ + const responseData = { + statusCode: response.statusCode, + headers: filterHeadersForStorage(normalizedHeaders, this.#headerFilters, this.matchOptions), + body: Buffer.isBuffer(response.body) + ? response.body.toString('base64') + : Buffer.from(String(response.body || '')).toString('base64'), + trailers: response.trailers + } - // 4. If the cookie-av string contains a %x3D ("=") character: - if (cookieAv.includes('=')) { - // 1. The (possibly empty) attribute-name string consists of the - // characters up to, but not including, the first %x3D ("=") - // character, and the (possibly empty) attribute-value string - // consists of the characters after the first %x3D ("=") - // character. - const position = { position: 0 } + // Remove oldest snapshot if we exceed maxSnapshots limit + if (this.#snapshots.size >= this.#maxSnapshots && !this.#snapshots.has(hash)) { + const oldestKey = this.#snapshots.keys().next().value + this.#snapshots.delete(oldestKey) + } - attributeName = collectASequenceOfCodePointsFast( - '=', - cookieAv, - position - ) - attributeValue = cookieAv.slice(position.position + 1) - } else { - // Otherwise: + // Support sequential responses - if snapshot exists, add to responses array + const existingSnapshot = this.#snapshots.get(hash) + if (existingSnapshot && existingSnapshot.responses) { + existingSnapshot.responses.push(responseData) + existingSnapshot.timestamp = new Date().toISOString() + } else { + this.#snapshots.set(hash, { + request, + responses: [responseData], // Always store as array for consistency + callCount: 0, + timestamp: new Date().toISOString() + }) + } - // 1. The attribute-name string consists of the entire cookie-av - // string, and the attribute-value string is empty. - attributeName = cookieAv + // Auto-flush if enabled + if (this.#autoFlush && this.#snapshotPath) { + this.#scheduleFlush() + } } - // 5. Remove any leading or trailing WSP characters from the attribute- - // name string and the attribute-value string. - attributeName = attributeName.trim() - attributeValue = attributeValue.trim() - - // 6. If the attribute-value is longer than 1024 octets, ignore the - // cookie-av string and return to Step 1 of this algorithm. - if (attributeValue.length > maxAttributeValueSize) { - return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList) + /** + * Checks if a URL should be excluded from recording/playback + * @param {SnapshotRequestOptions} requestOpts - Request options to check + * @returns {boolean} - True if URL is excluded + */ + isUrlExcluded (requestOpts) { + const url = new URL(requestOpts.path, requestOpts.origin).toString() + return this.#isUrlExcluded(url) } - // 7. Process the attribute-name and attribute-value according to the - // requirements in the following subsections. (Notice that - // attributes with unrecognized attribute-names are ignored.) - const attributeNameLowercase = attributeName.toLowerCase() + /** + * Finds a matching snapshot for the given request + * Returns the appropriate response based on call count for sequential responses + * + * @param {SnapshotRequestOptions} requestOpts - Request options to match + * @returns {SnapshotEntry&Record<'response', SnapshotEntryResponse>|undefined} - Matching snapshot response or undefined if not found + */ + findSnapshot (requestOpts) { + // Check if playback should be filtered out + if (!this.shouldPlayback(requestOpts)) { + return undefined // Skip playback + } - // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.1 - // If the attribute-name case-insensitively matches the string - // "Expires", the user agent MUST process the cookie-av as follows. - if (attributeNameLowercase === 'expires') { - // 1. Let the expiry-time be the result of parsing the attribute-value - // as cookie-date (see Section 5.1.1). - const expiryTime = new Date(attributeValue) + // Check URL exclusion patterns + if (this.isUrlExcluded(requestOpts)) { + return undefined // Skip playback + } - // 2. If the attribute-value failed to parse as a cookie date, ignore - // the cookie-av. + const request = formatRequestKey(requestOpts, this.#headerFilters, this.matchOptions) + const hash = createRequestHash(request) + const snapshot = this.#snapshots.get(hash) - cookieAttributeList.expires = expiryTime - } else if (attributeNameLowercase === 'max-age') { - // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.2 - // If the attribute-name case-insensitively matches the string "Max- - // Age", the user agent MUST process the cookie-av as follows. + if (!snapshot) return undefined - // 1. If the first character of the attribute-value is not a DIGIT or a - // "-" character, ignore the cookie-av. - const charCode = attributeValue.charCodeAt(0) + // Handle sequential responses + const currentCallCount = snapshot.callCount || 0 + const responseIndex = Math.min(currentCallCount, snapshot.responses.length - 1) + snapshot.callCount = currentCallCount + 1 - if ((charCode < 48 || charCode > 57) && attributeValue[0] !== '-') { - return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList) + return { + ...snapshot, + response: snapshot.responses[responseIndex] } + } - // 2. If the remainder of attribute-value contains a non-DIGIT - // character, ignore the cookie-av. - if (!/^\d+$/.test(attributeValue)) { - return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList) + /** + * Loads snapshots from file + * @param {string} [filePath] - Optional file path to load snapshots from + * @return {Promise} - Resolves when snapshots are loaded + */ + async loadSnapshots (filePath) { + const path = filePath || this.#snapshotPath + if (!path) { + throw new InvalidArgumentError('Snapshot path is required') } - // 3. Let delta-seconds be the attribute-value converted to an integer. - const deltaSeconds = Number(attributeValue) + try { + const data = await readFile(resolve(path), 'utf8') + const parsed = JSON.parse(data) - // 4. Let cookie-age-limit be the maximum age of the cookie (which - // SHOULD be 400 days or less, see Section 4.1.2.2). + // Convert array format back to Map + if (Array.isArray(parsed)) { + this.#snapshots.clear() + for (const { hash, snapshot } of parsed) { + this.#snapshots.set(hash, snapshot) + } + } else { + // Legacy object format + this.#snapshots = new Map(Object.entries(parsed)) + } + } catch (error) { + if (error.code === 'ENOENT') { + // File doesn't exist yet - that's ok for recording mode + this.#snapshots.clear() + } else { + throw new UndiciError(`Failed to load snapshots from ${path}`, { cause: error }) + } + } + } - // 5. Set delta-seconds to the smaller of its present value and cookie- - // age-limit. - // deltaSeconds = Math.min(deltaSeconds * 1000, maxExpiresMs) + /** + * Saves snapshots to file + * + * @param {string} [filePath] - Optional file path to save snapshots + * @returns {Promise} - Resolves when snapshots are saved + */ + async saveSnapshots (filePath) { + const path = filePath || this.#snapshotPath + if (!path) { + throw new InvalidArgumentError('Snapshot path is required') + } - // 6. If delta-seconds is less than or equal to zero (0), let expiry- - // time be the earliest representable date and time. Otherwise, let - // the expiry-time be the current date and time plus delta-seconds - // seconds. - // const expiryTime = deltaSeconds <= 0 ? Date.now() : Date.now() + deltaSeconds + const resolvedPath = resolve(path) - // 7. Append an attribute to the cookie-attribute-list with an - // attribute-name of Max-Age and an attribute-value of expiry-time. - cookieAttributeList.maxAge = deltaSeconds - } else if (attributeNameLowercase === 'domain') { - // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.3 - // If the attribute-name case-insensitively matches the string "Domain", - // the user agent MUST process the cookie-av as follows. + // Ensure directory exists + await mkdir(dirname(resolvedPath), { recursive: true }) - // 1. Let cookie-domain be the attribute-value. - let cookieDomain = attributeValue + // Convert Map to serializable format + const data = Array.from(this.#snapshots.entries()).map(([hash, snapshot]) => ({ + hash, + snapshot + })) - // 2. If cookie-domain starts with %x2E ("."), let cookie-domain be - // cookie-domain without its leading %x2E ("."). - if (cookieDomain[0] === '.') { - cookieDomain = cookieDomain.slice(1) - } + await writeFile(resolvedPath, JSON.stringify(data, null, 2), { flush: true }) + } - // 3. Convert the cookie-domain to lower case. - cookieDomain = cookieDomain.toLowerCase() + /** + * Clears all recorded snapshots + * @returns {void} + */ + clear () { + this.#snapshots.clear() + } - // 4. Append an attribute to the cookie-attribute-list with an - // attribute-name of Domain and an attribute-value of cookie-domain. - cookieAttributeList.domain = cookieDomain - } else if (attributeNameLowercase === 'path') { - // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.4 - // If the attribute-name case-insensitively matches the string "Path", - // the user agent MUST process the cookie-av as follows. + /** + * Gets all recorded snapshots + * @return {Array} - Array of all recorded snapshots + */ + getSnapshots () { + return Array.from(this.#snapshots.values()) + } - // 1. If the attribute-value is empty or if the first character of the - // attribute-value is not %x2F ("/"): - let cookiePath = '' - if (attributeValue.length === 0 || attributeValue[0] !== '/') { - // 1. Let cookie-path be the default-path. - cookiePath = '/' - } else { - // Otherwise: + /** + * Gets snapshot count + * @return {number} - Number of recorded snapshots + */ + size () { + return this.#snapshots.size + } - // 1. Let cookie-path be the attribute-value. - cookiePath = attributeValue + /** + * Resets call counts for all snapshots (useful for test cleanup) + * @returns {void} + */ + resetCallCounts () { + for (const snapshot of this.#snapshots.values()) { + snapshot.callCount = 0 } + } - // 2. Append an attribute to the cookie-attribute-list with an - // attribute-name of Path and an attribute-value of cookie-path. - cookieAttributeList.path = cookiePath - } else if (attributeNameLowercase === 'secure') { - // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.5 - // If the attribute-name case-insensitively matches the string "Secure", - // the user agent MUST append an attribute to the cookie-attribute-list - // with an attribute-name of Secure and an empty attribute-value. - - cookieAttributeList.secure = true - } else if (attributeNameLowercase === 'httponly') { - // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.6 - // If the attribute-name case-insensitively matches the string - // "HttpOnly", the user agent MUST append an attribute to the cookie- - // attribute-list with an attribute-name of HttpOnly and an empty - // attribute-value. + /** + * Deletes a specific snapshot by request options + * @param {SnapshotRequestOptions} requestOpts - Request options to match + * @returns {boolean} - True if snapshot was deleted, false if not found + */ + deleteSnapshot (requestOpts) { + const request = formatRequestKey(requestOpts, this.#headerFilters, this.matchOptions) + const hash = createRequestHash(request) + return this.#snapshots.delete(hash) + } - cookieAttributeList.httpOnly = true - } else if (attributeNameLowercase === 'samesite') { - // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.7 - // If the attribute-name case-insensitively matches the string - // "SameSite", the user agent MUST process the cookie-av as follows: + /** + * Gets information about a specific snapshot + * @param {SnapshotRequestOptions} requestOpts - Request options to match + * @returns {SnapshotInfo|null} - Snapshot information or null if not found + */ + getSnapshotInfo (requestOpts) { + const request = formatRequestKey(requestOpts, this.#headerFilters, this.matchOptions) + const hash = createRequestHash(request) + const snapshot = this.#snapshots.get(hash) - // 1. Let enforcement be "Default". - let enforcement = 'Default' + if (!snapshot) return null - const attributeValueLowercase = attributeValue.toLowerCase() - // 2. If cookie-av's attribute-value is a case-insensitive match for - // "None", set enforcement to "None". - if (attributeValueLowercase.includes('none')) { - enforcement = 'None' + return { + hash, + request: snapshot.request, + responseCount: snapshot.responses ? snapshot.responses.length : (snapshot.response ? 1 : 0), // .response for legacy snapshots + callCount: snapshot.callCount || 0, + timestamp: snapshot.timestamp } + } - // 3. If cookie-av's attribute-value is a case-insensitive match for - // "Strict", set enforcement to "Strict". - if (attributeValueLowercase.includes('strict')) { - enforcement = 'Strict' - } + /** + * Replaces all snapshots with new data (full replacement) + * @param {Array<{hash: string; snapshot: SnapshotEntry}>|Record} snapshotData - New snapshot data to replace existing ones + * @returns {void} + */ + replaceSnapshots (snapshotData) { + this.#snapshots.clear() - // 4. If cookie-av's attribute-value is a case-insensitive match for - // "Lax", set enforcement to "Lax". - if (attributeValueLowercase.includes('lax')) { - enforcement = 'Lax' + if (Array.isArray(snapshotData)) { + for (const { hash, snapshot } of snapshotData) { + this.#snapshots.set(hash, snapshot) + } + } else if (snapshotData && typeof snapshotData === 'object') { + // Legacy object format + this.#snapshots = new Map(Object.entries(snapshotData)) } - - // 5. Append an attribute to the cookie-attribute-list with an - // attribute-name of "SameSite" and an attribute-value of - // enforcement. - cookieAttributeList.sameSite = enforcement - } else { - cookieAttributeList.unparsed ??= [] - - cookieAttributeList.unparsed.push(`${attributeName}=${attributeValue}`) } - // 8. Return to Step 1 of this algorithm. - return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList) -} - -module.exports = { - parseSetCookie, - parseUnparsedAttributes -} - - -/***/ }), - -/***/ 76: -/***/ ((module) => { - -"use strict"; - - -/** - * @param {string} value - * @returns {boolean} - */ -function isCTLExcludingHtab (value) { - for (let i = 0; i < value.length; ++i) { - const code = value.charCodeAt(i) + /** + * Starts the auto-flush timer + * @returns {void} + */ + #startAutoFlush () { + return this.#scheduleFlush() + } - if ( - (code >= 0x00 && code <= 0x08) || - (code >= 0x0A && code <= 0x1F) || - code === 0x7F - ) { - return true + /** + * Stops the auto-flush timer + * @returns {void} + */ + #stopAutoFlush () { + if (this.#flushTimeout) { + clearTimeout(this.#flushTimeout) + // Ensure any pending flush is completed + this.saveSnapshots().catch(() => { + // Ignore flush errors + }) + this.#flushTimeout = null } } - return false -} -/** - CHAR = - token = 1* - separators = "(" | ")" | "<" | ">" | "@" - | "," | ";" | ":" | "\" | <"> - | "/" | "[" | "]" | "?" | "=" - | "{" | "}" | SP | HT - * @param {string} name - */ -function validateCookieName (name) { - for (let i = 0; i < name.length; ++i) { - const code = name.charCodeAt(i) + /** + * Schedules a flush (debounced to avoid excessive writes) + */ + #scheduleFlush () { + this.#flushTimeout = setTimeout(() => { + this.saveSnapshots().catch(() => { + // Ignore flush errors + }) + if (this.#autoFlush) { + this.#flushTimeout?.refresh() + } else { + this.#flushTimeout = null + } + }, 1000) // 1 second debounce + } - if ( - code < 0x21 || // exclude CTLs (0-31), SP and HT - code > 0x7E || // exclude non-ascii and DEL - code === 0x22 || // " - code === 0x28 || // ( - code === 0x29 || // ) - code === 0x3C || // < - code === 0x3E || // > - code === 0x40 || // @ - code === 0x2C || // , - code === 0x3B || // ; - code === 0x3A || // : - code === 0x5C || // \ - code === 0x2F || // / - code === 0x5B || // [ - code === 0x5D || // ] - code === 0x3F || // ? - code === 0x3D || // = - code === 0x7B || // { - code === 0x7D // } - ) { - throw new Error('Invalid cookie name') + /** + * Cleanup method to stop timers + * @returns {void} + */ + destroy () { + this.#stopAutoFlush() + if (this.#flushTimeout) { + clearTimeout(this.#flushTimeout) + this.#flushTimeout = null + } + } + + /** + * Async close method that saves all recordings and performs cleanup + * @returns {Promise} + */ + async close () { + // Save any pending recordings if we have a snapshot path + if (this.#snapshotPath && this.#snapshots.size !== 0) { + await this.saveSnapshots() } + + // Perform cleanup + this.destroy() } } +module.exports = { SnapshotRecorder, formatRequestKey, createRequestHash, filterHeadersForMatching, filterHeadersForStorage, createHeaderFilters } + + +/***/ }), + +/***/ 9661: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + + + +const { InvalidArgumentError } = __nccwpck_require__(5093) +const { runtimeFeatures } = __nccwpck_require__(3895) + /** - cookie-value = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE ) - cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E - ; US-ASCII characters excluding CTLs, - ; whitespace DQUOTE, comma, semicolon, - ; and backslash - * @param {string} value + * @typedef {Object} HeaderFilters + * @property {Set} ignore - Set of headers to ignore for matching + * @property {Set} exclude - Set of headers to exclude from matching + * @property {Set} match - Set of headers to match (empty means match */ -function validateCookieValue (value) { - let len = value.length - let i = 0 - // if the value is wrapped in DQUOTE - if (value[0] === '"') { - if (len === 1 || value[len - 1] !== '"') { - throw new Error('Invalid cookie value') - } - --len - ++i +/** + * Creates cached header sets for performance + * + * @param {import('./snapshot-recorder').SnapshotRecorderMatchOptions} matchOptions - Matching options for headers + * @returns {HeaderFilters} - Cached sets for ignore, exclude, and match headers + */ +function createHeaderFilters (matchOptions = {}) { + const { ignoreHeaders = [], excludeHeaders = [], matchHeaders = [], caseSensitive = false } = matchOptions + + return { + ignore: new Set(ignoreHeaders.map(header => caseSensitive ? header : header.toLowerCase())), + exclude: new Set(excludeHeaders.map(header => caseSensitive ? header : header.toLowerCase())), + match: new Set(matchHeaders.map(header => caseSensitive ? header : header.toLowerCase())) } +} - while (i < len) { - const code = value.charCodeAt(i++) +const crypto = runtimeFeatures.has('crypto') + ? __nccwpck_require__(7598) + : null - if ( - code < 0x21 || // exclude CTLs (0-31) - code > 0x7E || // non-ascii and DEL (127) - code === 0x22 || // " - code === 0x2C || // , - code === 0x3B || // ; - code === 0x5C // \ - ) { - throw new Error('Invalid cookie value') +/** + * @callback HashIdFunction + * @param {string} value - The value to hash + * @returns {string} - The base64url encoded hash of the value + */ + +/** + * Generates a hash for a given value + * @type {HashIdFunction} + */ +const hashId = crypto?.hash + ? (value) => crypto.hash('sha256', value, 'base64url') + : (value) => Buffer.from(value).toString('base64url') + +/** + * @typedef {(url: string) => boolean} IsUrlExcluded Checks if a URL matches any of the exclude patterns + */ + +/** @typedef {{[key: Lowercase]: string}} NormalizedHeaders */ +/** @typedef {Array} UndiciHeaders */ +/** @typedef {Record} Headers */ + +/** + * @param {*} headers + * @returns {headers is UndiciHeaders} + */ +function isUndiciHeaders (headers) { + return Array.isArray(headers) && (headers.length & 1) === 0 +} + +/** + * Factory function to create a URL exclusion checker + * @param {Array} [excludePatterns=[]] - Array of patterns to exclude + * @returns {IsUrlExcluded} - A function that checks if a URL matches any of the exclude patterns + */ +function isUrlExcludedFactory (excludePatterns = []) { + if (excludePatterns.length === 0) { + return () => false + } + + return function isUrlExcluded (url) { + let urlLowerCased + + for (const pattern of excludePatterns) { + if (typeof pattern === 'string') { + if (!urlLowerCased) { + // Convert URL to lowercase only once + urlLowerCased = url.toLowerCase() + } + // Simple string match (case-insensitive) + if (urlLowerCased.includes(pattern.toLowerCase())) { + return true + } + } else if (pattern instanceof RegExp) { + // Regex pattern match + if (pattern.test(url)) { + return true + } + } } + + return false } } /** - * path-value = - * @param {string} path + * Normalizes headers for consistent comparison + * + * @param {Object|UndiciHeaders} headers - Headers to normalize + * @returns {NormalizedHeaders} - Normalized headers as a lowercase object */ -function validateCookiePath (path) { - for (let i = 0; i < path.length; ++i) { - const code = path.charCodeAt(i) +function normalizeHeaders (headers) { + /** @type {NormalizedHeaders} */ + const normalizedHeaders = {} - if ( - code < 0x20 || // exclude CTLs (0-31) - code === 0x7F || // DEL - code === 0x3B // ; - ) { - throw new Error('Invalid cookie path') + if (!headers) return normalizedHeaders + + // Handle array format (undici internal format: [name, value, name, value, ...]) + if (isUndiciHeaders(headers)) { + for (let i = 0; i < headers.length; i += 2) { + const key = headers[i] + const value = headers[i + 1] + if (key && value !== undefined) { + // Convert Buffers to strings if needed + const keyStr = Buffer.isBuffer(key) ? key.toString() : key + const valueStr = Buffer.isBuffer(value) ? value.toString() : value + normalizedHeaders[keyStr.toLowerCase()] = valueStr + } + } + return normalizedHeaders + } + + // Handle object format + if (headers && typeof headers === 'object') { + for (const [key, value] of Object.entries(headers)) { + if (key && typeof key === 'string') { + normalizedHeaders[key.toLowerCase()] = Array.isArray(value) ? value.join(', ') : String(value) + } } } + + return normalizedHeaders } +const validSnapshotModes = /** @type {const} */ (['record', 'playback', 'update']) + +/** @typedef {typeof validSnapshotModes[number]} SnapshotMode */ + /** - * I have no idea why these values aren't allowed to be honest, - * but Deno tests these. - Khafra - * @param {string} domain + * @param {*} mode - The snapshot mode to validate + * @returns {asserts mode is SnapshotMode} */ -function validateCookieDomain (domain) { - if ( - domain.startsWith('-') || - domain.endsWith('.') || - domain.endsWith('-') - ) { - throw new Error('Invalid cookie domain') +function validateSnapshotMode (mode) { + if (!validSnapshotModes.includes(mode)) { + throw new InvalidArgumentError(`Invalid snapshot mode: ${mode}. Must be one of: ${validSnapshotModes.join(', ')}`) } } -const IMFDays = [ - 'Sun', 'Mon', 'Tue', 'Wed', - 'Thu', 'Fri', 'Sat' -] +module.exports = { + createHeaderFilters, + hashId, + isUndiciHeaders, + normalizeHeaders, + isUrlExcludedFactory, + validateSnapshotMode +} -const IMFMonths = [ - 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', - 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' -] -const IMFPaddedNumbers = Array(61).fill(0).map((_, i) => i.toString().padStart(2, '0')) +/***/ }), -/** - * @see https://www.rfc-editor.org/rfc/rfc7231#section-7.1.1.1 - * @param {number|Date} date - IMF-fixdate = day-name "," SP date1 SP time-of-day SP GMT - ; fixed length/zone/capitalization subset of the format - ; see Section 3.3 of [RFC5322] +/***/ 4649: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - day-name = %x4D.6F.6E ; "Mon", case-sensitive - / %x54.75.65 ; "Tue", case-sensitive - / %x57.65.64 ; "Wed", case-sensitive - / %x54.68.75 ; "Thu", case-sensitive - / %x46.72.69 ; "Fri", case-sensitive - / %x53.61.74 ; "Sat", case-sensitive - / %x53.75.6E ; "Sun", case-sensitive - date1 = day SP month SP year - ; e.g., 02 Jun 1982 - day = 2DIGIT - month = %x4A.61.6E ; "Jan", case-sensitive - / %x46.65.62 ; "Feb", case-sensitive - / %x4D.61.72 ; "Mar", case-sensitive - / %x41.70.72 ; "Apr", case-sensitive - / %x4D.61.79 ; "May", case-sensitive - / %x4A.75.6E ; "Jun", case-sensitive - / %x4A.75.6C ; "Jul", case-sensitive - / %x41.75.67 ; "Aug", case-sensitive - / %x53.65.70 ; "Sep", case-sensitive - / %x4F.63.74 ; "Oct", case-sensitive - / %x4E.6F.76 ; "Nov", case-sensitive - / %x44.65.63 ; "Dec", case-sensitive - year = 4DIGIT - GMT = %x47.4D.54 ; "GMT", case-sensitive +const { + safeHTTPMethods, + pathHasQueryOrFragment +} = __nccwpck_require__(2550) - time-of-day = hour ":" minute ":" second - ; 00:00:00 - 23:59:60 (leap second) +const { serializePathWithQuery } = __nccwpck_require__(2550) - hour = 2DIGIT - minute = 2DIGIT - second = 2DIGIT +/** + * @param {import('../../types/dispatcher.d.ts').default.DispatchOptions} opts */ -function toIMFDate (date) { - if (typeof date === 'number') { - date = new Date(date) +function makeCacheKey (opts) { + if (!opts.origin) { + throw new Error('opts.origin is undefined') } - return `${IMFDays[date.getUTCDay()]}, ${IMFPaddedNumbers[date.getUTCDate()]} ${IMFMonths[date.getUTCMonth()]} ${date.getUTCFullYear()} ${IMFPaddedNumbers[date.getUTCHours()]}:${IMFPaddedNumbers[date.getUTCMinutes()]}:${IMFPaddedNumbers[date.getUTCSeconds()]} GMT` + let fullPath = opts.path || '/' + + if (opts.query && !pathHasQueryOrFragment(opts.path)) { + fullPath = serializePathWithQuery(fullPath, opts.query) + } + + return { + origin: opts.origin.toString(), + method: opts.method, + path: fullPath, + headers: opts.headers + } } /** - max-age-av = "Max-Age=" non-zero-digit *DIGIT - ; In practice, both expires-av and max-age-av - ; are limited to dates representable by the - ; user agent. - * @param {number} maxAge + * @param {Record} + * @returns {Record} */ -function validateCookieMaxAge (maxAge) { - if (maxAge < 0) { - throw new Error('Invalid cookie max-age') +function normalizeHeaders (opts) { + let headers + if (opts.headers == null) { + headers = {} + } else if (typeof opts.headers[Symbol.iterator] === 'function') { + headers = {} + for (const x of opts.headers) { + if (!Array.isArray(x)) { + throw new Error('opts.headers is not a valid header map') + } + const [key, val] = x + if (typeof key !== 'string' || typeof val !== 'string') { + throw new Error('opts.headers is not a valid header map') + } + headers[key.toLowerCase()] = val + } + } else if (typeof opts.headers === 'object') { + headers = {} + + for (const key of Object.keys(opts.headers)) { + headers[key.toLowerCase()] = opts.headers[key] + } + } else { + throw new Error('opts.headers is not an object') } + + return headers } /** - * @see https://www.rfc-editor.org/rfc/rfc6265#section-4.1.1 - * @param {import('./index').Cookie} cookie + * @param {any} key */ -function stringify (cookie) { - if (cookie.name.length === 0) { - return null +function assertCacheKey (key) { + if (typeof key !== 'object') { + throw new TypeError(`expected key to be object, got ${typeof key}`) } - validateCookieName(cookie.name) - validateCookieValue(cookie.value) - - const out = [`${cookie.name}=${cookie.value}`] - - // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-cookie-prefixes-00#section-3.1 - // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-cookie-prefixes-00#section-3.2 - if (cookie.name.startsWith('__Secure-')) { - cookie.secure = true + for (const property of ['origin', 'method', 'path']) { + if (typeof key[property] !== 'string') { + throw new TypeError(`expected key.${property} to be string, got ${typeof key[property]}`) + } } - if (cookie.name.startsWith('__Host-')) { - cookie.secure = true - cookie.domain = null - cookie.path = '/' + if (key.headers !== undefined && typeof key.headers !== 'object') { + throw new TypeError(`expected headers to be object, got ${typeof key}`) } +} - if (cookie.secure) { - out.push('Secure') +/** + * @param {any} value + */ +function assertCacheValue (value) { + if (typeof value !== 'object') { + throw new TypeError(`expected value to be object, got ${typeof value}`) } - if (cookie.httpOnly) { - out.push('HttpOnly') + for (const property of ['statusCode', 'cachedAt', 'staleAt', 'deleteAt']) { + if (typeof value[property] !== 'number') { + throw new TypeError(`expected value.${property} to be number, got ${typeof value[property]}`) + } } - if (typeof cookie.maxAge === 'number') { - validateCookieMaxAge(cookie.maxAge) - out.push(`Max-Age=${cookie.maxAge}`) + if (typeof value.statusMessage !== 'string') { + throw new TypeError(`expected value.statusMessage to be string, got ${typeof value.statusMessage}`) } - if (cookie.domain) { - validateCookieDomain(cookie.domain) - out.push(`Domain=${cookie.domain}`) + if (value.headers != null && typeof value.headers !== 'object') { + throw new TypeError(`expected value.rawHeaders to be object, got ${typeof value.headers}`) } - if (cookie.path) { - validateCookiePath(cookie.path) - out.push(`Path=${cookie.path}`) + if (value.vary !== undefined && typeof value.vary !== 'object') { + throw new TypeError(`expected value.vary to be object, got ${typeof value.vary}`) } - if (cookie.expires && cookie.expires.toString() !== 'Invalid Date') { - out.push(`Expires=${toIMFDate(cookie.expires)}`) + if (value.etag !== undefined && typeof value.etag !== 'string') { + throw new TypeError(`expected value.etag to be string, got ${typeof value.etag}`) } +} - if (cookie.sameSite) { - out.push(`SameSite=${cookie.sameSite}`) - } +/** + * @see https://www.rfc-editor.org/rfc/rfc9111.html#name-cache-control + * @see https://www.iana.org/assignments/http-cache-directives/http-cache-directives.xhtml - for (const part of cookie.unparsed) { - if (!part.includes('=')) { - throw new Error('Invalid unparsed') - } + * @param {string | string[]} header + * @returns {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives} + */ +function parseCacheControlHeader (header) { + /** + * @type {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives} + */ + const output = {} - const [key, ...value] = part.split('=') + let directives + if (Array.isArray(header)) { + directives = [] - out.push(`${key.trim()}=${value.join('=')}`) + for (const directive of header) { + directives.push(...directive.split(',')) + } + } else { + directives = header.split(',') } - return out.join('; ') -} + for (let i = 0; i < directives.length; i++) { + const directive = directives[i].toLowerCase() + const keyValueDelimiter = directive.indexOf('=') -module.exports = { - isCTLExcludingHtab, - validateCookieName, - validateCookiePath, - validateCookieValue, - toIMFDate, - stringify -} + let key + let value + if (keyValueDelimiter !== -1) { + key = directive.substring(0, keyValueDelimiter).trimStart() + value = directive.substring(keyValueDelimiter + 1) + } else { + key = directive.trim() + } + switch (key) { + case 'min-fresh': + case 'max-stale': + case 'max-age': + case 's-maxage': + case 'stale-while-revalidate': + case 'stale-if-error': { + if (value === undefined || value[0] === ' ') { + continue + } -/***/ }), + if ( + value.length >= 2 && + value[0] === '"' && + value[value.length - 1] === '"' + ) { + value = value.substring(1, value.length - 1) + } -/***/ 3422: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + const parsedValue = parseInt(value, 10) + // eslint-disable-next-line no-self-compare + if (parsedValue !== parsedValue) { + continue + } -"use strict"; + if (key === 'max-age' && key in output && output[key] >= parsedValue) { + continue + } -const { Transform } = __nccwpck_require__(7075) -const { isASCIINumber, isValidLastEventId } = __nccwpck_require__(1970) + output[key] = parsedValue -/** - * @type {number[]} BOM - */ -const BOM = [0xEF, 0xBB, 0xBF] -/** - * @type {10} LF - */ -const LF = 0x0A -/** - * @type {13} CR - */ -const CR = 0x0D -/** - * @type {58} COLON - */ -const COLON = 0x3A -/** - * @type {32} SPACE - */ -const SPACE = 0x20 - -/** - * @typedef {object} EventSourceStreamEvent - * @type {object} - * @property {string} [event] The event type. - * @property {string} [data] The data of the message. - * @property {string} [id] A unique ID for the event. - * @property {string} [retry] The reconnection time, in milliseconds. - */ + break + } + case 'private': + case 'no-cache': { + if (value) { + // The private and no-cache directives can be unqualified (aka just + // `private` or `no-cache`) or qualified (w/ a value). When they're + // qualified, it's a list of headers like `no-cache=header1`, + // `no-cache="header1"`, or `no-cache="header1, header2"` + // If we're given multiple headers, the comma messes us up since + // we split the full header by commas. So, let's loop through the + // remaining parts in front of us until we find one that ends in a + // quote. We can then just splice all of the parts in between the + // starting quote and the ending quote out of the directives array + // and continue parsing like normal. + // https://www.rfc-editor.org/rfc/rfc9111.html#name-no-cache-2 + if (value[0] === '"') { + // Something like `no-cache="some-header"` OR `no-cache="some-header, another-header"`. -/** - * @typedef eventSourceSettings - * @type {object} - * @property {string} [lastEventId] The last event ID received from the server. - * @property {string} [origin] The origin of the event source. - * @property {number} [reconnectionTime] The reconnection time, in milliseconds. - */ + // Add the first header on and cut off the leading quote + const headers = [value.substring(1)] -class EventSourceStream extends Transform { - /** - * @type {eventSourceSettings} - */ - state + let foundEndingQuote = value[value.length - 1] === '"' + if (!foundEndingQuote) { + // Something like `no-cache="some-header, another-header"` + // This can still be something invalid, e.g. `no-cache="some-header, ...` + for (let j = i + 1; j < directives.length; j++) { + const nextPart = directives[j] + const nextPartLength = nextPart.length - /** - * Leading byte-order-mark check. - * @type {boolean} - */ - checkBOM = true + headers.push(nextPart.trim()) - /** - * @type {boolean} - */ - crlfCheck = false + if (nextPartLength !== 0 && nextPart[nextPartLength - 1] === '"') { + foundEndingQuote = true + break + } + } + } - /** - * @type {boolean} - */ - eventEndCheck = false + if (foundEndingQuote) { + let lastHeader = headers[headers.length - 1] + if (lastHeader[lastHeader.length - 1] === '"') { + lastHeader = lastHeader.substring(0, lastHeader.length - 1) + headers[headers.length - 1] = lastHeader + } - /** - * @type {Buffer|null} - */ - buffer = null + if (key in output) { + output[key] = output[key].concat(headers) + } else { + output[key] = headers + } + } + } else { + // Something like `no-cache="some-header"` + if (key in output) { + output[key] = output[key].concat(value) + } else { + output[key] = [value] + } + } - pos = 0 + break + } + } + // eslint-disable-next-line no-fallthrough + case 'public': + case 'no-store': + case 'must-revalidate': + case 'proxy-revalidate': + case 'immutable': + case 'no-transform': + case 'must-understand': + case 'only-if-cached': + if (value) { + // These are qualified (something like `public=...`) when they aren't + // allowed to be, skip + continue + } - event = { - data: undefined, - event: undefined, - id: undefined, - retry: undefined + output[key] = true + break + default: + // Ignore unknown directives as per https://www.rfc-editor.org/rfc/rfc9111.html#section-5.2.3-1 + continue + } } - /** - * @param {object} options - * @param {boolean} [options.readableObjectMode] - * @param {eventSourceSettings} [options.eventSourceSettings] - * @param {(chunk: any, encoding?: BufferEncoding | undefined) => boolean} [options.push] - */ - constructor (options = {}) { - // Enable object mode as EventSourceStream emits objects of shape - // EventSourceStreamEvent - options.readableObjectMode = true - - super(options) + return output +} - this.state = options.eventSourceSettings || {} - if (options.push) { - this.push = options.push - } +/** + * @param {string | string[]} varyHeader Vary header from the server + * @param {Record} headers Request headers + * @returns {Record} + */ +function parseVaryHeader (varyHeader, headers) { + if (typeof varyHeader === 'string' && varyHeader.includes('*')) { + return headers } - /** - * @param {Buffer} chunk - * @param {string} _encoding - * @param {Function} callback - * @returns {void} - */ - _transform (chunk, _encoding, callback) { - if (chunk.length === 0) { - callback() - return - } - - // Cache the chunk in the buffer, as the data might not be complete while - // processing it - // TODO: Investigate if there is a more performant way to handle - // incoming chunks - // see: https://github.com/nodejs/undici/issues/2630 - if (this.buffer) { - this.buffer = Buffer.concat([this.buffer, chunk]) - } else { - this.buffer = chunk - } + const output = /** @type {Record} */ ({}) - // Strip leading byte-order-mark if we opened the stream and started - // the processing of the incoming data - if (this.checkBOM) { - switch (this.buffer.length) { - case 1: - // Check if the first byte is the same as the first byte of the BOM - if (this.buffer[0] === BOM[0]) { - // If it is, we need to wait for more data - callback() - return - } - // Set the checkBOM flag to false as we don't need to check for the - // BOM anymore - this.checkBOM = false + const varyingHeaders = typeof varyHeader === 'string' + ? varyHeader.split(',') + : varyHeader - // The buffer only contains one byte so we need to wait for more data - callback() - return - case 2: - // Check if the first two bytes are the same as the first two bytes - // of the BOM - if ( - this.buffer[0] === BOM[0] && - this.buffer[1] === BOM[1] - ) { - // If it is, we need to wait for more data, because the third byte - // is needed to determine if it is the BOM or not - callback() - return - } + for (const header of varyingHeaders) { + const trimmedHeader = header.trim().toLowerCase() - // Set the checkBOM flag to false as we don't need to check for the - // BOM anymore - this.checkBOM = false - break - case 3: - // Check if the first three bytes are the same as the first three - // bytes of the BOM - if ( - this.buffer[0] === BOM[0] && - this.buffer[1] === BOM[1] && - this.buffer[2] === BOM[2] - ) { - // If it is, we can drop the buffered data, as it is only the BOM - this.buffer = Buffer.alloc(0) - // Set the checkBOM flag to false as we don't need to check for the - // BOM anymore - this.checkBOM = false + output[trimmedHeader] = headers[trimmedHeader] ?? null + } - // Await more data - callback() - return - } - // If it is not the BOM, we can start processing the data - this.checkBOM = false - break - default: - // The buffer is longer than 3 bytes, so we can drop the BOM if it is - // present - if ( - this.buffer[0] === BOM[0] && - this.buffer[1] === BOM[1] && - this.buffer[2] === BOM[2] - ) { - // Remove the BOM from the buffer - this.buffer = this.buffer.subarray(3) - } + return output +} - // Set the checkBOM flag to false as we don't need to check for the - this.checkBOM = false - break - } - } +/** + * Note: this deviates from the spec a little. Empty etags ("", W/"") are valid, + * however, including them in cached resposnes serves little to no purpose. + * + * @see https://www.rfc-editor.org/rfc/rfc9110.html#name-etag + * + * @param {string} etag + * @returns {boolean} + */ +function isEtagUsable (etag) { + if (etag.length <= 2) { + // Shortest an etag can be is two chars (just ""). This is where we deviate + // from the spec requiring a min of 3 chars however + return false + } - while (this.pos < this.buffer.length) { - // If the previous line ended with an end-of-line, we need to check - // if the next character is also an end-of-line. - if (this.eventEndCheck) { - // If the the current character is an end-of-line, then the event - // is finished and we can process it + if (etag[0] === '"' && etag[etag.length - 1] === '"') { + // ETag: ""asd123"" or ETag: "W/"asd123"", kinda undefined behavior in the + // spec. Some servers will accept these while others don't. + // ETag: "asd123" + return !(etag[1] === '"' || etag.startsWith('"W/')) + } - // If the previous line ended with a carriage return, we need to - // check if the current character is a line feed and remove it - // from the buffer. - if (this.crlfCheck) { - // If the current character is a line feed, we can remove it - // from the buffer and reset the crlfCheck flag - if (this.buffer[this.pos] === LF) { - this.buffer = this.buffer.subarray(this.pos + 1) - this.pos = 0 - this.crlfCheck = false + if (etag.startsWith('W/"') && etag[etag.length - 1] === '"') { + // ETag: W/"", also where we deviate from the spec & require a min of 3 + // chars + // ETag: for W/"", W/"asd123" + return etag.length !== 4 + } - // It is possible that the line feed is not the end of the - // event. We need to check if the next character is an - // end-of-line character to determine if the event is - // finished. We simply continue the loop to check the next - // character. + // Anything else + return false +} - // As we removed the line feed from the buffer and set the - // crlfCheck flag to false, we basically don't make any - // distinction between a line feed and a carriage return. - continue - } - this.crlfCheck = false - } +/** + * @param {unknown} store + * @returns {asserts store is import('../../types/cache-interceptor.d.ts').default.CacheStore} + */ +function assertCacheStore (store, name = 'CacheStore') { + if (typeof store !== 'object' || store === null) { + throw new TypeError(`expected type of ${name} to be a CacheStore, got ${store === null ? 'null' : typeof store}`) + } - if (this.buffer[this.pos] === LF || this.buffer[this.pos] === CR) { - // If the current character is a carriage return, we need to - // set the crlfCheck flag to true, as we need to check if the - // next character is a line feed so we can remove it from the - // buffer - if (this.buffer[this.pos] === CR) { - this.crlfCheck = true - } + for (const fn of ['get', 'createWriteStream', 'delete']) { + if (typeof store[fn] !== 'function') { + throw new TypeError(`${name} needs to have a \`${fn}()\` function`) + } + } +} +/** + * @param {unknown} methods + * @returns {asserts methods is import('../../types/cache-interceptor.d.ts').default.CacheMethods[]} + */ +function assertCacheMethods (methods, name = 'CacheMethods') { + if (!Array.isArray(methods)) { + throw new TypeError(`expected type of ${name} needs to be an array, got ${methods === null ? 'null' : typeof methods}`) + } - this.buffer = this.buffer.subarray(this.pos + 1) - this.pos = 0 - if ( - this.event.data !== undefined || this.event.event || this.event.id !== undefined || this.event.retry) { - this.processEvent(this.event) - } - this.clearEvent() - continue - } - // If the current character is not an end-of-line, then the event - // is not finished and we have to reset the eventEndCheck flag - this.eventEndCheck = false - continue - } + if (methods.length === 0) { + throw new TypeError(`${name} needs to have at least one method`) + } - // If the current character is an end-of-line, we can process the - // line - if (this.buffer[this.pos] === LF || this.buffer[this.pos] === CR) { - // If the current character is a carriage return, we need to - // set the crlfCheck flag to true, as we need to check if the - // next character is a line feed - if (this.buffer[this.pos] === CR) { - this.crlfCheck = true - } + for (const method of methods) { + if (!safeHTTPMethods.includes(method)) { + throw new TypeError(`element of ${name}-array needs to be one of following values: ${safeHTTPMethods.join(', ')}, got ${method}`) + } + } +} - // In any case, we can process the line as we reached an - // end-of-line character - this.parseLine(this.buffer.subarray(0, this.pos), this.event) +/** + * Creates a string key for request deduplication purposes. + * This key is used to identify in-flight requests that can be shared. + * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} cacheKey + * @param {Set} [excludeHeaders] Set of lowercase header names to exclude from the key + * @returns {string} + */ +function makeDeduplicationKey (cacheKey, excludeHeaders) { + // Create a deterministic string key from the cache key + // Include origin, method, path, and sorted headers + let key = `${cacheKey.origin}:${cacheKey.method}:${cacheKey.path}` - // Remove the processed line from the buffer - this.buffer = this.buffer.subarray(this.pos + 1) - // Reset the position as we removed the processed line from the buffer - this.pos = 0 - // A line was processed and this could be the end of the event. We need - // to check if the next line is empty to determine if the event is - // finished. - this.eventEndCheck = true + if (cacheKey.headers) { + const sortedHeaders = Object.keys(cacheKey.headers).sort() + for (const header of sortedHeaders) { + // Skip excluded headers + if (excludeHeaders?.has(header.toLowerCase())) { continue } - - this.pos++ + const value = cacheKey.headers[header] + key += `:${header}=${Array.isArray(value) ? value.join(',') : value}` } - - callback() } - /** - * @param {Buffer} line - * @param {EventSourceStreamEvent} event - */ - parseLine (line, event) { - // If the line is empty (a blank line) - // Dispatch the event, as defined below. - // This will be handled in the _transform method - if (line.length === 0) { - return - } - - // If the line starts with a U+003A COLON character (:) - // Ignore the line. - const colonPosition = line.indexOf(COLON) - if (colonPosition === 0) { - return - } + return key +} - let field = '' - let value = '' +module.exports = { + makeCacheKey, + normalizeHeaders, + assertCacheKey, + assertCacheValue, + parseCacheControlHeader, + parseVaryHeader, + isEtagUsable, + assertCacheMethods, + assertCacheStore, + makeDeduplicationKey +} - // If the line contains a U+003A COLON character (:) - if (colonPosition !== -1) { - // Collect the characters on the line before the first U+003A COLON - // character (:), and let field be that string. - // TODO: Investigate if there is a more performant way to extract the - // field - // see: https://github.com/nodejs/undici/issues/2630 - field = line.subarray(0, colonPosition).toString('utf8') - // Collect the characters on the line after the first U+003A COLON - // character (:), and let value be that string. - // If value starts with a U+0020 SPACE character, remove it from value. - let valueStart = colonPosition + 1 - if (line[valueStart] === SPACE) { - ++valueStart - } - // TODO: Investigate if there is a more performant way to extract the - // value - // see: https://github.com/nodejs/undici/issues/2630 - value = line.subarray(valueStart).toString('utf8') +/***/ }), - // Otherwise, the string is not empty but does not contain a U+003A COLON - // character (:) - } else { - // Process the field using the steps described below, using the whole - // line as the field name, and the empty string as the field value. - field = line.toString('utf8') - value = '' - } +/***/ 7159: +/***/ ((module) => { - // Modify the event with the field name and value. The value is also - // decoded as UTF-8 - switch (field) { - case 'data': - if (event[field] === undefined) { - event[field] = value - } else { - event[field] += `\n${value}` - } - break - case 'retry': - if (isASCIINumber(value)) { - event[field] = value - } - break - case 'id': - if (isValidLastEventId(value)) { - event[field] = value - } - break - case 'event': - if (value.length > 0) { - event[field] = value - } - break - } - } - /** - * @param {EventSourceStreamEvent} event - */ - processEvent (event) { - if (event.retry && isASCIINumber(event.retry)) { - this.state.reconnectionTime = parseInt(event.retry, 10) - } - - if (event.id !== undefined && isValidLastEventId(event.id)) { - this.state.lastEventId = event.id - } - - // only dispatch event, when data is provided - if (event.data !== undefined) { - this.push({ - type: event.event || 'message', - options: { - data: event.data, - lastEventId: this.state.lastEventId, - origin: this.state.origin - } - }) - } - } - - clearEvent () { - this.event = { - data: undefined, - event: undefined, - id: undefined, - retry: undefined - } - } -} - -module.exports = { - EventSourceStream -} - - -/***/ }), - -/***/ 8845: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -"use strict"; - - -const { pipeline } = __nccwpck_require__(7075) -const { fetching } = __nccwpck_require__(6377) -const { makeRequest } = __nccwpck_require__(8140) -const { webidl } = __nccwpck_require__(2318) -const { EventSourceStream } = __nccwpck_require__(3422) -const { parseMIMEType } = __nccwpck_require__(9425) -const { createFastMessageEvent } = __nccwpck_require__(649) -const { isNetworkError } = __nccwpck_require__(9294) -const { kEnumerableProperty } = __nccwpck_require__(983) -const { environmentSettingsObject } = __nccwpck_require__(8913) - -let experimentalWarned = false /** - * A reconnection time, in milliseconds. This must initially be an implementation-defined value, - * probably in the region of a few seconds. - * - * In Comparison: - * - Chrome uses 3000ms. - * - Deno uses 5000ms. + * @see https://www.rfc-editor.org/rfc/rfc9110.html#name-date-time-formats * - * @type {3000} - */ -const defaultReconnectionTime = 3000 - -/** - * The readyState attribute represents the state of the connection. - * @typedef ReadyState - * @type {0|1|2} - * @readonly - * @see https://html.spec.whatwg.org/multipage/server-sent-events.html#dom-eventsource-readystate-dev - */ - -/** - * The connection has not yet been established, or it was closed and the user - * agent is reconnecting. - * @type {0} - */ -const CONNECTING = 0 - -/** - * The user agent has an open connection and is dispatching events as it - * receives them. - * @type {1} - */ -const OPEN = 1 - -/** - * The connection is not open, and the user agent is not trying to reconnect. - * @type {2} - */ -const CLOSED = 2 - -/** - * Requests for the element will have their mode set to "cors" and their credentials mode set to "same-origin". - * @type {'anonymous'} + * @param {string} date + * @returns {Date | undefined} */ -const ANONYMOUS = 'anonymous' +function parseHttpDate (date) { + // Sun, 06 Nov 1994 08:49:37 GMT ; IMF-fixdate + // Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format + // Sunday, 06-Nov-94 08:49:37 GMT ; obsolete RFC 850 format -/** - * Requests for the element will have their mode set to "cors" and their credentials mode set to "include". - * @type {'use-credentials'} - */ -const USE_CREDENTIALS = 'use-credentials' + switch (date[3]) { + case ',': return parseImfDate(date) + case ' ': return parseAscTimeDate(date) + default: return parseRfc850Date(date) + } +} /** - * The EventSource interface is used to receive server-sent events. It - * connects to a server over HTTP and receives events in text/event-stream - * format without closing the connection. - * @extends {EventTarget} - * @see https://html.spec.whatwg.org/multipage/server-sent-events.html#server-sent-events - * @api public + * @see https://httpwg.org/specs/rfc9110.html#preferred.date.format + * + * @param {string} date + * @returns {Date | undefined} */ -class EventSource extends EventTarget { - #events = { - open: null, - error: null, - message: null +function parseImfDate (date) { + if ( + date.length !== 29 || + date[4] !== ' ' || + date[7] !== ' ' || + date[11] !== ' ' || + date[16] !== ' ' || + date[19] !== ':' || + date[22] !== ':' || + date[25] !== ' ' || + date[26] !== 'G' || + date[27] !== 'M' || + date[28] !== 'T' + ) { + return undefined } - #url - #withCredentials = false - - /** - * @type {ReadyState} - */ - #readyState = CONNECTING - - #request = null - #controller = null - - #dispatcher - - /** - * @type {import('./eventsource-stream').eventSourceSettings} - */ - #state - - /** - * Creates a new EventSource object. - * @param {string} url - * @param {EventSourceInit} [eventSourceInitDict={}] - * @see https://html.spec.whatwg.org/multipage/server-sent-events.html#the-eventsource-interface - */ - constructor (url, eventSourceInitDict = {}) { - // 1. Let ev be a new EventSource object. - super() - - webidl.util.markAsUncloneable(this) - - const prefix = 'EventSource constructor' - webidl.argumentLengthCheck(arguments, 1, prefix) + let weekday = -1 + if (date[0] === 'S' && date[1] === 'u' && date[2] === 'n') { // Sunday + weekday = 0 + } else if (date[0] === 'M' && date[1] === 'o' && date[2] === 'n') { // Monday + weekday = 1 + } else if (date[0] === 'T' && date[1] === 'u' && date[2] === 'e') { // Tuesday + weekday = 2 + } else if (date[0] === 'W' && date[1] === 'e' && date[2] === 'd') { // Wednesday + weekday = 3 + } else if (date[0] === 'T' && date[1] === 'h' && date[2] === 'u') { // Thursday + weekday = 4 + } else if (date[0] === 'F' && date[1] === 'r' && date[2] === 'i') { // Friday + weekday = 5 + } else if (date[0] === 'S' && date[1] === 'a' && date[2] === 't') { // Saturday + weekday = 6 + } else { + return undefined // Not a valid day of the week + } - if (!experimentalWarned) { - experimentalWarned = true - process.emitWarning('EventSource is experimental, expect them to change at any time.', { - code: 'UNDICI-ES' - }) + let day = 0 + if (date[5] === '0') { + // Single digit day, e.g. "Sun Nov 6 08:49:37 1994" + const code = date.charCodeAt(6) + if (code < 49 || code > 57) { + return undefined // Not a digit } - - url = webidl.converters.USVString(url) - eventSourceInitDict = webidl.converters.EventSourceInitDict(eventSourceInitDict, prefix, 'eventSourceInitDict') - - this.#dispatcher = eventSourceInitDict.node.dispatcher || eventSourceInitDict.dispatcher - this.#state = { - lastEventId: '', - reconnectionTime: eventSourceInitDict.node.reconnectionTime + day = code - 48 // Convert ASCII code to number + } else { + const code1 = date.charCodeAt(5) + if (code1 < 49 || code1 > 51) { + return undefined // Not a digit between 1 and 3 } - - // 2. Let settings be ev's relevant settings object. - // https://html.spec.whatwg.org/multipage/webappapis.html#environment-settings-object - const settings = environmentSettingsObject - - let urlRecord - - try { - // 3. Let urlRecord be the result of encoding-parsing a URL given url, relative to settings. - urlRecord = new URL(url, settings.settingsObject.baseUrl) - this.#state.origin = urlRecord.origin - } catch (e) { - // 4. If urlRecord is failure, then throw a "SyntaxError" DOMException. - throw new DOMException(e, 'SyntaxError') + const code2 = date.charCodeAt(6) + if (code2 < 48 || code2 > 57) { + return undefined // Not a digit } + day = (code1 - 48) * 10 + (code2 - 48) // Convert ASCII codes to number + } - // 5. Set ev's url to urlRecord. - this.#url = urlRecord.href - - // 6. Let corsAttributeState be Anonymous. - let corsAttributeState = ANONYMOUS - - // 7. If the value of eventSourceInitDict's withCredentials member is true, - // then set corsAttributeState to Use Credentials and set ev's - // withCredentials attribute to true. - if (eventSourceInitDict.withCredentials === true) { - corsAttributeState = USE_CREDENTIALS - this.#withCredentials = true + let monthIdx = -1 + if ( + (date[8] === 'J' && date[9] === 'a' && date[10] === 'n') + ) { + monthIdx = 0 // Jan + } else if ( + (date[8] === 'F' && date[9] === 'e' && date[10] === 'b') + ) { + monthIdx = 1 // Feb + } else if ( + (date[8] === 'M' && date[9] === 'a') + ) { + if (date[10] === 'r') { + monthIdx = 2 // Mar + } else if (date[10] === 'y') { + monthIdx = 4 // May + } else { + return undefined // Invalid month } - - // 8. Let request be the result of creating a potential-CORS request given - // urlRecord, the empty string, and corsAttributeState. - const initRequest = { - redirect: 'follow', - keepalive: true, - // @see https://html.spec.whatwg.org/multipage/urls-and-fetching.html#cors-settings-attributes - mode: 'cors', - credentials: corsAttributeState === 'anonymous' - ? 'same-origin' - : 'omit', - referrer: 'no-referrer' + } else if ( + (date[8] === 'J') + ) { + if (date[9] === 'a' && date[10] === 'n') { + monthIdx = 0 // Jan + } else if (date[9] === 'u') { + if (date[10] === 'n') { + monthIdx = 5 // Jun + } else if (date[10] === 'l') { + monthIdx = 6 // Jul + } else { + return undefined // Invalid month + } + } else { + return undefined // Invalid month } - - // 9. Set request's client to settings. - initRequest.client = environmentSettingsObject.settingsObject - - // 10. User agents may set (`Accept`, `text/event-stream`) in request's header list. - initRequest.headersList = [['accept', { name: 'accept', value: 'text/event-stream' }]] - - // 11. Set request's cache mode to "no-store". - initRequest.cache = 'no-store' - - // 12. Set request's initiator type to "other". - initRequest.initiator = 'other' - - initRequest.urlList = [new URL(this.#url)] - - // 13. Set ev's request to request. - this.#request = makeRequest(initRequest) - - this.#connect() + } else if ( + (date[8] === 'A') + ) { + if (date[9] === 'p' && date[10] === 'r') { + monthIdx = 3 // Apr + } else if (date[9] === 'u' && date[10] === 'g') { + monthIdx = 7 // Aug + } else { + return undefined // Invalid month + } + } else if ( + (date[8] === 'S' && date[9] === 'e' && date[10] === 'p') + ) { + monthIdx = 8 // Sep + } else if ( + (date[8] === 'O' && date[9] === 'c' && date[10] === 't') + ) { + monthIdx = 9 // Oct + } else if ( + (date[8] === 'N' && date[9] === 'o' && date[10] === 'v') + ) { + monthIdx = 10 // Nov + } else if ( + (date[8] === 'D' && date[9] === 'e' && date[10] === 'c') + ) { + monthIdx = 11 // Dec + } else { + // Not a valid month + return undefined } - /** - * Returns the state of this EventSource object's connection. It can have the - * values described below. - * @returns {ReadyState} - * @readonly - */ - get readyState () { - return this.#readyState + const yearDigit1 = date.charCodeAt(12) + if (yearDigit1 < 48 || yearDigit1 > 57) { + return undefined // Not a digit } - - /** - * Returns the URL providing the event stream. - * @readonly - * @returns {string} - */ - get url () { - return this.#url + const yearDigit2 = date.charCodeAt(13) + if (yearDigit2 < 48 || yearDigit2 > 57) { + return undefined // Not a digit } - - /** - * Returns a boolean indicating whether the EventSource object was - * instantiated with CORS credentials set (true), or not (false, the default). - */ - get withCredentials () { - return this.#withCredentials + const yearDigit3 = date.charCodeAt(14) + if (yearDigit3 < 48 || yearDigit3 > 57) { + return undefined // Not a digit } + const yearDigit4 = date.charCodeAt(15) + if (yearDigit4 < 48 || yearDigit4 > 57) { + return undefined // Not a digit + } + const year = (yearDigit1 - 48) * 1000 + (yearDigit2 - 48) * 100 + (yearDigit3 - 48) * 10 + (yearDigit4 - 48) - #connect () { - if (this.#readyState === CLOSED) return - - this.#readyState = CONNECTING - - const fetchParams = { - request: this.#request, - dispatcher: this.#dispatcher + let hour = 0 + if (date[17] === '0') { + const code = date.charCodeAt(18) + if (code < 48 || code > 57) { + return undefined // Not a digit + } + hour = code - 48 // Convert ASCII code to number + } else { + const code1 = date.charCodeAt(17) + if (code1 < 48 || code1 > 50) { + return undefined // Not a digit between 0 and 2 + } + const code2 = date.charCodeAt(18) + if (code2 < 48 || code2 > 57) { + return undefined // Not a digit + } + if (code1 === 50 && code2 > 51) { + return undefined // Hour cannot be greater than 23 } + hour = (code1 - 48) * 10 + (code2 - 48) // Convert ASCII codes to number + } - // 14. Let processEventSourceEndOfBody given response res be the following step: if res is not a network error, then reestablish the connection. - const processEventSourceEndOfBody = (response) => { - if (!isNetworkError(response)) { - return this.#reconnect() - } + let minute = 0 + if (date[20] === '0') { + const code = date.charCodeAt(21) + if (code < 48 || code > 57) { + return undefined // Not a digit + } + minute = code - 48 // Convert ASCII code to number + } else { + const code1 = date.charCodeAt(20) + if (code1 < 48 || code1 > 53) { + return undefined // Not a digit between 0 and 5 + } + const code2 = date.charCodeAt(21) + if (code2 < 48 || code2 > 57) { + return undefined // Not a digit } + minute = (code1 - 48) * 10 + (code2 - 48) // Convert ASCII codes to number + } - // 15. Fetch request, with processResponseEndOfBody set to processEventSourceEndOfBody... - fetchParams.processResponseEndOfBody = processEventSourceEndOfBody + let second = 0 + if (date[23] === '0') { + const code = date.charCodeAt(24) + if (code < 48 || code > 57) { + return undefined // Not a digit + } + second = code - 48 // Convert ASCII code to number + } else { + const code1 = date.charCodeAt(23) + if (code1 < 48 || code1 > 53) { + return undefined // Not a digit between 0 and 5 + } + const code2 = date.charCodeAt(24) + if (code2 < 48 || code2 > 57) { + return undefined // Not a digit + } + second = (code1 - 48) * 10 + (code2 - 48) // Convert ASCII codes to number + } - // and processResponse set to the following steps given response res: - fetchParams.processResponse = (response) => { - // 1. If res is an aborted network error, then fail the connection. + const result = new Date(Date.UTC(year, monthIdx, day, hour, minute, second)) + return result.getUTCDay() === weekday ? result : undefined +} - if (isNetworkError(response)) { - // 1. When a user agent is to fail the connection, the user agent - // must queue a task which, if the readyState attribute is set to a - // value other than CLOSED, sets the readyState attribute to CLOSED - // and fires an event named error at the EventSource object. Once the - // user agent has failed the connection, it does not attempt to - // reconnect. - if (response.aborted) { - this.close() - this.dispatchEvent(new Event('error')) - return - // 2. Otherwise, if res is a network error, then reestablish the - // connection, unless the user agent knows that to be futile, in - // which case the user agent may fail the connection. - } else { - this.#reconnect() - return - } - } +/** + * @see https://httpwg.org/specs/rfc9110.html#obsolete.date.formats + * + * @param {string} date + * @returns {Date | undefined} + */ +function parseAscTimeDate (date) { + // This is assumed to be in UTC - // 3. Otherwise, if res's status is not 200, or if res's `Content-Type` - // is not `text/event-stream`, then fail the connection. - const contentType = response.headersList.get('content-type', true) - const mimeType = contentType !== null ? parseMIMEType(contentType) : 'failure' - const contentTypeValid = mimeType !== 'failure' && mimeType.essence === 'text/event-stream' - if ( - response.status !== 200 || - contentTypeValid === false - ) { - this.close() - this.dispatchEvent(new Event('error')) - return - } + if ( + date.length !== 24 || + date[7] !== ' ' || + date[10] !== ' ' || + date[19] !== ' ' + ) { + return undefined + } - // 4. Otherwise, announce the connection and interpret res's body - // line by line. + let weekday = -1 + if (date[0] === 'S' && date[1] === 'u' && date[2] === 'n') { // Sunday + weekday = 0 + } else if (date[0] === 'M' && date[1] === 'o' && date[2] === 'n') { // Monday + weekday = 1 + } else if (date[0] === 'T' && date[1] === 'u' && date[2] === 'e') { // Tuesday + weekday = 2 + } else if (date[0] === 'W' && date[1] === 'e' && date[2] === 'd') { // Wednesday + weekday = 3 + } else if (date[0] === 'T' && date[1] === 'h' && date[2] === 'u') { // Thursday + weekday = 4 + } else if (date[0] === 'F' && date[1] === 'r' && date[2] === 'i') { // Friday + weekday = 5 + } else if (date[0] === 'S' && date[1] === 'a' && date[2] === 't') { // Saturday + weekday = 6 + } else { + return undefined // Not a valid day of the week + } - // When a user agent is to announce the connection, the user agent - // must queue a task which, if the readyState attribute is set to a - // value other than CLOSED, sets the readyState attribute to OPEN - // and fires an event named open at the EventSource object. - // @see https://html.spec.whatwg.org/multipage/server-sent-events.html#sse-processing-model - this.#readyState = OPEN - this.dispatchEvent(new Event('open')) - - // If redirected to a different origin, set the origin to the new origin. - this.#state.origin = response.urlList[response.urlList.length - 1].origin - - const eventSourceStream = new EventSourceStream({ - eventSourceSettings: this.#state, - push: (event) => { - this.dispatchEvent(createFastMessageEvent( - event.type, - event.options - )) - } - }) - - pipeline(response.body.stream, - eventSourceStream, - (error) => { - if ( - error?.aborted === false - ) { - this.close() - this.dispatchEvent(new Event('error')) - } - }) + let monthIdx = -1 + if ( + (date[4] === 'J' && date[5] === 'a' && date[6] === 'n') + ) { + monthIdx = 0 // Jan + } else if ( + (date[4] === 'F' && date[5] === 'e' && date[6] === 'b') + ) { + monthIdx = 1 // Feb + } else if ( + (date[4] === 'M' && date[5] === 'a') + ) { + if (date[6] === 'r') { + monthIdx = 2 // Mar + } else if (date[6] === 'y') { + monthIdx = 4 // May + } else { + return undefined // Invalid month } - - this.#controller = fetching(fetchParams) + } else if ( + (date[4] === 'J') + ) { + if (date[5] === 'a' && date[6] === 'n') { + monthIdx = 0 // Jan + } else if (date[5] === 'u') { + if (date[6] === 'n') { + monthIdx = 5 // Jun + } else if (date[6] === 'l') { + monthIdx = 6 // Jul + } else { + return undefined // Invalid month + } + } else { + return undefined // Invalid month + } + } else if ( + (date[4] === 'A') + ) { + if (date[5] === 'p' && date[6] === 'r') { + monthIdx = 3 // Apr + } else if (date[5] === 'u' && date[6] === 'g') { + monthIdx = 7 // Aug + } else { + return undefined // Invalid month + } + } else if ( + (date[4] === 'S' && date[5] === 'e' && date[6] === 'p') + ) { + monthIdx = 8 // Sep + } else if ( + (date[4] === 'O' && date[5] === 'c' && date[6] === 't') + ) { + monthIdx = 9 // Oct + } else if ( + (date[4] === 'N' && date[5] === 'o' && date[6] === 'v') + ) { + monthIdx = 10 // Nov + } else if ( + (date[4] === 'D' && date[5] === 'e' && date[6] === 'c') + ) { + monthIdx = 11 // Dec + } else { + // Not a valid month + return undefined } - /** - * @see https://html.spec.whatwg.org/multipage/server-sent-events.html#sse-processing-model - * @returns {void} - */ - #reconnect () { - // When a user agent is to reestablish the connection, the user agent must - // run the following steps. These steps are run in parallel, not as part of - // a task. (The tasks that it queues, of course, are run like normal tasks - // and not themselves in parallel.) - - // 1. Queue a task to run the following steps: - - // 1. If the readyState attribute is set to CLOSED, abort the task. - if (this.#readyState === CLOSED) return - - // 2. Set the readyState attribute to CONNECTING. - this.#readyState = CONNECTING - - // 3. Fire an event named error at the EventSource object. - this.dispatchEvent(new Event('error')) + let day = 0 + if (date[8] === ' ') { + // Single digit day, e.g. "Sun Nov 6 08:49:37 1994" + const code = date.charCodeAt(9) + if (code < 49 || code > 57) { + return undefined // Not a digit + } + day = code - 48 // Convert ASCII code to number + } else { + const code1 = date.charCodeAt(8) + if (code1 < 49 || code1 > 51) { + return undefined // Not a digit between 1 and 3 + } + const code2 = date.charCodeAt(9) + if (code2 < 48 || code2 > 57) { + return undefined // Not a digit + } + day = (code1 - 48) * 10 + (code2 - 48) // Convert ASCII codes to number + } - // 2. Wait a delay equal to the reconnection time of the event source. - setTimeout(() => { - // 5. Queue a task to run the following steps: + let hour = 0 + if (date[11] === '0') { + const code = date.charCodeAt(12) + if (code < 48 || code > 57) { + return undefined // Not a digit + } + hour = code - 48 // Convert ASCII code to number + } else { + const code1 = date.charCodeAt(11) + if (code1 < 48 || code1 > 50) { + return undefined // Not a digit between 0 and 2 + } + const code2 = date.charCodeAt(12) + if (code2 < 48 || code2 > 57) { + return undefined // Not a digit + } + if (code1 === 50 && code2 > 51) { + return undefined // Hour cannot be greater than 23 + } + hour = (code1 - 48) * 10 + (code2 - 48) // Convert ASCII codes to number + } - // 1. If the EventSource object's readyState attribute is not set to - // CONNECTING, then return. - if (this.#readyState !== CONNECTING) return + let minute = 0 + if (date[14] === '0') { + const code = date.charCodeAt(15) + if (code < 48 || code > 57) { + return undefined // Not a digit + } + minute = code - 48 // Convert ASCII code to number + } else { + const code1 = date.charCodeAt(14) + if (code1 < 48 || code1 > 53) { + return undefined // Not a digit between 0 and 5 + } + const code2 = date.charCodeAt(15) + if (code2 < 48 || code2 > 57) { + return undefined // Not a digit + } + minute = (code1 - 48) * 10 + (code2 - 48) // Convert ASCII codes to number + } - // 2. Let request be the EventSource object's request. - // 3. If the EventSource object's last event ID string is not the empty - // string, then: - // 1. Let lastEventIDValue be the EventSource object's last event ID - // string, encoded as UTF-8. - // 2. Set (`Last-Event-ID`, lastEventIDValue) in request's header - // list. - if (this.#state.lastEventId.length) { - this.#request.headersList.set('last-event-id', this.#state.lastEventId, true) - } + let second = 0 + if (date[17] === '0') { + const code = date.charCodeAt(18) + if (code < 48 || code > 57) { + return undefined // Not a digit + } + second = code - 48 // Convert ASCII code to number + } else { + const code1 = date.charCodeAt(17) + if (code1 < 48 || code1 > 53) { + return undefined // Not a digit between 0 and 5 + } + const code2 = date.charCodeAt(18) + if (code2 < 48 || code2 > 57) { + return undefined // Not a digit + } + second = (code1 - 48) * 10 + (code2 - 48) // Convert ASCII codes to number + } - // 4. Fetch request and process the response obtained in this fashion, if any, as described earlier in this section. - this.#connect() - }, this.#state.reconnectionTime)?.unref() + const yearDigit1 = date.charCodeAt(20) + if (yearDigit1 < 48 || yearDigit1 > 57) { + return undefined // Not a digit + } + const yearDigit2 = date.charCodeAt(21) + if (yearDigit2 < 48 || yearDigit2 > 57) { + return undefined // Not a digit + } + const yearDigit3 = date.charCodeAt(22) + if (yearDigit3 < 48 || yearDigit3 > 57) { + return undefined // Not a digit + } + const yearDigit4 = date.charCodeAt(23) + if (yearDigit4 < 48 || yearDigit4 > 57) { + return undefined // Not a digit } + const year = (yearDigit1 - 48) * 1000 + (yearDigit2 - 48) * 100 + (yearDigit3 - 48) * 10 + (yearDigit4 - 48) - /** - * Closes the connection, if any, and sets the readyState attribute to - * CLOSED. - */ - close () { - webidl.brandCheck(this, EventSource) + const result = new Date(Date.UTC(year, monthIdx, day, hour, minute, second)) + return result.getUTCDay() === weekday ? result : undefined +} - if (this.#readyState === CLOSED) return - this.#readyState = CLOSED - this.#controller.abort() - this.#request = null +/** + * @see https://httpwg.org/specs/rfc9110.html#obsolete.date.formats + * + * @param {string} date + * @returns {Date | undefined} + */ +function parseRfc850Date (date) { + let commaIndex = -1 + + let weekday = -1 + if (date[0] === 'S') { + if (date[1] === 'u' && date[2] === 'n' && date[3] === 'd' && date[4] === 'a' && date[5] === 'y') { + weekday = 0 // Sunday + commaIndex = 6 + } else if (date[1] === 'a' && date[2] === 't' && date[3] === 'u' && date[4] === 'r' && date[5] === 'd' && date[6] === 'a' && date[7] === 'y') { + weekday = 6 // Saturday + commaIndex = 8 + } + } else if (date[0] === 'M' && date[1] === 'o' && date[2] === 'n' && date[3] === 'd' && date[4] === 'a' && date[5] === 'y') { + weekday = 1 // Monday + commaIndex = 6 + } else if (date[0] === 'T') { + if (date[1] === 'u' && date[2] === 'e' && date[3] === 's' && date[4] === 'd' && date[5] === 'a' && date[6] === 'y') { + weekday = 2 // Tuesday + commaIndex = 7 + } else if (date[1] === 'h' && date[2] === 'u' && date[3] === 'r' && date[4] === 's' && date[5] === 'd' && date[6] === 'a' && date[7] === 'y') { + weekday = 4 // Thursday + commaIndex = 8 + } + } else if (date[0] === 'W' && date[1] === 'e' && date[2] === 'd' && date[3] === 'n' && date[4] === 'e' && date[5] === 's' && date[6] === 'd' && date[7] === 'a' && date[8] === 'y') { + weekday = 3 // Wednesday + commaIndex = 9 + } else if (date[0] === 'F' && date[1] === 'r' && date[2] === 'i' && date[3] === 'd' && date[4] === 'a' && date[5] === 'y') { + weekday = 5 // Friday + commaIndex = 6 + } else { + // Not a valid day name + return undefined } - get onopen () { - return this.#events.open + if ( + date[commaIndex] !== ',' || + (date.length - commaIndex - 1) !== 23 || + date[commaIndex + 1] !== ' ' || + date[commaIndex + 4] !== '-' || + date[commaIndex + 8] !== '-' || + date[commaIndex + 11] !== ' ' || + date[commaIndex + 14] !== ':' || + date[commaIndex + 17] !== ':' || + date[commaIndex + 20] !== ' ' || + date[commaIndex + 21] !== 'G' || + date[commaIndex + 22] !== 'M' || + date[commaIndex + 23] !== 'T' + ) { + return undefined } - set onopen (fn) { - if (this.#events.open) { - this.removeEventListener('open', this.#events.open) + let day = 0 + if (date[commaIndex + 2] === '0') { + // Single digit day, e.g. "Sun Nov 6 08:49:37 1994" + const code = date.charCodeAt(commaIndex + 3) + if (code < 49 || code > 57) { + return undefined // Not a digit } - - const listener = webidl.converters.EventHandlerNonNull(fn) - - if (listener !== null) { - this.addEventListener('open', listener) - this.#events.open = fn - } else { - this.#events.open = null + day = code - 48 // Convert ASCII code to number + } else { + const code1 = date.charCodeAt(commaIndex + 2) + if (code1 < 49 || code1 > 51) { + return undefined // Not a digit between 1 and 3 + } + const code2 = date.charCodeAt(commaIndex + 3) + if (code2 < 48 || code2 > 57) { + return undefined // Not a digit } + day = (code1 - 48) * 10 + (code2 - 48) // Convert ASCII codes to number } - get onmessage () { - return this.#events.message + let monthIdx = -1 + if ( + (date[commaIndex + 5] === 'J' && date[commaIndex + 6] === 'a' && date[commaIndex + 7] === 'n') + ) { + monthIdx = 0 // Jan + } else if ( + (date[commaIndex + 5] === 'F' && date[commaIndex + 6] === 'e' && date[commaIndex + 7] === 'b') + ) { + monthIdx = 1 // Feb + } else if ( + (date[commaIndex + 5] === 'M' && date[commaIndex + 6] === 'a' && date[commaIndex + 7] === 'r') + ) { + monthIdx = 2 // Mar + } else if ( + (date[commaIndex + 5] === 'A' && date[commaIndex + 6] === 'p' && date[commaIndex + 7] === 'r') + ) { + monthIdx = 3 // Apr + } else if ( + (date[commaIndex + 5] === 'M' && date[commaIndex + 6] === 'a' && date[commaIndex + 7] === 'y') + ) { + monthIdx = 4 // May + } else if ( + (date[commaIndex + 5] === 'J' && date[commaIndex + 6] === 'u' && date[commaIndex + 7] === 'n') + ) { + monthIdx = 5 // Jun + } else if ( + (date[commaIndex + 5] === 'J' && date[commaIndex + 6] === 'u' && date[commaIndex + 7] === 'l') + ) { + monthIdx = 6 // Jul + } else if ( + (date[commaIndex + 5] === 'A' && date[commaIndex + 6] === 'u' && date[commaIndex + 7] === 'g') + ) { + monthIdx = 7 // Aug + } else if ( + (date[commaIndex + 5] === 'S' && date[commaIndex + 6] === 'e' && date[commaIndex + 7] === 'p') + ) { + monthIdx = 8 // Sep + } else if ( + (date[commaIndex + 5] === 'O' && date[commaIndex + 6] === 'c' && date[commaIndex + 7] === 't') + ) { + monthIdx = 9 // Oct + } else if ( + (date[commaIndex + 5] === 'N' && date[commaIndex + 6] === 'o' && date[commaIndex + 7] === 'v') + ) { + monthIdx = 10 // Nov + } else if ( + (date[commaIndex + 5] === 'D' && date[commaIndex + 6] === 'e' && date[commaIndex + 7] === 'c') + ) { + monthIdx = 11 // Dec + } else { + // Not a valid month + return undefined } - set onmessage (fn) { - if (this.#events.message) { - this.removeEventListener('message', this.#events.message) - } + const yearDigit1 = date.charCodeAt(commaIndex + 9) + if (yearDigit1 < 48 || yearDigit1 > 57) { + return undefined // Not a digit + } + const yearDigit2 = date.charCodeAt(commaIndex + 10) + if (yearDigit2 < 48 || yearDigit2 > 57) { + return undefined // Not a digit + } - const listener = webidl.converters.EventHandlerNonNull(fn) + let year = (yearDigit1 - 48) * 10 + (yearDigit2 - 48) // Convert ASCII codes to number - if (listener !== null) { - this.addEventListener('message', listener) - this.#events.message = fn - } else { - this.#events.message = null + // RFC 6265 states that the year is in the range 1970-2069. + // @see https://datatracker.ietf.org/doc/html/rfc6265#section-5.1.1 + // + // 3. If the year-value is greater than or equal to 70 and less than or + // equal to 99, increment the year-value by 1900. + // 4. If the year-value is greater than or equal to 0 and less than or + // equal to 69, increment the year-value by 2000. + year += year < 70 ? 2000 : 1900 + + let hour = 0 + if (date[commaIndex + 12] === '0') { + const code = date.charCodeAt(commaIndex + 13) + if (code < 48 || code > 57) { + return undefined // Not a digit + } + hour = code - 48 // Convert ASCII code to number + } else { + const code1 = date.charCodeAt(commaIndex + 12) + if (code1 < 48 || code1 > 50) { + return undefined // Not a digit between 0 and 2 + } + const code2 = date.charCodeAt(commaIndex + 13) + if (code2 < 48 || code2 > 57) { + return undefined // Not a digit + } + if (code1 === 50 && code2 > 51) { + return undefined // Hour cannot be greater than 23 } + hour = (code1 - 48) * 10 + (code2 - 48) // Convert ASCII codes to number } - get onerror () { - return this.#events.error + let minute = 0 + if (date[commaIndex + 15] === '0') { + const code = date.charCodeAt(commaIndex + 16) + if (code < 48 || code > 57) { + return undefined // Not a digit + } + minute = code - 48 // Convert ASCII code to number + } else { + const code1 = date.charCodeAt(commaIndex + 15) + if (code1 < 48 || code1 > 53) { + return undefined // Not a digit between 0 and 5 + } + const code2 = date.charCodeAt(commaIndex + 16) + if (code2 < 48 || code2 > 57) { + return undefined // Not a digit + } + minute = (code1 - 48) * 10 + (code2 - 48) // Convert ASCII codes to number } - set onerror (fn) { - if (this.#events.error) { - this.removeEventListener('error', this.#events.error) + let second = 0 + if (date[commaIndex + 18] === '0') { + const code = date.charCodeAt(commaIndex + 19) + if (code < 48 || code > 57) { + return undefined // Not a digit } - - const listener = webidl.converters.EventHandlerNonNull(fn) - - if (listener !== null) { - this.addEventListener('error', listener) - this.#events.error = fn - } else { - this.#events.error = null + second = code - 48 // Convert ASCII code to number + } else { + const code1 = date.charCodeAt(commaIndex + 18) + if (code1 < 48 || code1 > 53) { + return undefined // Not a digit between 0 and 5 + } + const code2 = date.charCodeAt(commaIndex + 19) + if (code2 < 48 || code2 > 57) { + return undefined // Not a digit } + second = (code1 - 48) * 10 + (code2 - 48) // Convert ASCII codes to number } + + const result = new Date(Date.UTC(year, monthIdx, day, hour, minute, second)) + return result.getUTCDay() === weekday ? result : undefined } -const constantsPropertyDescriptors = { - CONNECTING: { - __proto__: null, - configurable: false, - enumerable: true, - value: CONNECTING, - writable: false - }, - OPEN: { - __proto__: null, - configurable: false, - enumerable: true, - value: OPEN, - writable: false - }, - CLOSED: { - __proto__: null, - configurable: false, - enumerable: true, - value: CLOSED, - writable: false - } +module.exports = { + parseHttpDate } -Object.defineProperties(EventSource, constantsPropertyDescriptors) -Object.defineProperties(EventSource.prototype, constantsPropertyDescriptors) -Object.defineProperties(EventSource.prototype, { - close: kEnumerableProperty, - onerror: kEnumerableProperty, - onmessage: kEnumerableProperty, - onopen: kEnumerableProperty, - readyState: kEnumerableProperty, - url: kEnumerableProperty, - withCredentials: kEnumerableProperty -}) +/***/ }), -webidl.converters.EventSourceInitDict = webidl.dictionaryConverter([ - { - key: 'withCredentials', - converter: webidl.converters.boolean, - defaultValue: () => false - }, - { - key: 'dispatcher', // undici only - converter: webidl.converters.any - }, - { - key: 'node', // undici only - converter: webidl.dictionaryConverter([ - { - key: 'reconnectionTime', - converter: webidl.converters['unsigned long'], - defaultValue: () => defaultReconnectionTime - }, - { - key: 'dispatcher', - converter: webidl.converters.any - } - ]), - defaultValue: () => ({}) - } -]) - -module.exports = { - EventSource, - defaultReconnectionTime -} - - -/***/ }), - -/***/ 1970: +/***/ 3022: /***/ ((module) => { -"use strict"; /** - * Checks if the given value is a valid LastEventId. - * @param {string} value - * @returns {boolean} + * @template {*} T + * @typedef {Object} DeferredPromise + * @property {Promise} promise + * @property {(value?: T) => void} resolve + * @property {(reason?: any) => void} reject */ -function isValidLastEventId (value) { - // LastEventId should not contain U+0000 NULL - return value.indexOf('\u0000') === -1 -} /** - * Checks if the given value is a base 10 digit. - * @param {string} value - * @returns {boolean} + * @template {*} T + * @returns {DeferredPromise} An object containing a promise and its resolve/reject methods. */ -function isASCIINumber (value) { - if (value.length === 0) return false - for (let i = 0; i < value.length; i++) { - if (value.charCodeAt(i) < 0x30 || value.charCodeAt(i) > 0x39) return false - } - return true +function createDeferredPromise () { + let res + let rej + const promise = new Promise((resolve, reject) => { + res = resolve + rej = reject + }) + + return { promise, resolve: res, reject: rej } } module.exports = { - isValidLastEventId, - isASCIINumber + createDeferredPromise } /***/ }), -/***/ 2921: +/***/ 3895: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; - -const util = __nccwpck_require__(983) -const { - ReadableStreamFrom, - readableStreamClose, - fullyReadBody, - extractMimeType -} = __nccwpck_require__(8913) -const { FormData, setFormDataState } = __nccwpck_require__(51) -const { webidl } = __nccwpck_require__(2318) -const assert = __nccwpck_require__(4589) -const { isErrored, isDisturbed } = __nccwpck_require__(7075) -const { isArrayBuffer } = __nccwpck_require__(3429) -const { serializeAMimeType } = __nccwpck_require__(9425) -const { multipartFormDataParser } = __nccwpck_require__(9211) -const { createDeferredPromise } = __nccwpck_require__(9797) -const { parseJSONFromBytes } = __nccwpck_require__(3883) -const { utf8DecodeBytes } = __nccwpck_require__(9825) -const { runtimeFeatures } = __nccwpck_require__(1422) -const random = runtimeFeatures.has('crypto') - ? (__nccwpck_require__(7598).randomInt) - : (max) => Math.floor(Math.random() * max) +/** @typedef {`node:${string}`} NodeModuleName */ -const textEncoder = new TextEncoder() -function noop () {} +/** @type {Record any>} */ +const lazyLoaders = { + __proto__: null, + 'node:crypto': () => __nccwpck_require__(7598), + 'node:sqlite': () => __nccwpck_require__(99), + 'node:worker_threads': () => __nccwpck_require__(5919), + 'node:zlib': () => __nccwpck_require__(8522) +} -const streamRegistry = new FinalizationRegistry((weakRef) => { - const stream = weakRef.deref() - if (stream && !stream.locked && !isDisturbed(stream) && !isErrored(stream)) { - stream.cancel('Response object has been garbage collected').catch(noop) +/** + * @param {NodeModuleName} moduleName + * @returns {boolean} + */ +function detectRuntimeFeatureByNodeModule (moduleName) { + try { + lazyLoaders[moduleName]() + return true + } catch (err) { + if (err.code !== 'ERR_UNKNOWN_BUILTIN_MODULE' && err.code !== 'ERR_NO_CRYPTO') { + throw err + } + return false } -}) +} /** - * Extract a body with type from a byte sequence or BodyInit object - * - * @param {import('../../../types').BodyInit} object - The BodyInit object to extract from - * @param {boolean} [keepalive=false] - If true, indicates that the body - * @returns {[{stream: ReadableStream, source: any, length: number | null}, string | null]} - Returns a tuple containing the body and its type - * - * @see https://fetch.spec.whatwg.org/#concept-bodyinit-extract + * @param {NodeModuleName} moduleName + * @param {string} property + * @returns {boolean} */ -function extractBody (object, keepalive = false) { - // 1. Let stream be null. - let stream = null +function detectRuntimeFeatureByExportedProperty (moduleName, property) { + const module = lazyLoaders[moduleName]() + return typeof module[property] !== 'undefined' +} - // 2. If object is a ReadableStream object, then set stream to object. - if (webidl.is.ReadableStream(object)) { - stream = object - } else if (webidl.is.Blob(object)) { - // 3. Otherwise, if object is a Blob object, set stream to the - // result of running object’s get stream. - stream = object.stream() - } else { - // 4. Otherwise, set stream to a new ReadableStream object, and set - // up stream with byte reading support. - stream = new ReadableStream({ - pull (controller) { - const buffer = typeof source === 'string' ? textEncoder.encode(source) : source +const runtimeFeaturesByExportedProperty = /** @type {const} */ (['markAsUncloneable', 'zstd']) - if (buffer.byteLength) { - controller.enqueue(buffer) - } +/** @type {Record} */ +const exportedPropertyLookup = { + markAsUncloneable: ['node:worker_threads', 'markAsUncloneable'], + zstd: ['node:zlib', 'createZstdDecompress'] +} - queueMicrotask(() => readableStreamClose(controller)) - }, - start () {}, - type: 'bytes' - }) - } +/** @typedef {typeof runtimeFeaturesByExportedProperty[number]} RuntimeFeatureByExportedProperty */ - // 5. Assert: stream is a ReadableStream object. - assert(webidl.is.ReadableStream(stream)) +const runtimeFeaturesAsNodeModule = /** @type {const} */ (['crypto', 'sqlite']) +/** @typedef {typeof runtimeFeaturesAsNodeModule[number]} RuntimeFeatureByNodeModule */ - // 6. Let action be null. - let action = null +const features = /** @type {const} */ ([ + ...runtimeFeaturesAsNodeModule, + ...runtimeFeaturesByExportedProperty +]) - // 7. Let source be null. - let source = null +/** @typedef {typeof features[number]} Feature */ - // 8. Let length be null. - let length = null +/** + * @param {Feature} feature + * @returns {boolean} + */ +function detectRuntimeFeature (feature) { + if (runtimeFeaturesAsNodeModule.includes(/** @type {RuntimeFeatureByNodeModule} */ (feature))) { + return detectRuntimeFeatureByNodeModule(`node:${feature}`) + } else if (runtimeFeaturesByExportedProperty.includes(/** @type {RuntimeFeatureByExportedProperty} */ (feature))) { + const [moduleName, property] = exportedPropertyLookup[feature] + return detectRuntimeFeatureByExportedProperty(moduleName, property) + } + throw new TypeError(`unknown feature: ${feature}`) +} - // 9. Let type be null. - let type = null +/** + * @class + * @name RuntimeFeatures + */ +class RuntimeFeatures { + /** @type {Map} */ + #map = new Map() - // 10. Switch on object: - if (typeof object === 'string') { - // Set source to the UTF-8 encoding of object. - // Note: setting source to a Uint8Array here breaks some mocking assumptions. - source = object + /** + * Clears all cached feature detections. + */ + clear () { + this.#map.clear() + } - // Set type to `text/plain;charset=UTF-8`. - type = 'text/plain;charset=UTF-8' - } else if (webidl.is.URLSearchParams(object)) { - // URLSearchParams + /** + * @param {Feature} feature + * @returns {boolean} + */ + has (feature) { + return ( + this.#map.get(feature) ?? this.#detectRuntimeFeature(feature) + ) + } - // spec says to run application/x-www-form-urlencoded on body.list - // this is implemented in Node.js as apart of an URLSearchParams instance toString method - // See: https://github.com/nodejs/node/blob/e46c680bf2b211bbd52cf959ca17ee98c7f657f5/lib/internal/url.js#L490 - // and https://github.com/nodejs/node/blob/e46c680bf2b211bbd52cf959ca17ee98c7f657f5/lib/internal/url.js#L1100 + /** + * @param {Feature} feature + * @param {boolean} value + */ + set (feature, value) { + if (features.includes(feature) === false) { + throw new TypeError(`unknown feature: ${feature}`) + } + this.#map.set(feature, value) + } - // Set source to the result of running the application/x-www-form-urlencoded serializer with object’s list. - source = object.toString() + /** + * @param {Feature} feature + * @returns {boolean} + */ + #detectRuntimeFeature (feature) { + const result = detectRuntimeFeature(feature) + this.#map.set(feature, result) + return result + } +} - // Set type to `application/x-www-form-urlencoded;charset=UTF-8`. - type = 'application/x-www-form-urlencoded;charset=UTF-8' - } else if (webidl.is.BufferSource(object)) { - source = isArrayBuffer(object) - ? new Uint8Array(object.slice()) - : new Uint8Array(object.buffer.slice(object.byteOffset, object.byteOffset + object.byteLength)) - } else if (webidl.is.FormData(object)) { - const boundary = `----formdata-undici-0${`${random(1e11)}`.padStart(11, '0')}` - const prefix = `--${boundary}\r\nContent-Disposition: form-data` +const instance = new RuntimeFeatures() - /*! formdata-polyfill. MIT License. Jimmy Wärting */ - const formdataEscape = (str) => - str.replace(/\n/g, '%0A').replace(/\r/g, '%0D').replace(/"/g, '%22') - const normalizeLinefeeds = (value) => value.replace(/\r?\n|\r/g, '\r\n') +module.exports.runtimeFeatures = instance +module.exports["default"] = instance - // Set action to this step: run the multipart/form-data - // encoding algorithm, with object’s entry list and UTF-8. - // - This ensures that the body is immutable and can't be changed afterwords - // - That the content-length is calculated in advance. - // - And that all parts are pre-encoded and ready to be sent. - const blobParts = [] - const rn = new Uint8Array([13, 10]) // '\r\n' - length = 0 - let hasUnknownSizeValue = false +/***/ }), - for (const [name, value] of object) { - if (typeof value === 'string') { - const chunk = textEncoder.encode(prefix + - `; name="${formdataEscape(normalizeLinefeeds(name))}"` + - `\r\n\r\n${normalizeLinefeeds(value)}\r\n`) - blobParts.push(chunk) - length += chunk.byteLength - } else { - const chunk = textEncoder.encode(`${prefix}; name="${formdataEscape(normalizeLinefeeds(name))}"` + - (value.name ? `; filename="${formdataEscape(value.name)}"` : '') + '\r\n' + - `Content-Type: ${ - value.type || 'application/octet-stream' - }\r\n\r\n`) - blobParts.push(chunk, value, rn) - if (typeof value.size === 'number') { - length += chunk.byteLength + value.size + rn.byteLength - } else { - hasUnknownSizeValue = true - } - } - } +/***/ 7044: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - // CRLF is appended to the body to function with legacy servers and match other implementations. - // https://github.com/curl/curl/blob/3434c6b46e682452973972e8313613dfa58cd690/lib/mime.c#L1029-L1030 - // https://github.com/form-data/form-data/issues/63 - const chunk = textEncoder.encode(`--${boundary}--\r\n`) - blobParts.push(chunk) - length += chunk.byteLength - if (hasUnknownSizeValue) { - length = null - } - // Set source to object. - source = object - action = async function * () { - for (const part of blobParts) { - if (part.stream) { - yield * part.stream() - } else { - yield part - } - } - } +const { + kConnected, + kPending, + kRunning, + kSize, + kFree, + kQueued +} = __nccwpck_require__(8261) - // Set type to `multipart/form-data; boundary=`, - // followed by the multipart/form-data boundary string generated - // by the multipart/form-data encoding algorithm. - type = `multipart/form-data; boundary=${boundary}` - } else if (webidl.is.Blob(object)) { - // Blob +class ClientStats { + constructor (client) { + this.connected = client[kConnected] + this.pending = client[kPending] + this.running = client[kRunning] + this.size = client[kSize] + } +} - // Set source to object. - source = object +class PoolStats { + constructor (pool) { + this.connected = pool[kConnected] + this.free = pool[kFree] + this.pending = pool[kPending] + this.queued = pool[kQueued] + this.running = pool[kRunning] + this.size = pool[kSize] + } +} - // Set length to object’s size. - length = object.size +module.exports = { ClientStats, PoolStats } - // If object’s type attribute is not the empty byte sequence, set - // type to its value. - if (object.type) { - type = object.type - } - } else if (typeof object[Symbol.asyncIterator] === 'function') { - // If keepalive is true, then throw a TypeError. - if (keepalive) { - throw new TypeError('keepalive') - } - // If object is disturbed or locked, then throw a TypeError. - if (util.isDisturbed(object) || object.locked) { - throw new TypeError( - 'Response body object should not be disturbed or locked' - ) - } +/***/ }), - stream = - webidl.is.ReadableStream(object) ? object : ReadableStreamFrom(object) - } +/***/ 8621: +/***/ ((module) => { - // 11. If source is a byte sequence, then set action to a - // step that returns source and length to source’s length. - if (typeof source === 'string' || util.isBuffer(source)) { - length = Buffer.byteLength(source) - } - // 12. If action is non-null, then run these steps in in parallel: - if (action != null) { - // Run action. - let iterator - stream = new ReadableStream({ - start () { - iterator = action(object)[Symbol.asyncIterator]() - }, - pull (controller) { - return iterator.next().then(({ value, done }) => { - if (done) { - // When running action is done, close stream. - queueMicrotask(() => { - controller.close() - controller.byobRequest?.respond(0) - }) - } else { - // Whenever one or more bytes are available and stream is not errored, - // enqueue a Uint8Array wrapping an ArrayBuffer containing the available - // bytes into stream. - if (!isErrored(stream)) { - const buffer = new Uint8Array(value) - if (buffer.byteLength) { - controller.enqueue(buffer) - } - } - } - return controller.desiredSize > 0 - }) - }, - cancel (reason) { - return iterator.return() - }, - type: 'bytes' - }) - } - // 13. Let body be a body whose stream is stream, source is source, - // and length is length. - const body = { stream, source, length } +/** + * This module offers an optimized timer implementation designed for scenarios + * where high precision is not critical. + * + * The timer achieves faster performance by using a low-resolution approach, + * with an accuracy target of within 500ms. This makes it particularly useful + * for timers with delays of 1 second or more, where exact timing is less + * crucial. + * + * It's important to note that Node.js timers are inherently imprecise, as + * delays can occur due to the event loop being blocked by other operations. + * Consequently, timers may trigger later than their scheduled time. + */ - // 14. Return (body, type). - return [body, type] -} +/** + * The fastNow variable contains the internal fast timer clock value. + * + * @type {number} + */ +let fastNow = 0 /** - * @typedef {object} ExtractBodyResult - * @property {ReadableStream>} stream - The ReadableStream containing the body data - * @property {any} source - The original source of the body data - * @property {number | null} length - The length of the body data, or null + * RESOLUTION_MS represents the target resolution time in milliseconds. + * + * @type {number} + * @default 1000 */ +const RESOLUTION_MS = 1e3 /** - * Safely extract a body with type from a byte sequence or BodyInit object. + * TICK_MS defines the desired interval in milliseconds between each tick. + * The target value is set to half the resolution time, minus 1 ms, to account + * for potential event loop overhead. * - * @param {import('../../../types').BodyInit} object - The BodyInit object to extract from - * @param {boolean} [keepalive=false] - If true, indicates that the body - * @returns {[ExtractBodyResult, string | null]} - Returns a tuple containing the body and its type + * @type {number} + * @default 499 + */ +const TICK_MS = (RESOLUTION_MS >> 1) - 1 + +/** + * fastNowTimeout is a Node.js timer used to manage and process + * the FastTimers stored in the `fastTimers` array. * - * @see https://fetch.spec.whatwg.org/#bodyinit-safely-extract + * @type {NodeJS.Timeout} */ -function safelyExtractBody (object, keepalive = false) { - // To safely extract a body and a `Content-Type` value from - // a byte sequence or BodyInit object object, run these steps: +let fastNowTimeout - // 1. If object is a ReadableStream object, then: - if (webidl.is.ReadableStream(object)) { - // Assert: object is neither disturbed nor locked. - assert(!util.isDisturbed(object), 'The body has already been consumed.') - assert(!object.locked, 'The stream is locked.') - } +/** + * The kFastTimer symbol is used to identify FastTimer instances. + * + * @type {Symbol} + */ +const kFastTimer = Symbol('kFastTimer') - // 2. Return the results of extracting object. - return extractBody(object, keepalive) -} +/** + * The fastTimers array contains all active FastTimers. + * + * @type {FastTimer[]} + */ +const fastTimers = [] -function cloneBody (body) { - // To clone a body body, run these steps: +/** + * These constants represent the various states of a FastTimer. + */ - // https://fetch.spec.whatwg.org/#concept-body-clone +/** + * The `NOT_IN_LIST` constant indicates that the FastTimer is not included + * in the `fastTimers` array. Timers with this status will not be processed + * during the next tick by the `onTick` function. + * + * A FastTimer can be re-added to the `fastTimers` array by invoking the + * `refresh` method on the FastTimer instance. + * + * @type {-2} + */ +const NOT_IN_LIST = -2 - // 1. Let « out1, out2 » be the result of teeing body’s stream. - const { 0: out1, 1: out2 } = body.stream.tee() +/** + * The `TO_BE_CLEARED` constant indicates that the FastTimer is scheduled + * for removal from the `fastTimers` array. A FastTimer in this state will + * be removed in the next tick by the `onTick` function and will no longer + * be processed. + * + * This status is also set when the `clear` method is called on the FastTimer instance. + * + * @type {-1} + */ +const TO_BE_CLEARED = -1 - // 2. Set body’s stream to out1. - body.stream = out1 +/** + * The `PENDING` constant signifies that the FastTimer is awaiting processing + * in the next tick by the `onTick` function. Timers with this status will have + * their `_idleStart` value set and their status updated to `ACTIVE` in the next tick. + * + * @type {0} + */ +const PENDING = 0 - // 3. Return a body whose stream is out2 and other members are copied from body. - return { - stream: out2, - length: body.length, - source: body.source - } -} - -function bodyMixinMethods (instance, getInternalState) { - const methods = { - blob () { - // The blob() method steps are to return the result of - // running consume body with this and the following step - // given a byte sequence bytes: return a Blob whose - // contents are bytes and whose type attribute is this’s - // MIME type. - return consumeBody(this, (bytes) => { - let mimeType = bodyMimeType(getInternalState(this)) - - if (mimeType === null) { - mimeType = '' - } else if (mimeType) { - mimeType = serializeAMimeType(mimeType) - } - - // Return a Blob whose contents are bytes and type attribute - // is mimeType. - return new Blob([bytes], { type: mimeType }) - }, instance, getInternalState) - }, - - arrayBuffer () { - // The arrayBuffer() method steps are to return the result - // of running consume body with this and the following step - // given a byte sequence bytes: return a new ArrayBuffer - // whose contents are bytes. - return consumeBody(this, (bytes) => { - return new Uint8Array(bytes).buffer - }, instance, getInternalState) - }, - - text () { - // The text() method steps are to return the result of running - // consume body with this and UTF-8 decode. - return consumeBody(this, utf8DecodeBytes, instance, getInternalState) - }, - - json () { - // The json() method steps are to return the result of running - // consume body with this and parse JSON from bytes. - return consumeBody(this, parseJSONFromBytes, instance, getInternalState) - }, - - formData () { - // The formData() method steps are to return the result of running - // consume body with this and the following step given a byte sequence bytes: - return consumeBody(this, (value) => { - // 1. Let mimeType be the result of get the MIME type with this. - const mimeType = bodyMimeType(getInternalState(this)) - - // 2. If mimeType is non-null, then switch on mimeType’s essence and run - // the corresponding steps: - if (mimeType !== null) { - switch (mimeType.essence) { - case 'multipart/form-data': { - // 1. ... [long step] - // 2. If that fails for some reason, then throw a TypeError. - const parsed = multipartFormDataParser(value, mimeType) - - // 3. Return a new FormData object, appending each entry, - // resulting from the parsing operation, to its entry list. - const fd = new FormData() - setFormDataState(fd, parsed) +/** + * The `ACTIVE` constant indicates that the FastTimer is active and waiting + * for its timer to expire. During the next tick, the `onTick` function will + * check if the timer has expired, and if so, it will execute the associated callback. + * + * @type {1} + */ +const ACTIVE = 1 - return fd - } - case 'application/x-www-form-urlencoded': { - // 1. Let entries be the result of parsing bytes. - const entries = new URLSearchParams(value.toString()) +/** + * The onTick function processes the fastTimers array. + * + * @returns {void} + */ +function onTick () { + /** + * Increment the fastNow value by the TICK_MS value, despite the actual time + * that has passed since the last tick. This approach ensures independence + * from the system clock and delays caused by a blocked event loop. + * + * @type {number} + */ + fastNow += TICK_MS - // 2. If entries is failure, then throw a TypeError. + /** + * The `idx` variable is used to iterate over the `fastTimers` array. + * Expired timers are removed by replacing them with the last element in the array. + * Consequently, `idx` is only incremented when the current element is not removed. + * + * @type {number} + */ + let idx = 0 - // 3. Return a new FormData object whose entry list is entries. - const fd = new FormData() + /** + * The len variable will contain the length of the fastTimers array + * and will be decremented when a FastTimer should be removed from the + * fastTimers array. + * + * @type {number} + */ + let len = fastTimers.length - for (const [name, value] of entries) { - fd.append(name, value) - } + while (idx < len) { + /** + * @type {FastTimer} + */ + const timer = fastTimers[idx] - return fd - } - } - } + // If the timer is in the ACTIVE state and the timer has expired, it will + // be processed in the next tick. + if (timer._state === PENDING) { + // Set the _idleStart value to the fastNow value minus the TICK_MS value + // to account for the time the timer was in the PENDING state. + timer._idleStart = fastNow - TICK_MS + timer._state = ACTIVE + } else if ( + timer._state === ACTIVE && + fastNow >= timer._idleStart + timer._idleTimeout + ) { + timer._state = TO_BE_CLEARED + timer._idleStart = -1 + timer._onTimeout(timer._timerArg) + } - // 3. Throw a TypeError. - throw new TypeError( - 'Content-Type was not one of "multipart/form-data" or "application/x-www-form-urlencoded".' - ) - }, instance, getInternalState) - }, + if (timer._state === TO_BE_CLEARED) { + timer._state = NOT_IN_LIST - bytes () { - // The bytes() method steps are to return the result of running consume body - // with this and the following step given a byte sequence bytes: return the - // result of creating a Uint8Array from bytes in this’s relevant realm. - return consumeBody(this, (bytes) => { - return new Uint8Array(bytes) - }, instance, getInternalState) + // Move the last element to the current index and decrement len if it is + // not the only element in the array. + if (--len !== 0) { + fastTimers[idx] = fastTimers[len] + } + } else { + ++idx } } - return methods + // Set the length of the fastTimers array to the new length and thus + // removing the excess FastTimers elements from the array. + fastTimers.length = len + + // If there are still active FastTimers in the array, refresh the Timer. + // If there are no active FastTimers, the timer will be refreshed again + // when a new FastTimer is instantiated. + if (fastTimers.length !== 0) { + refreshTimeout() + } } -function mixinBody (prototype, getInternalState) { - Object.assign(prototype.prototype, bodyMixinMethods(prototype, getInternalState)) +function refreshTimeout () { + // If the fastNowTimeout is already set and the Timer has the refresh()- + // method available, call it to refresh the timer. + // Some timer objects returned by setTimeout may not have a .refresh() + // method (e.g. mocked timers in tests). + if (fastNowTimeout?.refresh) { + fastNowTimeout.refresh() + // fastNowTimeout is not instantiated yet or refresh is not availabe, + // create a new Timer. + } else { + clearTimeout(fastNowTimeout) + fastNowTimeout = setTimeout(onTick, TICK_MS) + // If the Timer has an unref method, call it to allow the process to exit, + // if there are no other active handles. When using fake timers or mocked + // environments (like Jest), .unref() may not be defined, + fastNowTimeout?.unref() + } } /** - * @see https://fetch.spec.whatwg.org/#concept-body-consume-body - * @param {any} object internal state - * @param {(value: unknown) => unknown} convertBytesToJSValue - * @param {any} instance - * @param {(target: any) => any} getInternalState + * The `FastTimer` class is a data structure designed to store and manage + * timer information. */ -function consumeBody (object, convertBytesToJSValue, instance, getInternalState) { - try { - webidl.brandCheck(object, instance) - } catch (e) { - return Promise.reject(e) - } +class FastTimer { + [kFastTimer] = true - const state = getInternalState(object) + /** + * The state of the timer, which can be one of the following: + * - NOT_IN_LIST (-2) + * - TO_BE_CLEARED (-1) + * - PENDING (0) + * - ACTIVE (1) + * + * @type {-2|-1|0|1} + * @private + */ + _state = NOT_IN_LIST - // 1. If object is unusable, then return a promise rejected - // with a TypeError. - if (bodyUnusable(state)) { - return Promise.reject(new TypeError('Body is unusable: Body has already been read')) - } + /** + * The number of milliseconds to wait before calling the callback. + * + * @type {number} + * @private + */ + _idleTimeout = -1 - if (state.aborted) { - return Promise.reject(new DOMException('The operation was aborted.', 'AbortError')) - } + /** + * The time in milliseconds when the timer was started. This value is used to + * calculate when the timer should expire. + * + * @type {number} + * @default -1 + * @private + */ + _idleStart = -1 - // 2. Let promise be a new promise. - const promise = createDeferredPromise() + /** + * The function to be executed when the timer expires. + * @type {Function} + * @private + */ + _onTimeout - // 3. Let errorSteps given error be to reject promise with error. - const errorSteps = promise.reject + /** + * The argument to be passed to the callback when the timer expires. + * + * @type {*} + * @private + */ + _timerArg - // 4. Let successSteps given a byte sequence data be to resolve - // promise with the result of running convertBytesToJSValue - // with data. If that threw an exception, then run errorSteps - // with that exception. - const successSteps = (data) => { - try { - promise.resolve(convertBytesToJSValue(data)) - } catch (e) { - errorSteps(e) - } - } + /** + * @constructor + * @param {Function} callback A function to be executed after the timer + * expires. + * @param {number} delay The time, in milliseconds that the timer should wait + * before the specified function or code is executed. + * @param {*} arg + */ + constructor (callback, delay, arg) { + this._onTimeout = callback + this._idleTimeout = delay + this._timerArg = arg - // 5. If object’s body is null, then run successSteps with an - // empty byte sequence. - if (state.body == null) { - successSteps(Buffer.allocUnsafe(0)) - return promise.promise + this.refresh() } - // 6. Otherwise, fully read object’s body given successSteps, - // errorSteps, and object’s relevant global object. - fullyReadBody(state.body, successSteps, errorSteps) - - // 7. Return promise. - return promise.promise -} - -/** - * @see https://fetch.spec.whatwg.org/#body-unusable - * @param {any} object internal state - */ -function bodyUnusable (object) { - const body = object.body + /** + * Sets the timer's start time to the current time, and reschedules the timer + * to call its callback at the previously specified duration adjusted to the + * current time. + * Using this on a timer that has already called its callback will reactivate + * the timer. + * + * @returns {void} + */ + refresh () { + // In the special case that the timer is not in the list of active timers, + // add it back to the array to be processed in the next tick by the onTick + // function. + if (this._state === NOT_IN_LIST) { + fastTimers.push(this) + } - // An object including the Body interface mixin is - // said to be unusable if its body is non-null and - // its body’s stream is disturbed or locked. - return body != null && (body.stream.locked || util.isDisturbed(body.stream)) -} + // If the timer is the only active timer, refresh the fastNowTimeout for + // better resolution. + if (!fastNowTimeout || fastTimers.length === 1) { + refreshTimeout() + } -/** - * @see https://fetch.spec.whatwg.org/#concept-body-mime-type - * @param {any} requestOrResponse internal state - */ -function bodyMimeType (requestOrResponse) { - // 1. Let headers be null. - // 2. If requestOrResponse is a Request object, then set headers to requestOrResponse’s request’s header list. - // 3. Otherwise, set headers to requestOrResponse’s response’s header list. - /** @type {import('./headers').HeadersList} */ - const headers = requestOrResponse.headersList + // Setting the state to PENDING will cause the timer to be reset in the + // next tick by the onTick function. + this._state = PENDING + } - // 4. Let mimeType be the result of extracting a MIME type from headers. - const mimeType = extractMimeType(headers) + /** + * The `clear` method cancels the timer, preventing it from executing. + * + * @returns {void} + * @private + */ + clear () { + // Set the state to TO_BE_CLEARED to mark the timer for removal in the next + // tick by the onTick function. + this._state = TO_BE_CLEARED - // 5. If mimeType is failure, then return null. - if (mimeType === 'failure') { - return null + // Reset the _idleStart value to -1 to indicate that the timer is no longer + // active. + this._idleStart = -1 } - - // 6. Return mimeType. - return mimeType } +/** + * This module exports a setTimeout and clearTimeout function that can be + * used as a drop-in replacement for the native functions. + */ module.exports = { - extractBody, - safelyExtractBody, - cloneBody, - mixinBody, - streamRegistry, - bodyUnusable + /** + * The setTimeout() method sets a timer which executes a function once the + * timer expires. + * @param {Function} callback A function to be executed after the timer + * expires. + * @param {number} delay The time, in milliseconds that the timer should + * wait before the specified function or code is executed. + * @param {*} [arg] An optional argument to be passed to the callback function + * when the timer expires. + * @returns {NodeJS.Timeout|FastTimer} + */ + setTimeout (callback, delay, arg) { + // If the delay is less than or equal to the RESOLUTION_MS value return a + // native Node.js Timer instance. + return delay <= RESOLUTION_MS + ? setTimeout(callback, delay, arg) + : new FastTimer(callback, delay, arg) + }, + /** + * The clearTimeout method cancels an instantiated Timer previously created + * by calling setTimeout. + * + * @param {NodeJS.Timeout|FastTimer} timeout + */ + clearTimeout (timeout) { + // If the timeout is a FastTimer, call its own clear method. + if (timeout[kFastTimer]) { + /** + * @type {FastTimer} + */ + timeout.clear() + // Otherwise it is an instance of a native NodeJS.Timeout, so call the + // Node.js native clearTimeout function. + } else { + clearTimeout(timeout) + } + }, + /** + * The setFastTimeout() method sets a fastTimer which executes a function once + * the timer expires. + * @param {Function} callback A function to be executed after the timer + * expires. + * @param {number} delay The time, in milliseconds that the timer should + * wait before the specified function or code is executed. + * @param {*} [arg] An optional argument to be passed to the callback function + * when the timer expires. + * @returns {FastTimer} + */ + setFastTimeout (callback, delay, arg) { + return new FastTimer(callback, delay, arg) + }, + /** + * The clearTimeout method cancels an instantiated FastTimer previously + * created by calling setFastTimeout. + * + * @param {FastTimer} timeout + */ + clearFastTimeout (timeout) { + timeout.clear() + }, + /** + * The now method returns the value of the internal fast timer clock. + * + * @returns {number} + */ + now () { + return fastNow + }, + /** + * Trigger the onTick function to process the fastTimers array. + * Exported for testing purposes only. + * Marking as deprecated to discourage any use outside of testing. + * @deprecated + * @param {number} [delay=0] The delay in milliseconds to add to the now value. + */ + tick (delay = 0) { + fastNow += delay - RESOLUTION_MS + 1 + onTick() + onTick() + }, + /** + * Reset FastTimers. + * Exported for testing purposes only. + * Marking as deprecated to discourage any use outside of testing. + * @deprecated + */ + reset () { + fastNow = 0 + fastTimers.length = 0 + clearTimeout(fastNowTimeout) + fastNowTimeout = null + }, + /** + * Exporting for testing purposes only. + * Marking as deprecated to discourage any use outside of testing. + * @deprecated + */ + kFastTimer } /***/ }), -/***/ 112: -/***/ ((module) => { - -"use strict"; +/***/ 336: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -const corsSafeListedMethods = /** @type {const} */ (['GET', 'HEAD', 'POST']) -const corsSafeListedMethodsSet = new Set(corsSafeListedMethods) -const nullBodyStatus = /** @type {const} */ ([101, 204, 205, 304]) +const assert = __nccwpck_require__(4589) -const redirectStatus = /** @type {const} */ ([301, 302, 303, 307, 308]) -const redirectStatusSet = new Set(redirectStatus) +const { kConstruct } = __nccwpck_require__(8261) +const { urlEquals, getFieldValues } = __nccwpck_require__(1488) +const { kEnumerableProperty, isDisturbed } = __nccwpck_require__(2550) +const { webidl } = __nccwpck_require__(909) +const { cloneResponse, fromInnerResponse, getResponseState } = __nccwpck_require__(4545) +const { Request, fromInnerRequest, getRequestState } = __nccwpck_require__(4517) +const { fetching } = __nccwpck_require__(5288) +const { urlIsHttpHttpsScheme, readAllBytes } = __nccwpck_require__(3106) +const { createDeferredPromise } = __nccwpck_require__(3022) /** - * @see https://fetch.spec.whatwg.org/#block-bad-port + * @see https://w3c.github.io/ServiceWorker/#dfn-cache-batch-operation + * @typedef {Object} CacheBatchOperation + * @property {'delete' | 'put'} type + * @property {any} request + * @property {any} response + * @property {import('../../../types/cache').CacheQueryOptions} options */ -const badPorts = /** @type {const} */ ([ - '1', '7', '9', '11', '13', '15', '17', '19', '20', '21', '22', '23', '25', '37', '42', '43', '53', '69', '77', '79', - '87', '95', '101', '102', '103', '104', '109', '110', '111', '113', '115', '117', '119', '123', '135', '137', - '139', '143', '161', '179', '389', '427', '465', '512', '513', '514', '515', '526', '530', '531', '532', - '540', '548', '554', '556', '563', '587', '601', '636', '989', '990', '993', '995', '1719', '1720', '1723', - '2049', '3659', '4045', '4190', '5060', '5061', '6000', '6566', '6665', '6666', '6667', '6668', '6669', '6679', - '6697', '10080' -]) -const badPortsSet = new Set(badPorts) /** - * @see https://w3c.github.io/webappsec-referrer-policy/#referrer-policy-header + * @see https://w3c.github.io/ServiceWorker/#dfn-request-response-list + * @typedef {[any, any][]} requestResponseList */ -const referrerPolicyTokens = /** @type {const} */ ([ - 'no-referrer', - 'no-referrer-when-downgrade', - 'same-origin', - 'origin', - 'strict-origin', - 'origin-when-cross-origin', - 'strict-origin-when-cross-origin', - 'unsafe-url' -]) -/** - * @see https://w3c.github.io/webappsec-referrer-policy/#referrer-policies - */ -const referrerPolicy = /** @type {const} */ ([ - '', - ...referrerPolicyTokens -]) -const referrerPolicyTokensSet = new Set(referrerPolicyTokens) - -const requestRedirect = /** @type {const} */ (['follow', 'manual', 'error']) - -const safeMethods = /** @type {const} */ (['GET', 'HEAD', 'OPTIONS', 'TRACE']) -const safeMethodsSet = new Set(safeMethods) - -const requestMode = /** @type {const} */ (['navigate', 'same-origin', 'no-cors', 'cors']) - -const requestCredentials = /** @type {const} */ (['omit', 'same-origin', 'include']) - -const requestCache = /** @type {const} */ ([ - 'default', - 'no-store', - 'reload', - 'no-cache', - 'force-cache', - 'only-if-cached' -]) - -/** - * @see https://fetch.spec.whatwg.org/#request-body-header-name - */ -const requestBodyHeader = /** @type {const} */ ([ - 'content-encoding', - 'content-language', - 'content-location', - 'content-type', - // See https://github.com/nodejs/undici/issues/2021 - // 'Content-Length' is a forbidden header name, which is typically - // removed in the Headers implementation. However, undici doesn't - // filter out headers, so we add it here. - 'content-length' -]) +class Cache { + /** + * @see https://w3c.github.io/ServiceWorker/#dfn-relevant-request-response-list + * @type {requestResponseList} + */ + #relevantRequestResponseList -/** - * @see https://fetch.spec.whatwg.org/#enumdef-requestduplex - */ -const requestDuplex = /** @type {const} */ ([ - 'half' -]) + constructor () { + if (arguments[0] !== kConstruct) { + webidl.illegalConstructor() + } -/** - * @see http://fetch.spec.whatwg.org/#forbidden-method - */ -const forbiddenMethods = /** @type {const} */ (['CONNECT', 'TRACE', 'TRACK']) -const forbiddenMethodsSet = new Set(forbiddenMethods) + webidl.util.markAsUncloneable(this) + this.#relevantRequestResponseList = arguments[1] + } -const subresource = /** @type {const} */ ([ - 'audio', - 'audioworklet', - 'font', - 'image', - 'manifest', - 'paintworklet', - 'script', - 'style', - 'track', - 'video', - 'xslt', - '' -]) -const subresourceSet = new Set(subresource) + async match (request, options = {}) { + webidl.brandCheck(this, Cache) -module.exports = { - subresource, - forbiddenMethods, - requestBodyHeader, - referrerPolicy, - requestRedirect, - requestMode, - requestCredentials, - requestCache, - redirectStatus, - corsSafeListedMethods, - nullBodyStatus, - safeMethods, - badPorts, - requestDuplex, - subresourceSet, - badPortsSet, - redirectStatusSet, - corsSafeListedMethodsSet, - safeMethodsSet, - forbiddenMethodsSet, - referrerPolicyTokens: referrerPolicyTokensSet -} + const prefix = 'Cache.match' + webidl.argumentLengthCheck(arguments, 1, prefix) + request = webidl.converters.RequestInfo(request) + options = webidl.converters.CacheQueryOptions(options, prefix, 'options') -/***/ }), + const p = this.#internalMatchAll(request, options, 1) -/***/ 9425: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + if (p.length === 0) { + return + } -"use strict"; + return p[0] + } + async matchAll (request = undefined, options = {}) { + webidl.brandCheck(this, Cache) -const assert = __nccwpck_require__(4589) -const { forgivingBase64, collectASequenceOfCodePoints, collectASequenceOfCodePointsFast, isomorphicDecode, removeASCIIWhitespace, removeChars } = __nccwpck_require__(3883) + const prefix = 'Cache.matchAll' + if (request !== undefined) request = webidl.converters.RequestInfo(request) + options = webidl.converters.CacheQueryOptions(options, prefix, 'options') -const encoder = new TextEncoder() + return this.#internalMatchAll(request, options) + } -/** - * @see https://mimesniff.spec.whatwg.org/#http-token-code-point - */ -const HTTP_TOKEN_CODEPOINTS = /^[-!#$%&'*+.^_|~A-Za-z0-9]+$/u -const HTTP_WHITESPACE_REGEX = /[\u000A\u000D\u0009\u0020]/u // eslint-disable-line + async add (request) { + webidl.brandCheck(this, Cache) -/** - * @see https://mimesniff.spec.whatwg.org/#http-quoted-string-token-code-point - */ -const HTTP_QUOTED_STRING_TOKENS = /^[\u0009\u0020-\u007E\u0080-\u00FF]+$/u // eslint-disable-line + const prefix = 'Cache.add' + webidl.argumentLengthCheck(arguments, 1, prefix) -// https://fetch.spec.whatwg.org/#data-url-processor -/** @param {URL} dataURL */ -function dataURLProcessor (dataURL) { - // 1. Assert: dataURL’s scheme is "data". - assert(dataURL.protocol === 'data:') + request = webidl.converters.RequestInfo(request) - // 2. Let input be the result of running the URL - // serializer on dataURL with exclude fragment - // set to true. - let input = URLSerializer(dataURL, true) + // 1. + const requests = [request] - // 3. Remove the leading "data:" string from input. - input = input.slice(5) + // 2. + const responseArrayPromise = this.addAll(requests) - // 4. Let position point at the start of input. - const position = { position: 0 } + // 3. + return await responseArrayPromise + } - // 5. Let mimeType be the result of collecting a - // sequence of code points that are not equal - // to U+002C (,), given position. - let mimeType = collectASequenceOfCodePointsFast( - ',', - input, - position - ) + async addAll (requests) { + webidl.brandCheck(this, Cache) - // 6. Strip leading and trailing ASCII whitespace - // from mimeType. - // Undici implementation note: we need to store the - // length because if the mimetype has spaces removed, - // the wrong amount will be sliced from the input in - // step #9 - const mimeTypeLength = mimeType.length - mimeType = removeASCIIWhitespace(mimeType, true, true) + const prefix = 'Cache.addAll' + webidl.argumentLengthCheck(arguments, 1, prefix) - // 7. If position is past the end of input, then - // return failure - if (position.position >= input.length) { - return 'failure' - } + // 1. + const responsePromises = [] - // 8. Advance position by 1. - position.position++ + // 2. + const requestList = [] - // 9. Let encodedBody be the remainder of input. - const encodedBody = input.slice(mimeTypeLength + 1) + // 3. + for (let request of requests) { + if (request === undefined) { + throw webidl.errors.conversionFailed({ + prefix, + argument: 'Argument 1', + types: ['undefined is not allowed'] + }) + } - // 10. Let body be the percent-decoding of encodedBody. - let body = stringPercentDecode(encodedBody) + request = webidl.converters.RequestInfo(request) - // 11. If mimeType ends with U+003B (;), followed by - // zero or more U+0020 SPACE, followed by an ASCII - // case-insensitive match for "base64", then: - if (/;(?:\u0020*)base64$/ui.test(mimeType)) { - // 1. Let stringBody be the isomorphic decode of body. - const stringBody = isomorphicDecode(body) + if (typeof request === 'string') { + continue + } - // 2. Set body to the forgiving-base64 decode of - // stringBody. - body = forgivingBase64(stringBody) + // 3.1 + const r = getRequestState(request) - // 3. If body is failure, then return failure. - if (body === 'failure') { - return 'failure' + // 3.2 + if (!urlIsHttpHttpsScheme(r.url) || r.method !== 'GET') { + throw webidl.errors.exception({ + header: prefix, + message: 'Expected http/s scheme when method is not GET.' + }) + } } - // 4. Remove the last 6 code points from mimeType. - mimeType = mimeType.slice(0, -6) - - // 5. Remove trailing U+0020 SPACE code points from mimeType, - // if any. - mimeType = mimeType.replace(/(\u0020+)$/u, '') - - // 6. Remove the last U+003B (;) code point from mimeType. - mimeType = mimeType.slice(0, -1) - } + // 4. + /** @type {ReturnType[]} */ + const fetchControllers = [] - // 12. If mimeType starts with U+003B (;), then prepend - // "text/plain" to mimeType. - if (mimeType.startsWith(';')) { - mimeType = 'text/plain' + mimeType - } + // 5. + for (const request of requests) { + // 5.1 + const r = getRequestState(new Request(request)) - // 13. Let mimeTypeRecord be the result of parsing - // mimeType. - let mimeTypeRecord = parseMIMEType(mimeType) + // 5.2 + if (!urlIsHttpHttpsScheme(r.url)) { + throw webidl.errors.exception({ + header: prefix, + message: 'Expected http/s scheme.' + }) + } - // 14. If mimeTypeRecord is failure, then set - // mimeTypeRecord to text/plain;charset=US-ASCII. - if (mimeTypeRecord === 'failure') { - mimeTypeRecord = parseMIMEType('text/plain;charset=US-ASCII') - } + // 5.4 + r.initiator = 'fetch' + r.destination = 'subresource' - // 15. Return a new data: URL struct whose MIME - // type is mimeTypeRecord and body is body. - // https://fetch.spec.whatwg.org/#data-url-struct - return { mimeType: mimeTypeRecord, body } -} + // 5.5 + requestList.push(r) -// https://url.spec.whatwg.org/#concept-url-serializer -/** - * @param {URL} url - * @param {boolean} excludeFragment - */ -function URLSerializer (url, excludeFragment = false) { - if (!excludeFragment) { - return url.href - } + // 5.6 + const responsePromise = createDeferredPromise() - const href = url.href - const hashLength = url.hash.length + // 5.7 + fetchControllers.push(fetching({ + request: r, + processResponse (response) { + // 1. + if (response.type === 'error' || response.status === 206 || response.status < 200 || response.status > 299) { + responsePromise.reject(webidl.errors.exception({ + header: 'Cache.addAll', + message: 'Received an invalid status code or the request failed.' + })) + } else if (response.headersList.contains('vary')) { // 2. + // 2.1 + const fieldValues = getFieldValues(response.headersList.get('vary')) - const serialized = hashLength === 0 ? href : href.substring(0, href.length - hashLength) + // 2.2 + for (const fieldValue of fieldValues) { + // 2.2.1 + if (fieldValue === '*') { + responsePromise.reject(webidl.errors.exception({ + header: 'Cache.addAll', + message: 'invalid vary field value' + })) - if (!hashLength && href.endsWith('#')) { - return serialized.slice(0, -1) - } + for (const controller of fetchControllers) { + controller.abort() + } - return serialized -} + return + } + } + } + }, + processResponseEndOfBody (response) { + // 1. + if (response.aborted) { + responsePromise.reject(new DOMException('aborted', 'AbortError')) + return + } -// https://url.spec.whatwg.org/#string-percent-decode -/** @param {string} input */ -function stringPercentDecode (input) { - // 1. Let bytes be the UTF-8 encoding of input. - const bytes = encoder.encode(input) + // 2. + responsePromise.resolve(response) + } + })) - // 2. Return the percent-decoding of bytes. - return percentDecode(bytes) -} + // 5.8 + responsePromises.push(responsePromise.promise) + } -/** - * @param {number} byte - */ -function isHexCharByte (byte) { - // 0-9 A-F a-f - return (byte >= 0x30 && byte <= 0x39) || (byte >= 0x41 && byte <= 0x46) || (byte >= 0x61 && byte <= 0x66) -} + // 6. + const p = Promise.all(responsePromises) -/** - * @param {number} byte - */ -function hexByteToNumber (byte) { - return ( - // 0-9 - byte >= 0x30 && byte <= 0x39 - ? (byte - 48) - // Convert to uppercase - // ((byte & 0xDF) - 65) + 10 - : ((byte & 0xDF) - 55) - ) -} + // 7. + const responses = await p -// https://url.spec.whatwg.org/#percent-decode -/** @param {Uint8Array} input */ -function percentDecode (input) { - const length = input.length - // 1. Let output be an empty byte sequence. - /** @type {Uint8Array} */ - const output = new Uint8Array(length) - let j = 0 - let i = 0 - // 2. For each byte byte in input: - while (i < length) { - const byte = input[i] + // 7.1 + const operations = [] - // 1. If byte is not 0x25 (%), then append byte to output. - if (byte !== 0x25) { - output[j++] = byte + // 7.2 + let index = 0 - // 2. Otherwise, if byte is 0x25 (%) and the next two bytes - // after byte in input are not in the ranges - // 0x30 (0) to 0x39 (9), 0x41 (A) to 0x46 (F), - // and 0x61 (a) to 0x66 (f), all inclusive, append byte - // to output. - } else if ( - byte === 0x25 && - !(isHexCharByte(input[i + 1]) && isHexCharByte(input[i + 2])) - ) { - output[j++] = 0x25 + // 7.3 + for (const response of responses) { + // 7.3.1 + /** @type {CacheBatchOperation} */ + const operation = { + type: 'put', // 7.3.2 + request: requestList[index], // 7.3.3 + response // 7.3.4 + } - // 3. Otherwise: - } else { - // 1. Let bytePoint be the two bytes after byte in input, - // decoded, and then interpreted as hexadecimal number. - // 2. Append a byte whose value is bytePoint to output. - output[j++] = (hexByteToNumber(input[i + 1]) << 4) | hexByteToNumber(input[i + 2]) + operations.push(operation) // 7.3.5 - // 3. Skip the next two bytes in input. - i += 2 + index++ // 7.3.6 } - ++i - } - // 3. Return output. - return length === j ? output : output.subarray(0, j) -} + // 7.5 + const cacheJobPromise = createDeferredPromise() -// https://mimesniff.spec.whatwg.org/#parse-a-mime-type -/** @param {string} input */ -function parseMIMEType (input) { - // 1. Remove any leading and trailing HTTP whitespace - // from input. - input = removeHTTPWhitespace(input, true, true) + // 7.6.1 + let errorData = null - // 2. Let position be a position variable for input, - // initially pointing at the start of input. - const position = { position: 0 } + // 7.6.2 + try { + this.#batchCacheOperations(operations) + } catch (e) { + errorData = e + } - // 3. Let type be the result of collecting a sequence - // of code points that are not U+002F (/) from - // input, given position. - const type = collectASequenceOfCodePointsFast( - '/', - input, - position - ) + // 7.6.3 + queueMicrotask(() => { + // 7.6.3.1 + if (errorData === null) { + cacheJobPromise.resolve(undefined) + } else { + // 7.6.3.2 + cacheJobPromise.reject(errorData) + } + }) - // 4. If type is the empty string or does not solely - // contain HTTP token code points, then return failure. - // https://mimesniff.spec.whatwg.org/#http-token-code-point - if (type.length === 0 || !HTTP_TOKEN_CODEPOINTS.test(type)) { - return 'failure' + // 7.7 + return cacheJobPromise.promise } - // 5. If position is past the end of input, then return - // failure - if (position.position >= input.length) { - return 'failure' - } + async put (request, response) { + webidl.brandCheck(this, Cache) - // 6. Advance position by 1. (This skips past U+002F (/).) - position.position++ + const prefix = 'Cache.put' + webidl.argumentLengthCheck(arguments, 2, prefix) - // 7. Let subtype be the result of collecting a sequence of - // code points that are not U+003B (;) from input, given - // position. - let subtype = collectASequenceOfCodePointsFast( - ';', - input, - position - ) + request = webidl.converters.RequestInfo(request) + response = webidl.converters.Response(response, prefix, 'response') - // 8. Remove any trailing HTTP whitespace from subtype. - subtype = removeHTTPWhitespace(subtype, false, true) + // 1. + let innerRequest = null - // 9. If subtype is the empty string or does not solely - // contain HTTP token code points, then return failure. - if (subtype.length === 0 || !HTTP_TOKEN_CODEPOINTS.test(subtype)) { - return 'failure' - } + // 2. + if (webidl.is.Request(request)) { + innerRequest = getRequestState(request) + } else { // 3. + innerRequest = getRequestState(new Request(request)) + } - const typeLowercase = type.toLowerCase() - const subtypeLowercase = subtype.toLowerCase() + // 4. + if (!urlIsHttpHttpsScheme(innerRequest.url) || innerRequest.method !== 'GET') { + throw webidl.errors.exception({ + header: prefix, + message: 'Expected an http/s scheme when method is not GET' + }) + } - // 10. Let mimeType be a new MIME type record whose type - // is type, in ASCII lowercase, and subtype is subtype, - // in ASCII lowercase. - // https://mimesniff.spec.whatwg.org/#mime-type - const mimeType = { - type: typeLowercase, - subtype: subtypeLowercase, - /** @type {Map} */ - parameters: new Map(), - // https://mimesniff.spec.whatwg.org/#mime-type-essence - essence: `${typeLowercase}/${subtypeLowercase}` - } - - // 11. While position is not past the end of input: - while (position.position < input.length) { - // 1. Advance position by 1. (This skips past U+003B (;).) - position.position++ - - // 2. Collect a sequence of code points that are HTTP - // whitespace from input given position. - collectASequenceOfCodePoints( - // https://fetch.spec.whatwg.org/#http-whitespace - char => HTTP_WHITESPACE_REGEX.test(char), - input, - position - ) + // 5. + const innerResponse = getResponseState(response) - // 3. Let parameterName be the result of collecting a - // sequence of code points that are not U+003B (;) - // or U+003D (=) from input, given position. - let parameterName = collectASequenceOfCodePoints( - (char) => char !== ';' && char !== '=', - input, - position - ) + // 6. + if (innerResponse.status === 206) { + throw webidl.errors.exception({ + header: prefix, + message: 'Got 206 status' + }) + } - // 4. Set parameterName to parameterName, in ASCII - // lowercase. - parameterName = parameterName.toLowerCase() + // 7. + if (innerResponse.headersList.contains('vary')) { + // 7.1. + const fieldValues = getFieldValues(innerResponse.headersList.get('vary')) - // 5. If position is not past the end of input, then: - if (position.position < input.length) { - // 1. If the code point at position within input is - // U+003B (;), then continue. - if (input[position.position] === ';') { - continue + // 7.2. + for (const fieldValue of fieldValues) { + // 7.2.1 + if (fieldValue === '*') { + throw webidl.errors.exception({ + header: prefix, + message: 'Got * vary field value' + }) + } } - - // 2. Advance position by 1. (This skips past U+003D (=).) - position.position++ } - // 6. If position is past the end of input, then break. - if (position.position >= input.length) { - break + // 8. + if (innerResponse.body && (isDisturbed(innerResponse.body.stream) || innerResponse.body.stream.locked)) { + throw webidl.errors.exception({ + header: prefix, + message: 'Response body is locked or disturbed' + }) } - // 7. Let parameterValue be null. - let parameterValue = null + // 9. + const clonedResponse = cloneResponse(innerResponse) - // 8. If the code point at position within input is - // U+0022 ("), then: - if (input[position.position] === '"') { - // 1. Set parameterValue to the result of collecting - // an HTTP quoted string from input, given position - // and the extract-value flag. - parameterValue = collectAnHTTPQuotedString(input, position, true) + // 10. + const bodyReadPromise = createDeferredPromise() - // 2. Collect a sequence of code points that are not - // U+003B (;) from input, given position. - collectASequenceOfCodePointsFast( - ';', - input, - position - ) + // 11. + if (innerResponse.body != null) { + // 11.1 + const stream = innerResponse.body.stream - // 9. Otherwise: + // 11.2 + const reader = stream.getReader() + + // 11.3 + readAllBytes(reader, bodyReadPromise.resolve, bodyReadPromise.reject) } else { - // 1. Set parameterValue to the result of collecting - // a sequence of code points that are not U+003B (;) - // from input, given position. - parameterValue = collectASequenceOfCodePointsFast( - ';', - input, - position - ) + bodyReadPromise.resolve(undefined) + } - // 2. Remove any trailing HTTP whitespace from parameterValue. - parameterValue = removeHTTPWhitespace(parameterValue, false, true) + // 12. + /** @type {CacheBatchOperation[]} */ + const operations = [] - // 3. If parameterValue is the empty string, then continue. - if (parameterValue.length === 0) { - continue - } + // 13. + /** @type {CacheBatchOperation} */ + const operation = { + type: 'put', // 14. + request: innerRequest, // 15. + response: clonedResponse // 16. } - // 10. If all of the following are true - // - parameterName is not the empty string - // - parameterName solely contains HTTP token code points - // - parameterValue solely contains HTTP quoted-string token code points - // - mimeType’s parameters[parameterName] does not exist - // then set mimeType’s parameters[parameterName] to parameterValue. - if ( - parameterName.length !== 0 && - HTTP_TOKEN_CODEPOINTS.test(parameterName) && - (parameterValue.length === 0 || HTTP_QUOTED_STRING_TOKENS.test(parameterValue)) && - !mimeType.parameters.has(parameterName) - ) { - mimeType.parameters.set(parameterName, parameterValue) - } - } + // 17. + operations.push(operation) - // 12. Return mimeType. - return mimeType -} + // 19. + const bytes = await bodyReadPromise.promise -// https://fetch.spec.whatwg.org/#collect-an-http-quoted-string -// tests: https://fetch.spec.whatwg.org/#example-http-quoted-string -/** - * @param {string} input - * @param {{ position: number }} position - * @param {boolean} [extractValue=false] - */ -function collectAnHTTPQuotedString (input, position, extractValue = false) { - // 1. Let positionStart be position. - const positionStart = position.position + if (clonedResponse.body != null) { + clonedResponse.body.source = bytes + } - // 2. Let value be the empty string. - let value = '' + // 19.1 + const cacheJobPromise = createDeferredPromise() - // 3. Assert: the code point at position within input - // is U+0022 ("). - assert(input[position.position] === '"') + // 19.2.1 + let errorData = null - // 4. Advance position by 1. - position.position++ + // 19.2.2 + try { + this.#batchCacheOperations(operations) + } catch (e) { + errorData = e + } - // 5. While true: - while (true) { - // 1. Append the result of collecting a sequence of code points - // that are not U+0022 (") or U+005C (\) from input, given - // position, to value. - value += collectASequenceOfCodePoints( - (char) => char !== '"' && char !== '\\', - input, - position - ) + // 19.2.3 + queueMicrotask(() => { + // 19.2.3.1 + if (errorData === null) { + cacheJobPromise.resolve() + } else { // 19.2.3.2 + cacheJobPromise.reject(errorData) + } + }) - // 2. If position is past the end of input, then break. - if (position.position >= input.length) { - break - } + return cacheJobPromise.promise + } - // 3. Let quoteOrBackslash be the code point at position within - // input. - const quoteOrBackslash = input[position.position] + async delete (request, options = {}) { + webidl.brandCheck(this, Cache) - // 4. Advance position by 1. - position.position++ + const prefix = 'Cache.delete' + webidl.argumentLengthCheck(arguments, 1, prefix) - // 5. If quoteOrBackslash is U+005C (\), then: - if (quoteOrBackslash === '\\') { - // 1. If position is past the end of input, then append - // U+005C (\) to value and break. - if (position.position >= input.length) { - value += '\\' - break - } + request = webidl.converters.RequestInfo(request) + options = webidl.converters.CacheQueryOptions(options, prefix, 'options') - // 2. Append the code point at position within input to value. - value += input[position.position] + /** + * @type {Request} + */ + let r = null - // 3. Advance position by 1. - position.position++ + if (webidl.is.Request(request)) { + r = getRequestState(request) - // 6. Otherwise: + if (r.method !== 'GET' && !options.ignoreMethod) { + return false + } } else { - // 1. Assert: quoteOrBackslash is U+0022 ("). - assert(quoteOrBackslash === '"') + assert(typeof request === 'string') - // 2. Break. - break + r = getRequestState(new Request(request)) } - } - // 6. If the extract-value flag is set, then return value. - if (extractValue) { - return value - } + /** @type {CacheBatchOperation[]} */ + const operations = [] - // 7. Return the code points from positionStart to position, - // inclusive, within input. - return input.slice(positionStart, position.position) -} + /** @type {CacheBatchOperation} */ + const operation = { + type: 'delete', + request: r, + options + } -/** - * @see https://mimesniff.spec.whatwg.org/#serialize-a-mime-type - */ -function serializeAMimeType (mimeType) { - assert(mimeType !== 'failure') - const { parameters, essence } = mimeType + operations.push(operation) - // 1. Let serialization be the concatenation of mimeType’s - // type, U+002F (/), and mimeType’s subtype. - let serialization = essence + const cacheJobPromise = createDeferredPromise() - // 2. For each name → value of mimeType’s parameters: - for (let [name, value] of parameters.entries()) { - // 1. Append U+003B (;) to serialization. - serialization += ';' + let errorData = null + let requestResponses - // 2. Append name to serialization. - serialization += name + try { + requestResponses = this.#batchCacheOperations(operations) + } catch (e) { + errorData = e + } - // 3. Append U+003D (=) to serialization. - serialization += '=' + queueMicrotask(() => { + if (errorData === null) { + cacheJobPromise.resolve(!!requestResponses?.length) + } else { + cacheJobPromise.reject(errorData) + } + }) - // 4. If value does not solely contain HTTP token code - // points or value is the empty string, then: - if (!HTTP_TOKEN_CODEPOINTS.test(value)) { - // 1. Precede each occurrence of U+0022 (") or - // U+005C (\) in value with U+005C (\). - value = value.replace(/[\\"]/ug, '\\$&') + return cacheJobPromise.promise + } - // 2. Prepend U+0022 (") to value. - value = '"' + value + /** + * @see https://w3c.github.io/ServiceWorker/#dom-cache-keys + * @param {any} request + * @param {import('../../../types/cache').CacheQueryOptions} options + * @returns {Promise} + */ + async keys (request = undefined, options = {}) { + webidl.brandCheck(this, Cache) - // 3. Append U+0022 (") to value. - value += '"' + const prefix = 'Cache.keys' + + if (request !== undefined) request = webidl.converters.RequestInfo(request) + options = webidl.converters.CacheQueryOptions(options, prefix, 'options') + + // 1. + let r = null + + // 2. + if (request !== undefined) { + // 2.1 + if (webidl.is.Request(request)) { + // 2.1.1 + r = getRequestState(request) + + // 2.1.2 + if (r.method !== 'GET' && !options.ignoreMethod) { + return [] + } + } else if (typeof request === 'string') { // 2.2 + r = getRequestState(new Request(request)) + } } - // 5. Append value to serialization. - serialization += value - } + // 4. + const promise = createDeferredPromise() - // 3. Return serialization. - return serialization -} + // 5. + // 5.1 + const requests = [] -/** - * @see https://fetch.spec.whatwg.org/#http-whitespace - * @param {number} char - */ -function isHTTPWhiteSpace (char) { - // "\r\n\t " - return char === 0x00d || char === 0x00a || char === 0x009 || char === 0x020 -} + // 5.2 + if (request === undefined) { + // 5.2.1 + for (const requestResponse of this.#relevantRequestResponseList) { + // 5.2.1.1 + requests.push(requestResponse[0]) + } + } else { // 5.3 + // 5.3.1 + const requestResponses = this.#queryCache(r, options) -/** - * @see https://fetch.spec.whatwg.org/#http-whitespace - * @param {string} str - * @param {boolean} [leading=true] - * @param {boolean} [trailing=true] - */ -function removeHTTPWhitespace (str, leading = true, trailing = true) { - return removeChars(str, leading, trailing, isHTTPWhiteSpace) -} + // 5.3.2 + for (const requestResponse of requestResponses) { + // 5.3.2.1 + requests.push(requestResponse[0]) + } + } -/** - * @see https://mimesniff.spec.whatwg.org/#minimize-a-supported-mime-type - * @param {Exclude, 'failure'>} mimeType - */ -function minimizeSupportedMimeType (mimeType) { - switch (mimeType.essence) { - case 'application/ecmascript': - case 'application/javascript': - case 'application/x-ecmascript': - case 'application/x-javascript': - case 'text/ecmascript': - case 'text/javascript': - case 'text/javascript1.0': - case 'text/javascript1.1': - case 'text/javascript1.2': - case 'text/javascript1.3': - case 'text/javascript1.4': - case 'text/javascript1.5': - case 'text/jscript': - case 'text/livescript': - case 'text/x-ecmascript': - case 'text/x-javascript': - // 1. If mimeType is a JavaScript MIME type, then return "text/javascript". - return 'text/javascript' - case 'application/json': - case 'text/json': - // 2. If mimeType is a JSON MIME type, then return "application/json". - return 'application/json' - case 'image/svg+xml': - // 3. If mimeType’s essence is "image/svg+xml", then return "image/svg+xml". - return 'image/svg+xml' - case 'text/xml': - case 'application/xml': - // 4. If mimeType is an XML MIME type, then return "application/xml". - return 'application/xml' - } + // 5.4 + queueMicrotask(() => { + // 5.4.1 + const requestList = [] - // 2. If mimeType is a JSON MIME type, then return "application/json". - if (mimeType.subtype.endsWith('+json')) { - return 'application/json' - } + // 5.4.2 + for (const request of requests) { + const requestObject = fromInnerRequest( + request, + undefined, + new AbortController().signal, + 'immutable' + ) + // 5.4.2.1 + requestList.push(requestObject) + } - // 4. If mimeType is an XML MIME type, then return "application/xml". - if (mimeType.subtype.endsWith('+xml')) { - return 'application/xml' + // 5.4.3 + promise.resolve(Object.freeze(requestList)) + }) + + return promise.promise } - // 5. If mimeType is supported by the user agent, then return mimeType’s essence. - // Technically, node doesn't support any mimetypes. + /** + * @see https://w3c.github.io/ServiceWorker/#batch-cache-operations-algorithm + * @param {CacheBatchOperation[]} operations + * @returns {requestResponseList} + */ + #batchCacheOperations (operations) { + // 1. + const cache = this.#relevantRequestResponseList - // 6. Return the empty string. - return '' -} + // 2. + const backupCache = [...cache] -module.exports = { - dataURLProcessor, - URLSerializer, - stringPercentDecode, - parseMIMEType, - collectAnHTTPQuotedString, - serializeAMimeType, - removeHTTPWhitespace, - minimizeSupportedMimeType, - HTTP_TOKEN_CODEPOINTS -} + // 3. + const addedItems = [] + // 4.1 + const resultList = [] -/***/ }), + try { + // 4.2 + for (const operation of operations) { + // 4.2.1 + if (operation.type !== 'delete' && operation.type !== 'put') { + throw webidl.errors.exception({ + header: 'Cache.#batchCacheOperations', + message: 'operation type does not match "delete" or "put"' + }) + } -/***/ 9211: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // 4.2.2 + if (operation.type === 'delete' && operation.response != null) { + throw webidl.errors.exception({ + header: 'Cache.#batchCacheOperations', + message: 'delete operation should not have an associated response' + }) + } -"use strict"; + // 4.2.3 + if (this.#queryCache(operation.request, operation.options, addedItems).length) { + throw new DOMException('???', 'InvalidStateError') + } + // 4.2.4 + let requestResponses -const { bufferToLowerCasedHeaderName } = __nccwpck_require__(983) -const { HTTP_TOKEN_CODEPOINTS } = __nccwpck_require__(9425) -const { makeEntry } = __nccwpck_require__(51) -const { webidl } = __nccwpck_require__(2318) -const assert = __nccwpck_require__(4589) -const { isomorphicDecode } = __nccwpck_require__(3883) -const { utf8DecodeBytes } = __nccwpck_require__(9825) + // 4.2.5 + if (operation.type === 'delete') { + // 4.2.5.1 + requestResponses = this.#queryCache(operation.request, operation.options) -const dd = Buffer.from('--') -const decoder = new TextDecoder() + // TODO: the spec is wrong, this is needed to pass WPTs + if (requestResponses.length === 0) { + return [] + } -/** - * @param {string} chars - */ -function isAsciiString (chars) { - for (let i = 0; i < chars.length; ++i) { - if ((chars.charCodeAt(i) & ~0x7F) !== 0) { - return false - } - } - return true -} + // 4.2.5.2 + for (const requestResponse of requestResponses) { + const idx = cache.indexOf(requestResponse) + assert(idx !== -1) -/** - * @see https://andreubotella.github.io/multipart-form-data/#multipart-form-data-boundary - * @param {string} boundary - */ -function validateBoundary (boundary) { - const length = boundary.length + // 4.2.5.2.1 + cache.splice(idx, 1) + } + } else if (operation.type === 'put') { // 4.2.6 + // 4.2.6.1 + if (operation.response == null) { + throw webidl.errors.exception({ + header: 'Cache.#batchCacheOperations', + message: 'put operation should have an associated response' + }) + } - // - its length is greater or equal to 27 and lesser or equal to 70, and - if (length < 27 || length > 70) { - return false - } + // 4.2.6.2 + const r = operation.request - // - it is composed by bytes in the ranges 0x30 to 0x39, 0x41 to 0x5A, or - // 0x61 to 0x7A, inclusive (ASCII alphanumeric), or which are 0x27 ('), - // 0x2D (-) or 0x5F (_). - for (let i = 0; i < length; ++i) { - const cp = boundary.charCodeAt(i) + // 4.2.6.3 + if (!urlIsHttpHttpsScheme(r.url)) { + throw webidl.errors.exception({ + header: 'Cache.#batchCacheOperations', + message: 'expected http or https scheme' + }) + } - if (!( - (cp >= 0x30 && cp <= 0x39) || - (cp >= 0x41 && cp <= 0x5a) || - (cp >= 0x61 && cp <= 0x7a) || - cp === 0x27 || - cp === 0x2d || - cp === 0x5f - )) { - return false - } - } + // 4.2.6.4 + if (r.method !== 'GET') { + throw webidl.errors.exception({ + header: 'Cache.#batchCacheOperations', + message: 'not get method' + }) + } - return true -} + // 4.2.6.5 + if (operation.options != null) { + throw webidl.errors.exception({ + header: 'Cache.#batchCacheOperations', + message: 'options must not be defined' + }) + } -/** - * @see https://andreubotella.github.io/multipart-form-data/#multipart-form-data-parser - * @param {Buffer} input - * @param {ReturnType} mimeType - */ -function multipartFormDataParser (input, mimeType) { - // 1. Assert: mimeType’s essence is "multipart/form-data". - assert(mimeType !== 'failure' && mimeType.essence === 'multipart/form-data') + // 4.2.6.6 + requestResponses = this.#queryCache(operation.request) - const boundaryString = mimeType.parameters.get('boundary') + // 4.2.6.7 + for (const requestResponse of requestResponses) { + const idx = cache.indexOf(requestResponse) + assert(idx !== -1) - // 2. If mimeType’s parameters["boundary"] does not exist, return failure. - // Otherwise, let boundary be the result of UTF-8 decoding mimeType’s - // parameters["boundary"]. - if (boundaryString === undefined) { - throw parsingError('missing boundary in content-type header') - } + // 4.2.6.7.1 + cache.splice(idx, 1) + } - const boundary = Buffer.from(`--${boundaryString}`, 'utf8') + // 4.2.6.8 + cache.push([operation.request, operation.response]) - // 3. Let entry list be an empty entry list. - const entryList = [] + // 4.2.6.10 + addedItems.push([operation.request, operation.response]) + } - // 4. Let position be a pointer to a byte in input, initially pointing at - // the first byte. - const position = { position: 0 } + // 4.2.7 + resultList.push([operation.request, operation.response]) + } - // Note: Per RFC 2046 Section 5.1.1, we must ignore anything before the - // first boundary delimiter line (preamble). Search for the first boundary. - const firstBoundaryIndex = input.indexOf(boundary) + // 4.3 + return resultList + } catch (e) { // 5. + // 5.1 + this.#relevantRequestResponseList.length = 0 - if (firstBoundaryIndex === -1) { - throw parsingError('no boundary found in multipart body') + // 5.2 + this.#relevantRequestResponseList = backupCache + + // 5.3 + throw e + } } - // Start parsing from the first boundary, ignoring any preamble - position.position = firstBoundaryIndex + /** + * @see https://w3c.github.io/ServiceWorker/#query-cache + * @param {any} requestQuery + * @param {import('../../../types/cache').CacheQueryOptions} options + * @param {requestResponseList} targetStorage + * @returns {requestResponseList} + */ + #queryCache (requestQuery, options, targetStorage) { + /** @type {requestResponseList} */ + const resultList = [] - // 5. While true: - while (true) { - // 5.1. If position points to a sequence of bytes starting with 0x2D 0x2D - // (`--`) followed by boundary, advance position by 2 + the length of - // boundary. Otherwise, return failure. - // Note: boundary is padded with 2 dashes already, no need to add 2. - if (input.subarray(position.position, position.position + boundary.length).equals(boundary)) { - position.position += boundary.length - } else { - throw parsingError('expected a value starting with -- and the boundary') + const storage = targetStorage ?? this.#relevantRequestResponseList + + for (const requestResponse of storage) { + const [cachedRequest, cachedResponse] = requestResponse + if (this.#requestMatchesCachedItem(requestQuery, cachedRequest, cachedResponse, options)) { + resultList.push(requestResponse) + } } - // 5.2. If position points to the sequence of bytes 0x2D 0x2D 0x0D 0x0A - // (`--` followed by CR LF) followed by the end of input, return entry list. - // Note: Per RFC 2046 Section 5.1.1, we must ignore anything after the - // final boundary delimiter (epilogue). Check for -- or --CRLF and return - // regardless of what follows. - if (bufferStartsWith(input, dd, position)) { - // Found closing boundary delimiter (--), ignore any epilogue - return entryList + return resultList + } + + /** + * @see https://w3c.github.io/ServiceWorker/#request-matches-cached-item-algorithm + * @param {any} requestQuery + * @param {any} request + * @param {any | null} response + * @param {import('../../../types/cache').CacheQueryOptions | undefined} options + * @returns {boolean} + */ + #requestMatchesCachedItem (requestQuery, request, response = null, options) { + // if (options?.ignoreMethod === false && request.method === 'GET') { + // return false + // } + + const queryURL = new URL(requestQuery.url) + + const cachedURL = new URL(request.url) + + if (options?.ignoreSearch) { + cachedURL.search = '' + + queryURL.search = '' } - // 5.3. If position does not point to a sequence of bytes starting with 0x0D - // 0x0A (CR LF), return failure. - if (input[position.position] !== 0x0d || input[position.position + 1] !== 0x0a) { - throw parsingError('expected CRLF') + if (!urlEquals(queryURL, cachedURL, true)) { + return false } - // 5.4. Advance position by 2. (This skips past the newline.) - position.position += 2 + if ( + response == null || + options?.ignoreVary || + !response.headersList.contains('vary') + ) { + return true + } - // 5.5. Let name, filename and contentType be the result of parsing - // multipart/form-data headers on input and position, if the result - // is not failure. Otherwise, return failure. - const result = parseMultipartFormDataHeaders(input, position) + const fieldValues = getFieldValues(response.headersList.get('vary')) - let { name, filename, contentType, encoding } = result + for (const fieldValue of fieldValues) { + if (fieldValue === '*') { + return false + } - // 5.6. Advance position by 2. (This skips past the empty line that marks - // the end of the headers.) - position.position += 2 + const requestValue = request.headersList.get(fieldValue) + const queryValue = requestQuery.headersList.get(fieldValue) - // 5.7. Let body be the empty byte sequence. - let body + // If one has the header and the other doesn't, or one has + // a different value than the other, return false + if (requestValue !== queryValue) { + return false + } + } - // 5.8. Body loop: While position is not past the end of input: - // TODO: the steps here are completely wrong - { - const boundaryIndex = input.indexOf(boundary.subarray(2), position.position) + return true + } - if (boundaryIndex === -1) { - throw parsingError('expected boundary after body') + #internalMatchAll (request, options, maxResponses = Infinity) { + // 1. + let r = null + + // 2. + if (request !== undefined) { + if (webidl.is.Request(request)) { + // 2.1.1 + r = getRequestState(request) + + // 2.1.2 + if (r.method !== 'GET' && !options.ignoreMethod) { + return [] + } + } else if (typeof request === 'string') { + // 2.2.1 + r = getRequestState(new Request(request)) } + } - body = input.subarray(position.position, boundaryIndex - 4) + // 5. + // 5.1 + const responses = [] - position.position += body.length + // 5.2 + if (request === undefined) { + // 5.2.1 + for (const requestResponse of this.#relevantRequestResponseList) { + responses.push(requestResponse[1]) + } + } else { // 5.3 + // 5.3.1 + const requestResponses = this.#queryCache(r, options) - // Note: position must be advanced by the body's length before being - // decoded, otherwise the parsing will fail. - if (encoding === 'base64') { - body = Buffer.from(body.toString(), 'base64') + // 5.3.2 + for (const requestResponse of requestResponses) { + responses.push(requestResponse[1]) } } - // 5.9. If position does not point to a sequence of bytes starting with - // 0x0D 0x0A (CR LF), return failure. Otherwise, advance position by 2. - if (input[position.position] !== 0x0d || input[position.position + 1] !== 0x0a) { - throw parsingError('expected CRLF') - } else { - position.position += 2 - } + // 5.4 + // We don't implement CORs so we don't need to loop over the responses, yay! - // 5.10. If filename is not null: - let value + // 5.5.1 + const responseList = [] - if (filename !== null) { - // 5.10.1. If contentType is null, set contentType to "text/plain". - contentType ??= 'text/plain' + // 5.5.2 + for (const response of responses) { + // 5.5.2.1 + const responseObject = fromInnerResponse(cloneResponse(response), 'immutable') - // 5.10.2. If contentType is not an ASCII string, set contentType to the empty string. + responseList.push(responseObject) - // Note: `buffer.isAscii` can be used at zero-cost, but converting a string to a buffer is a high overhead. - // Content-Type is a relatively small string, so it is faster to use `String#charCodeAt`. - if (!isAsciiString(contentType)) { - contentType = '' + if (responseList.length >= maxResponses) { + break } - - // 5.10.3. Let value be a new File object with name filename, type contentType, and body body. - value = new File([body], filename, { type: contentType }) - } else { - // 5.11. Otherwise: - - // 5.11.1. Let value be the UTF-8 decoding without BOM of body. - value = utf8DecodeBytes(Buffer.from(body)) } - // 5.12. Assert: name is a scalar value string and value is either a scalar value string or a File object. - assert(webidl.is.USVString(name)) - assert((typeof value === 'string' && webidl.is.USVString(value)) || webidl.is.File(value)) - - // 5.13. Create an entry with name and value, and append it to entry list. - entryList.push(makeEntry(name, value, filename)) + // 6. + return Object.freeze(responseList) } } -/** - * Parses content-disposition attributes (e.g., name="value" or filename*=utf-8''encoded) - * @param {Buffer} input - * @param {{ position: number }} position - * @returns {{ name: string, value: string }} - */ -function parseContentDispositionAttribute (input, position) { - // Skip leading semicolon and whitespace - if (input[position.position] === 0x3b /* ; */) { - position.position++ - } +Object.defineProperties(Cache.prototype, { + [Symbol.toStringTag]: { + value: 'Cache', + configurable: true + }, + match: kEnumerableProperty, + matchAll: kEnumerableProperty, + add: kEnumerableProperty, + addAll: kEnumerableProperty, + put: kEnumerableProperty, + delete: kEnumerableProperty, + keys: kEnumerableProperty +}) - // Skip whitespace - collectASequenceOfBytes( - (char) => char === 0x20 || char === 0x09, - input, - position - ) +const cacheQueryOptionConverters = [ + { + key: 'ignoreSearch', + converter: webidl.converters.boolean, + defaultValue: () => false + }, + { + key: 'ignoreMethod', + converter: webidl.converters.boolean, + defaultValue: () => false + }, + { + key: 'ignoreVary', + converter: webidl.converters.boolean, + defaultValue: () => false + } +] - // Collect attribute name (token characters) - const attributeName = collectASequenceOfBytes( - (char) => isToken(char) && char !== 0x3d && char !== 0x2a, // not = or * - input, - position - ) +webidl.converters.CacheQueryOptions = webidl.dictionaryConverter(cacheQueryOptionConverters) - if (attributeName.length === 0) { - return null +webidl.converters.MultiCacheQueryOptions = webidl.dictionaryConverter([ + ...cacheQueryOptionConverters, + { + key: 'cacheName', + converter: webidl.converters.DOMString } +]) - const attrNameStr = attributeName.toString('ascii').toLowerCase() +webidl.converters.Response = webidl.interfaceConverter( + webidl.is.Response, + 'Response' +) - // Check for extended notation (attribute*) - const isExtended = input[position.position] === 0x2a /* * */ - if (isExtended) { - position.position++ // skip * - } +webidl.converters['sequence'] = webidl.sequenceConverter( + webidl.converters.RequestInfo +) - // Expect = sign - if (input[position.position] !== 0x3d /* = */) { - return null - } - position.position++ // skip = +module.exports = { + Cache +} - // Skip whitespace - collectASequenceOfBytes( - (char) => char === 0x20 || char === 0x09, - input, - position - ) - let value +/***/ }), - if (isExtended) { - // Extended attribute format: charset'language'encoded-value - const headerValue = collectASequenceOfBytes( - (char) => char !== 0x20 && char !== 0x0d && char !== 0x0a && char !== 0x3b, // not space, CRLF, or ; - input, - position - ) +/***/ 2335: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - // Check for utf-8'' prefix (case insensitive) - if ( - (headerValue[0] !== 0x75 && headerValue[0] !== 0x55) || // u or U - (headerValue[1] !== 0x74 && headerValue[1] !== 0x54) || // t or T - (headerValue[2] !== 0x66 && headerValue[2] !== 0x46) || // f or F - headerValue[3] !== 0x2d || // - - headerValue[4] !== 0x38 // 8 - ) { - throw parsingError('unknown encoding, expected utf-8\'\'') - } - // Skip utf-8'' and decode the rest - value = decodeURIComponent(decoder.decode(headerValue.subarray(7))) - } else if (input[position.position] === 0x22 /* " */) { - // Quoted string - position.position++ // skip opening quote - const quotedValue = collectASequenceOfBytes( - (char) => char !== 0x0a && char !== 0x0d && char !== 0x22, // not LF, CR, or " - input, - position - ) +const { Cache } = __nccwpck_require__(336) +const { webidl } = __nccwpck_require__(909) +const { kEnumerableProperty } = __nccwpck_require__(2550) +const { kConstruct } = __nccwpck_require__(8261) - if (input[position.position] !== 0x22) { - throw parsingError('Closing quote not found') - } - position.position++ // skip closing quote +class CacheStorage { + /** + * @see https://w3c.github.io/ServiceWorker/#dfn-relevant-name-to-cache-map + * @type {Map isToken(char) && char !== 0x3b, // not ; - input, - position - ) + constructor () { + if (arguments[0] !== kConstruct) { + webidl.illegalConstructor() + } - value = decoder.decode(tokenValue) + webidl.util.markAsUncloneable(this) } - return { name: attrNameStr, value } -} + async match (request, options = {}) { + webidl.brandCheck(this, CacheStorage) + webidl.argumentLengthCheck(arguments, 1, 'CacheStorage.match') -/** - * @see https://andreubotella.github.io/multipart-form-data/#parse-multipart-form-data-headers - * @param {Buffer} input - * @param {{ position: number }} position - */ -function parseMultipartFormDataHeaders (input, position) { - // 1. Let name, filename and contentType be null. - let name = null - let filename = null - let contentType = null - let encoding = null + request = webidl.converters.RequestInfo(request) + options = webidl.converters.MultiCacheQueryOptions(options) - // 2. While true: - while (true) { - // 2.1. If position points to a sequence of bytes starting with 0x0D 0x0A (CR LF): - if (input[position.position] === 0x0d && input[position.position + 1] === 0x0a) { - // 2.1.1. If name is null, return failure. - if (name === null) { - throw parsingError('header name is null') + // 1. + if (options.cacheName != null) { + // 1.1.1.1 + if (this.#caches.has(options.cacheName)) { + // 1.1.1.1.1 + const cacheList = this.#caches.get(options.cacheName) + const cache = new Cache(kConstruct, cacheList) + + return await cache.match(request, options) } + } else { // 2. + // 2.2 + for (const cacheList of this.#caches.values()) { + const cache = new Cache(kConstruct, cacheList) - // 2.1.2. Return name, filename and contentType. - return { name, filename, contentType, encoding } - } + // 2.2.1.2 + const response = await cache.match(request, options) - // 2.2. Let header name be the result of collecting a sequence of bytes that are - // not 0x0A (LF), 0x0D (CR) or 0x3A (:), given position. - let headerName = collectASequenceOfBytes( - (char) => char !== 0x0a && char !== 0x0d && char !== 0x3a, - input, - position - ) + if (response !== undefined) { + return response + } + } + } + } - // 2.3. Remove any HTTP tab or space bytes from the start or end of header name. - headerName = removeChars(headerName, true, true, (char) => char === 0x9 || char === 0x20) + /** + * @see https://w3c.github.io/ServiceWorker/#cache-storage-has + * @param {string} cacheName + * @returns {Promise} + */ + async has (cacheName) { + webidl.brandCheck(this, CacheStorage) - // 2.4. If header name does not match the field-name token production, return failure. - if (!HTTP_TOKEN_CODEPOINTS.test(headerName.toString())) { - throw parsingError('header name does not match the field-name token production') - } + const prefix = 'CacheStorage.has' + webidl.argumentLengthCheck(arguments, 1, prefix) - // 2.5. If the byte at position is not 0x3A (:), return failure. - if (input[position.position] !== 0x3a) { - throw parsingError('expected :') - } + cacheName = webidl.converters.DOMString(cacheName, prefix, 'cacheName') - // 2.6. Advance position by 1. - position.position++ + // 2.1.1 + // 2.2 + return this.#caches.has(cacheName) + } - // 2.7. Collect a sequence of bytes that are HTTP tab or space bytes given position. - // (Do nothing with those bytes.) - collectASequenceOfBytes( - (char) => char === 0x20 || char === 0x09, - input, - position - ) + /** + * @see https://w3c.github.io/ServiceWorker/#dom-cachestorage-open + * @param {string} cacheName + * @returns {Promise} + */ + async open (cacheName) { + webidl.brandCheck(this, CacheStorage) - // 2.8. Byte-lowercase header name and switch on the result: - switch (bufferToLowerCasedHeaderName(headerName)) { - case 'content-disposition': { - name = filename = null + const prefix = 'CacheStorage.open' + webidl.argumentLengthCheck(arguments, 1, prefix) - // Collect the disposition type (should be "form-data") - const dispositionType = collectASequenceOfBytes( - (char) => isToken(char), - input, - position - ) + cacheName = webidl.converters.DOMString(cacheName, prefix, 'cacheName') - if (dispositionType.toString('ascii').toLowerCase() !== 'form-data') { - throw parsingError('expected form-data for content-disposition header') - } + // 2.1 + if (this.#caches.has(cacheName)) { + // await caches.open('v1') !== await caches.open('v1') - // Parse attributes recursively until CRLF - while ( - position.position < input.length && - input[position.position] !== 0x0d && - input[position.position + 1] !== 0x0a - ) { - const attribute = parseContentDispositionAttribute(input, position) + // 2.1.1 + const cache = this.#caches.get(cacheName) - if (!attribute) { - break - } + // 2.1.1.1 + return new Cache(kConstruct, cache) + } - if (attribute.name === 'name') { - name = attribute.value - } else if (attribute.name === 'filename') { - filename = attribute.value - } - } + // 2.2 + const cache = [] - if (name === null) { - throw parsingError('name attribute is required in content-disposition header') - } + // 2.3 + this.#caches.set(cacheName, cache) - break - } - case 'content-type': { - // 1. Let header value be the result of collecting a sequence of bytes that are - // not 0x0A (LF) or 0x0D (CR), given position. - let headerValue = collectASequenceOfBytes( - (char) => char !== 0x0a && char !== 0x0d, - input, - position - ) + // 2.4 + return new Cache(kConstruct, cache) + } - // 2. Remove any HTTP tab or space bytes from the end of header value. - headerValue = removeChars(headerValue, false, true, (char) => char === 0x9 || char === 0x20) + /** + * @see https://w3c.github.io/ServiceWorker/#cache-storage-delete + * @param {string} cacheName + * @returns {Promise} + */ + async delete (cacheName) { + webidl.brandCheck(this, CacheStorage) - // 3. Set contentType to the isomorphic decoding of header value. - contentType = isomorphicDecode(headerValue) + const prefix = 'CacheStorage.delete' + webidl.argumentLengthCheck(arguments, 1, prefix) - break - } - case 'content-transfer-encoding': { - let headerValue = collectASequenceOfBytes( - (char) => char !== 0x0a && char !== 0x0d, - input, - position - ) + cacheName = webidl.converters.DOMString(cacheName, prefix, 'cacheName') - headerValue = removeChars(headerValue, false, true, (char) => char === 0x9 || char === 0x20) + return this.#caches.delete(cacheName) + } - encoding = isomorphicDecode(headerValue) + /** + * @see https://w3c.github.io/ServiceWorker/#cache-storage-keys + * @returns {Promise} + */ + async keys () { + webidl.brandCheck(this, CacheStorage) - break - } - default: { - // Collect a sequence of bytes that are not 0x0A (LF) or 0x0D (CR), given position. - // (Do nothing with those bytes.) - collectASequenceOfBytes( - (char) => char !== 0x0a && char !== 0x0d, - input, - position - ) - } - } + // 2.1 + const keys = this.#caches.keys() - // 2.9. If position does not point to a sequence of bytes starting with 0x0D 0x0A - // (CR LF), return failure. Otherwise, advance position by 2 (past the newline). - if (input[position.position] !== 0x0d && input[position.position + 1] !== 0x0a) { - throw parsingError('expected CRLF') - } else { - position.position += 2 - } + // 2.2 + return [...keys] } } -/** - * @param {(char: number) => boolean} condition - * @param {Buffer} input - * @param {{ position: number }} position - */ -function collectASequenceOfBytes (condition, input, position) { - let start = position.position - - while (start < input.length && condition(input[start])) { - ++start - } +Object.defineProperties(CacheStorage.prototype, { + [Symbol.toStringTag]: { + value: 'CacheStorage', + configurable: true + }, + match: kEnumerableProperty, + has: kEnumerableProperty, + open: kEnumerableProperty, + delete: kEnumerableProperty, + keys: kEnumerableProperty +}) - return input.subarray(position.position, (position.position = start)) +module.exports = { + CacheStorage } -/** - * @param {Buffer} buf - * @param {boolean} leading - * @param {boolean} trailing - * @param {(charCode: number) => boolean} predicate - * @returns {Buffer} - */ -function removeChars (buf, leading, trailing, predicate) { - let lead = 0 - let trail = buf.length - 1 - if (leading) { - while (lead < buf.length && predicate(buf[lead])) lead++ - } +/***/ }), - if (trailing) { - while (trail > 0 && predicate(buf[trail])) trail-- - } +/***/ 1488: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - return lead === 0 && trail === buf.length - 1 ? buf : buf.subarray(lead, trail + 1) -} + + +const assert = __nccwpck_require__(4589) +const { URLSerializer } = __nccwpck_require__(1410) +const { isValidHeaderName } = __nccwpck_require__(3106) /** - * Checks if {@param buffer} starts with {@param start} - * @param {Buffer} buffer - * @param {Buffer} start - * @param {{ position: number }} position + * @see https://url.spec.whatwg.org/#concept-url-equals + * @param {URL} A + * @param {URL} B + * @param {boolean | undefined} excludeFragment + * @returns {boolean} */ -function bufferStartsWith (buffer, start, position) { - if (buffer.length < start.length) { - return false - } - - for (let i = 0; i < start.length; i++) { - if (start[i] !== buffer[position.position + i]) { - return false - } - } +function urlEquals (A, B, excludeFragment = false) { + const serializedA = URLSerializer(A, excludeFragment) - return true -} + const serializedB = URLSerializer(B, excludeFragment) -function parsingError (cause) { - return new TypeError('Failed to parse body as FormData.', { cause: new TypeError(cause) }) + return serializedA === serializedB } /** - * CTL = - * @param {number} char + * @see https://github.com/chromium/chromium/blob/694d20d134cb553d8d89e5500b9148012b1ba299/content/browser/cache_storage/cache_storage_cache.cc#L260-L262 + * @param {string} header */ -function isCTL (char) { - return char <= 0x1f || char === 0x7f -} +function getFieldValues (header) { + assert(header !== null) -/** - * tspecials := "(" / ")" / "<" / ">" / "@" / - * "," / ";" / ":" / "\" / <"> - * "/" / "[" / "]" / "?" / "=" - * ; Must be in quoted-string, - * ; to use within parameter values - * @param {number} char - */ -function isTSpecial (char) { - return ( - char === 0x28 || // ( - char === 0x29 || // ) - char === 0x3c || // < - char === 0x3e || // > - char === 0x40 || // @ - char === 0x2c || // , - char === 0x3b || // ; - char === 0x3a || // : - char === 0x5c || // \ - char === 0x22 || // " - char === 0x2f || // / - char === 0x5b || // [ - char === 0x5d || // ] - char === 0x3f || // ? - char === 0x3d // + - ) -} + const values = [] -/** - * token := 1* - * @param {number} char - */ -function isToken (char) { - return ( - char <= 0x7f && // ascii - char !== 0x20 && // space - char !== 0x09 && - !isCTL(char) && - !isTSpecial(char) - ) + for (let value of header.split(',')) { + value = value.trim() + + if (isValidHeaderName(value)) { + values.push(value) + } + } + + return values } module.exports = { - multipartFormDataParser, - validateBoundary + urlEquals, + getFieldValues } /***/ }), -/***/ 51: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +/***/ 5230: +/***/ ((module) => { -"use strict"; -const { iteratorMixin } = __nccwpck_require__(8913) -const { kEnumerableProperty } = __nccwpck_require__(983) -const { webidl } = __nccwpck_require__(2318) -const nodeUtil = __nccwpck_require__(7975) +// https://wicg.github.io/cookie-store/#cookie-maximum-attribute-value-size +const maxAttributeValueSize = 1024 -// https://xhr.spec.whatwg.org/#formdata -class FormData { - #state = [] +// https://wicg.github.io/cookie-store/#cookie-maximum-name-value-pair-size +const maxNameValuePairSize = 4096 - constructor (form = undefined) { - webidl.util.markAsUncloneable(this) +module.exports = { + maxAttributeValueSize, + maxNameValuePairSize +} - if (form !== undefined) { - throw webidl.errors.conversionFailed({ - prefix: 'FormData constructor', - argument: 'Argument 1', - types: ['undefined'] - }) - } - } - append (name, value, filename = undefined) { - webidl.brandCheck(this, FormData) +/***/ }), - const prefix = 'FormData.append' - webidl.argumentLengthCheck(arguments, 2, prefix) +/***/ 1051: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - name = webidl.converters.USVString(name) - if (arguments.length === 3 || webidl.is.Blob(value)) { - value = webidl.converters.Blob(value, prefix, 'value') - if (filename !== undefined) { - filename = webidl.converters.USVString(filename) - } - } else { - value = webidl.converters.USVString(value) - } +const { parseSetCookie } = __nccwpck_require__(5764) +const { stringify } = __nccwpck_require__(3091) +const { webidl } = __nccwpck_require__(909) +const { Headers } = __nccwpck_require__(7754) - // 1. Let value be value if given; otherwise blobValue. +const brandChecks = webidl.brandCheckMultiple([Headers, globalThis.Headers].filter(Boolean)) - // 2. Let entry be the result of creating an entry with - // name, value, and filename if given. - const entry = makeEntry(name, value, filename) +/** + * @typedef {Object} Cookie + * @property {string} name + * @property {string} value + * @property {Date|number} [expires] + * @property {number} [maxAge] + * @property {string} [domain] + * @property {string} [path] + * @property {boolean} [secure] + * @property {boolean} [httpOnly] + * @property {'Strict'|'Lax'|'None'} [sameSite] + * @property {string[]} [unparsed] + */ - // 3. Append entry to this’s entry list. - this.#state.push(entry) - } +/** + * @param {Headers} headers + * @returns {Record} + */ +function getCookies (headers) { + webidl.argumentLengthCheck(arguments, 1, 'getCookies') - delete (name) { - webidl.brandCheck(this, FormData) + brandChecks(headers) - const prefix = 'FormData.delete' - webidl.argumentLengthCheck(arguments, 1, prefix) + const cookie = headers.get('cookie') - name = webidl.converters.USVString(name) + /** @type {Record} */ + const out = {} - // The delete(name) method steps are to remove all entries whose name - // is name from this’s entry list. - this.#state = this.#state.filter(entry => entry.name !== name) + if (!cookie) { + return out } - get (name) { - webidl.brandCheck(this, FormData) - - const prefix = 'FormData.get' - webidl.argumentLengthCheck(arguments, 1, prefix) - - name = webidl.converters.USVString(name) - - // 1. If there is no entry whose name is name in this’s entry list, - // then return null. - const idx = this.#state.findIndex((entry) => entry.name === name) - if (idx === -1) { - return null - } + for (const piece of cookie.split(';')) { + const [name, ...value] = piece.split('=') - // 2. Return the value of the first entry whose name is name from - // this’s entry list. - return this.#state[idx].value + out[name.trim()] = value.join('=') } - getAll (name) { - webidl.brandCheck(this, FormData) + return out +} - const prefix = 'FormData.getAll' - webidl.argumentLengthCheck(arguments, 1, prefix) +/** + * @param {Headers} headers + * @param {string} name + * @param {{ path?: string, domain?: string }|undefined} attributes + * @returns {void} + */ +function deleteCookie (headers, name, attributes) { + brandChecks(headers) - name = webidl.converters.USVString(name) + const prefix = 'deleteCookie' + webidl.argumentLengthCheck(arguments, 2, prefix) - // 1. If there is no entry whose name is name in this’s entry list, - // then return the empty list. - // 2. Return the values of all entries whose name is name, in order, - // from this’s entry list. - return this.#state - .filter((entry) => entry.name === name) - .map((entry) => entry.value) - } + name = webidl.converters.DOMString(name, prefix, 'name') + attributes = webidl.converters.DeleteCookieAttributes(attributes) - has (name) { - webidl.brandCheck(this, FormData) + // Matches behavior of + // https://github.com/denoland/deno_std/blob/63827b16330b82489a04614027c33b7904e08be5/http/cookie.ts#L278 + setCookie(headers, { + name, + value: '', + expires: new Date(0), + ...attributes + }) +} - const prefix = 'FormData.has' - webidl.argumentLengthCheck(arguments, 1, prefix) +/** + * @param {Headers} headers + * @returns {Cookie[]} + */ +function getSetCookies (headers) { + webidl.argumentLengthCheck(arguments, 1, 'getSetCookies') - name = webidl.converters.USVString(name) + brandChecks(headers) - // The has(name) method steps are to return true if there is an entry - // whose name is name in this’s entry list; otherwise false. - return this.#state.findIndex((entry) => entry.name === name) !== -1 + const cookies = headers.getSetCookie() + + if (!cookies) { + return [] } - set (name, value, filename = undefined) { - webidl.brandCheck(this, FormData) + return cookies.map((pair) => parseSetCookie(pair)) +} - const prefix = 'FormData.set' - webidl.argumentLengthCheck(arguments, 2, prefix) +/** + * Parses a cookie string + * @param {string} cookie + */ +function parseCookie (cookie) { + cookie = webidl.converters.DOMString(cookie) - name = webidl.converters.USVString(name) + return parseSetCookie(cookie) +} - if (arguments.length === 3 || webidl.is.Blob(value)) { - value = webidl.converters.Blob(value, prefix, 'value') +/** + * @param {Headers} headers + * @param {Cookie} cookie + * @returns {void} + */ +function setCookie (headers, cookie) { + webidl.argumentLengthCheck(arguments, 2, 'setCookie') - if (filename !== undefined) { - filename = webidl.converters.USVString(filename) - } - } else { - value = webidl.converters.USVString(value) - } + brandChecks(headers) - // The set(name, value) and set(name, blobValue, filename) method steps - // are: + cookie = webidl.converters.Cookie(cookie) - // 1. Let value be value if given; otherwise blobValue. + const str = stringify(cookie) - // 2. Let entry be the result of creating an entry with name, value, and - // filename if given. - const entry = makeEntry(name, value, filename) + if (str) { + headers.append('set-cookie', str, true) + } +} - // 3. If there are entries in this’s entry list whose name is name, then - // replace the first such entry with entry and remove the others. - const idx = this.#state.findIndex((entry) => entry.name === name) - if (idx !== -1) { - this.#state = [ - ...this.#state.slice(0, idx), - entry, - ...this.#state.slice(idx + 1).filter((entry) => entry.name !== name) - ] - } else { - // 4. Otherwise, append entry to this’s entry list. - this.#state.push(entry) - } +webidl.converters.DeleteCookieAttributes = webidl.dictionaryConverter([ + { + converter: webidl.nullableConverter(webidl.converters.DOMString), + key: 'path', + defaultValue: () => null + }, + { + converter: webidl.nullableConverter(webidl.converters.DOMString), + key: 'domain', + defaultValue: () => null } +]) - [nodeUtil.inspect.custom] (depth, options) { - const state = this.#state.reduce((a, b) => { - if (a[b.name]) { - if (Array.isArray(a[b.name])) { - a[b.name].push(b.value) - } else { - a[b.name] = [a[b.name], b.value] - } - } else { - a[b.name] = b.value +webidl.converters.Cookie = webidl.dictionaryConverter([ + { + converter: webidl.converters.DOMString, + key: 'name' + }, + { + converter: webidl.converters.DOMString, + key: 'value' + }, + { + converter: webidl.nullableConverter((value) => { + if (typeof value === 'number') { + return webidl.converters['unsigned long long'](value) } - return a - }, { __proto__: null }) + return new Date(value) + }), + key: 'expires', + defaultValue: () => null + }, + { + converter: webidl.nullableConverter(webidl.converters['long long']), + key: 'maxAge', + defaultValue: () => null + }, + { + converter: webidl.nullableConverter(webidl.converters.DOMString), + key: 'domain', + defaultValue: () => null + }, + { + converter: webidl.nullableConverter(webidl.converters.DOMString), + key: 'path', + defaultValue: () => null + }, + { + converter: webidl.nullableConverter(webidl.converters.boolean), + key: 'secure', + defaultValue: () => null + }, + { + converter: webidl.nullableConverter(webidl.converters.boolean), + key: 'httpOnly', + defaultValue: () => null + }, + { + converter: webidl.converters.USVString, + key: 'sameSite', + allowedValues: ['Strict', 'Lax', 'None'] + }, + { + converter: webidl.sequenceConverter(webidl.converters.DOMString), + key: 'unparsed', + defaultValue: () => [] + } +]) - options.depth ??= depth - options.colors ??= true +module.exports = { + getCookies, + deleteCookie, + getSetCookies, + setCookie, + parseCookie +} - const output = nodeUtil.formatWithOptions(options, state) - // remove [Object null prototype] - return `FormData ${output.slice(output.indexOf(']') + 2)}` +/***/ }), + +/***/ 5764: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + + + +const { collectASequenceOfCodePointsFast } = __nccwpck_require__(5074) +const { maxNameValuePairSize, maxAttributeValueSize } = __nccwpck_require__(5230) +const { isCTLExcludingHtab } = __nccwpck_require__(3091) +const assert = __nccwpck_require__(4589) +const { unescape: qsUnescape } = __nccwpck_require__(1792) + +/** + * @description Parses the field-value attributes of a set-cookie header string. + * @see https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4 + * @param {string} header + * @returns {import('./index').Cookie|null} if the header is invalid, null will be returned + */ +function parseSetCookie (header) { + // 1. If the set-cookie-string contains a %x00-08 / %x0A-1F / %x7F + // character (CTL characters excluding HTAB): Abort these steps and + // ignore the set-cookie-string entirely. + if (isCTLExcludingHtab(header)) { + return null } - /** - * @param {FormData} formData - */ - static getFormDataState (formData) { - return formData.#state + let nameValuePair = '' + let unparsedAttributes = '' + let name = '' + let value = '' + + // 2. If the set-cookie-string contains a %x3B (";") character: + if (header.includes(';')) { + // 1. The name-value-pair string consists of the characters up to, + // but not including, the first %x3B (";"), and the unparsed- + // attributes consist of the remainder of the set-cookie-string + // (including the %x3B (";") in question). + const position = { position: 0 } + + nameValuePair = collectASequenceOfCodePointsFast(';', header, position) + unparsedAttributes = header.slice(position.position) + } else { + // Otherwise: + + // 1. The name-value-pair string consists of all the characters + // contained in the set-cookie-string, and the unparsed- + // attributes is the empty string. + nameValuePair = header } - /** - * @param {FormData} formData - * @param {any[]} newState - */ - static setFormDataState (formData, newState) { - formData.#state = newState + // 3. If the name-value-pair string lacks a %x3D ("=") character, then + // the name string is empty, and the value string is the value of + // name-value-pair. + if (!nameValuePair.includes('=')) { + value = nameValuePair + } else { + // Otherwise, the name string consists of the characters up to, but + // not including, the first %x3D ("=") character, and the (possibly + // empty) value string consists of the characters after the first + // %x3D ("=") character. + const position = { position: 0 } + name = collectASequenceOfCodePointsFast( + '=', + nameValuePair, + position + ) + value = nameValuePair.slice(position.position + 1) } -} -const { getFormDataState, setFormDataState } = FormData -Reflect.deleteProperty(FormData, 'getFormDataState') -Reflect.deleteProperty(FormData, 'setFormDataState') + // 4. Remove any leading or trailing WSP characters from the name + // string and the value string. + name = name.trim() + value = value.trim() -iteratorMixin('FormData', FormData, getFormDataState, 'name', 'value') + // 5. If the sum of the lengths of the name string and the value string + // is more than 4096 octets, abort these steps and ignore the set- + // cookie-string entirely. + if (name.length + value.length > maxNameValuePairSize) { + return null + } -Object.defineProperties(FormData.prototype, { - append: kEnumerableProperty, - delete: kEnumerableProperty, - get: kEnumerableProperty, - getAll: kEnumerableProperty, - has: kEnumerableProperty, - set: kEnumerableProperty, - [Symbol.toStringTag]: { - value: 'FormData', - configurable: true + // 6. The cookie-name is the name string, and the cookie-value is the + // value string. + // https://datatracker.ietf.org/doc/html/rfc6265 + // To maximize compatibility with user agents, servers that wish to + // store arbitrary data in a cookie-value SHOULD encode that data, for + // example, using Base64 [RFC4648]. + return { + name, value: qsUnescape(value), ...parseUnparsedAttributes(unparsedAttributes) } -}) +} /** - * @see https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#create-an-entry - * @param {string} name - * @param {string|Blob} value - * @param {?string} filename - * @returns + * Parses the remaining attributes of a set-cookie header + * @see https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4 + * @param {string} unparsedAttributes + * @param {Object.} [cookieAttributeList={}] */ -function makeEntry (name, value, filename) { - // 1. Set name to the result of converting name into a scalar value string. - // Note: This operation was done by the webidl converter USVString. +function parseUnparsedAttributes (unparsedAttributes, cookieAttributeList = {}) { + // 1. If the unparsed-attributes string is empty, skip the rest of + // these steps. + if (unparsedAttributes.length === 0) { + return cookieAttributeList + } - // 2. If value is a string, then set value to the result of converting - // value into a scalar value string. - if (typeof value === 'string') { - // Note: This operation was done by the webidl converter USVString. - } else { - // 3. Otherwise: + // 2. Discard the first character of the unparsed-attributes (which + // will be a %x3B (";") character). + assert(unparsedAttributes[0] === ';') + unparsedAttributes = unparsedAttributes.slice(1) - // 1. If value is not a File object, then set value to a new File object, - // representing the same bytes, whose name attribute value is "blob" - if (!webidl.is.File(value)) { - value = new File([value], 'blob', { type: value.type }) - } + let cookieAv = '' - // 2. If filename is given, then set value to a new File object, - // representing the same bytes, whose name attribute is filename. - if (filename !== undefined) { - /** @type {FilePropertyBag} */ - const options = { - type: value.type, - lastModified: value.lastModified - } + // 3. If the remaining unparsed-attributes contains a %x3B (";") + // character: + if (unparsedAttributes.includes(';')) { + // 1. Consume the characters of the unparsed-attributes up to, but + // not including, the first %x3B (";") character. + cookieAv = collectASequenceOfCodePointsFast( + ';', + unparsedAttributes, + { position: 0 } + ) + unparsedAttributes = unparsedAttributes.slice(cookieAv.length) + } else { + // Otherwise: - value = new File([value], filename, options) - } + // 1. Consume the remainder of the unparsed-attributes. + cookieAv = unparsedAttributes + unparsedAttributes = '' } - // 4. Return an entry whose name is name and whose value is value. - return { name, value } -} + // Let the cookie-av string be the characters consumed in this step. -webidl.is.FormData = webidl.util.MakeTypeAssertion(FormData) + let attributeName = '' + let attributeValue = '' -module.exports = { FormData, makeEntry, setFormDataState } + // 4. If the cookie-av string contains a %x3D ("=") character: + if (cookieAv.includes('=')) { + // 1. The (possibly empty) attribute-name string consists of the + // characters up to, but not including, the first %x3D ("=") + // character, and the (possibly empty) attribute-value string + // consists of the characters after the first %x3D ("=") + // character. + const position = { position: 0 } + attributeName = collectASequenceOfCodePointsFast( + '=', + cookieAv, + position + ) + attributeValue = cookieAv.slice(position.position + 1) + } else { + // Otherwise: -/***/ }), + // 1. The attribute-name string consists of the entire cookie-av + // string, and the attribute-value string is empty. + attributeName = cookieAv + } -/***/ 3862: -/***/ ((module) => { + // 5. Remove any leading or trailing WSP characters from the attribute- + // name string and the attribute-value string. + attributeName = attributeName.trim() + attributeValue = attributeValue.trim() -"use strict"; + // 6. If the attribute-value is longer than 1024 octets, ignore the + // cookie-av string and return to Step 1 of this algorithm. + if (attributeValue.length > maxAttributeValueSize) { + return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList) + } + // 7. Process the attribute-name and attribute-value according to the + // requirements in the following subsections. (Notice that + // attributes with unrecognized attribute-names are ignored.) + const attributeNameLowercase = attributeName.toLowerCase() -// In case of breaking changes, increase the version -// number to avoid conflicts. -const globalOrigin = Symbol.for('undici.globalOrigin.1') + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.1 + // If the attribute-name case-insensitively matches the string + // "Expires", the user agent MUST process the cookie-av as follows. + if (attributeNameLowercase === 'expires') { + // 1. Let the expiry-time be the result of parsing the attribute-value + // as cookie-date (see Section 5.1.1). + const expiryTime = new Date(attributeValue) -function getGlobalOrigin () { - return globalThis[globalOrigin] -} + // 2. If the attribute-value failed to parse as a cookie date, ignore + // the cookie-av. -function setGlobalOrigin (newOrigin) { - if (newOrigin === undefined) { - Object.defineProperty(globalThis, globalOrigin, { - value: undefined, - writable: true, - enumerable: false, - configurable: false - }) + cookieAttributeList.expires = expiryTime + } else if (attributeNameLowercase === 'max-age') { + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.2 + // If the attribute-name case-insensitively matches the string "Max- + // Age", the user agent MUST process the cookie-av as follows. - return - } + // 1. If the first character of the attribute-value is not a DIGIT or a + // "-" character, ignore the cookie-av. + const charCode = attributeValue.charCodeAt(0) - const parsedURL = new URL(newOrigin) + if ((charCode < 48 || charCode > 57) && attributeValue[0] !== '-') { + return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList) + } - if (parsedURL.protocol !== 'http:' && parsedURL.protocol !== 'https:') { - throw new TypeError(`Only http & https urls are allowed, received ${parsedURL.protocol}`) - } + // 2. If the remainder of attribute-value contains a non-DIGIT + // character, ignore the cookie-av. + if (!/^\d+$/.test(attributeValue)) { + return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList) + } - Object.defineProperty(globalThis, globalOrigin, { - value: parsedURL, - writable: true, - enumerable: false, - configurable: false - }) -} + // 3. Let delta-seconds be the attribute-value converted to an integer. + const deltaSeconds = Number(attributeValue) -module.exports = { - getGlobalOrigin, - setGlobalOrigin -} + // 4. Let cookie-age-limit be the maximum age of the cookie (which + // SHOULD be 400 days or less, see Section 4.1.2.2). + // 5. Set delta-seconds to the smaller of its present value and cookie- + // age-limit. + // deltaSeconds = Math.min(deltaSeconds * 1000, maxExpiresMs) -/***/ }), + // 6. If delta-seconds is less than or equal to zero (0), let expiry- + // time be the earliest representable date and time. Otherwise, let + // the expiry-time be the current date and time plus delta-seconds + // seconds. + // const expiryTime = deltaSeconds <= 0 ? Date.now() : Date.now() + deltaSeconds -/***/ 8447: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // 7. Append an attribute to the cookie-attribute-list with an + // attribute-name of Max-Age and an attribute-value of expiry-time. + cookieAttributeList.maxAge = deltaSeconds + } else if (attributeNameLowercase === 'domain') { + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.3 + // If the attribute-name case-insensitively matches the string "Domain", + // the user agent MUST process the cookie-av as follows. -"use strict"; -// https://github.com/Ethan-Arrowood/undici-fetch + // 1. Let cookie-domain be the attribute-value. + let cookieDomain = attributeValue + + // 2. If cookie-domain starts with %x2E ("."), let cookie-domain be + // cookie-domain without its leading %x2E ("."). + if (cookieDomain[0] === '.') { + cookieDomain = cookieDomain.slice(1) + } + // 3. Convert the cookie-domain to lower case. + cookieDomain = cookieDomain.toLowerCase() + // 4. Append an attribute to the cookie-attribute-list with an + // attribute-name of Domain and an attribute-value of cookie-domain. + cookieAttributeList.domain = cookieDomain + } else if (attributeNameLowercase === 'path') { + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.4 + // If the attribute-name case-insensitively matches the string "Path", + // the user agent MUST process the cookie-av as follows. -const { kConstruct } = __nccwpck_require__(9562) -const { kEnumerableProperty } = __nccwpck_require__(983) -const { - iteratorMixin, - isValidHeaderName, - isValidHeaderValue -} = __nccwpck_require__(8913) -const { webidl } = __nccwpck_require__(2318) -const assert = __nccwpck_require__(4589) -const util = __nccwpck_require__(7975) + // 1. If the attribute-value is empty or if the first character of the + // attribute-value is not %x2F ("/"): + let cookiePath = '' + if (attributeValue.length === 0 || attributeValue[0] !== '/') { + // 1. Let cookie-path be the default-path. + cookiePath = '/' + } else { + // Otherwise: -/** - * @param {number} code - * @returns {code is (0x0a | 0x0d | 0x09 | 0x20)} - */ -function isHTTPWhiteSpaceCharCode (code) { - return code === 0x0a || code === 0x0d || code === 0x09 || code === 0x20 -} + // 1. Let cookie-path be the attribute-value. + cookiePath = attributeValue + } -/** - * @see https://fetch.spec.whatwg.org/#concept-header-value-normalize - * @param {string} potentialValue - * @returns {string} - */ -function headerValueNormalize (potentialValue) { - // To normalize a byte sequence potentialValue, remove - // any leading and trailing HTTP whitespace bytes from - // potentialValue. - let i = 0; let j = potentialValue.length + // 2. Append an attribute to the cookie-attribute-list with an + // attribute-name of Path and an attribute-value of cookie-path. + cookieAttributeList.path = cookiePath + } else if (attributeNameLowercase === 'secure') { + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.5 + // If the attribute-name case-insensitively matches the string "Secure", + // the user agent MUST append an attribute to the cookie-attribute-list + // with an attribute-name of Secure and an empty attribute-value. - while (j > i && isHTTPWhiteSpaceCharCode(potentialValue.charCodeAt(j - 1))) --j - while (j > i && isHTTPWhiteSpaceCharCode(potentialValue.charCodeAt(i))) ++i + cookieAttributeList.secure = true + } else if (attributeNameLowercase === 'httponly') { + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.6 + // If the attribute-name case-insensitively matches the string + // "HttpOnly", the user agent MUST append an attribute to the cookie- + // attribute-list with an attribute-name of HttpOnly and an empty + // attribute-value. - return i === 0 && j === potentialValue.length ? potentialValue : potentialValue.substring(i, j) -} + cookieAttributeList.httpOnly = true + } else if (attributeNameLowercase === 'samesite') { + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.7 + // If the attribute-name case-insensitively matches the string + // "SameSite", the user agent MUST process the cookie-av as follows: -/** - * @param {Headers} headers - * @param {Array|Object} object - */ -function fill (headers, object) { - // To fill a Headers object headers with a given object object, run these steps: + // 1. Let enforcement be "Default". + let enforcement = 'Default' - // 1. If object is a sequence, then for each header in object: - // Note: webidl conversion to array has already been done. - if (Array.isArray(object)) { - for (let i = 0; i < object.length; ++i) { - const header = object[i] - // 1. If header does not contain exactly two items, then throw a TypeError. - if (header.length !== 2) { - throw webidl.errors.exception({ - header: 'Headers constructor', - message: `expected name/value pair to be length 2, found ${header.length}.` - }) - } + const attributeValueLowercase = attributeValue.toLowerCase() + // 2. If cookie-av's attribute-value is a case-insensitive match for + // "None", set enforcement to "None". + if (attributeValueLowercase.includes('none')) { + enforcement = 'None' + } - // 2. Append (header’s first item, header’s second item) to headers. - appendHeader(headers, header[0], header[1]) + // 3. If cookie-av's attribute-value is a case-insensitive match for + // "Strict", set enforcement to "Strict". + if (attributeValueLowercase.includes('strict')) { + enforcement = 'Strict' } - } else if (typeof object === 'object' && object !== null) { - // Note: null should throw - // 2. Otherwise, object is a record, then for each key → value in object, - // append (key, value) to headers - const keys = Object.keys(object) - for (let i = 0; i < keys.length; ++i) { - appendHeader(headers, keys[i], object[keys[i]]) + // 4. If cookie-av's attribute-value is a case-insensitive match for + // "Lax", set enforcement to "Lax". + if (attributeValueLowercase.includes('lax')) { + enforcement = 'Lax' } + + // 5. Append an attribute to the cookie-attribute-list with an + // attribute-name of "SameSite" and an attribute-value of + // enforcement. + cookieAttributeList.sameSite = enforcement } else { - throw webidl.errors.conversionFailed({ - prefix: 'Headers constructor', - argument: 'Argument 1', - types: ['sequence>', 'record'] - }) + cookieAttributeList.unparsed ??= [] + + cookieAttributeList.unparsed.push(`${attributeName}=${attributeValue}`) } + + // 8. Return to Step 1 of this algorithm. + return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList) } +module.exports = { + parseSetCookie, + parseUnparsedAttributes +} + + +/***/ }), + +/***/ 3091: +/***/ ((module) => { + + + /** - * @see https://fetch.spec.whatwg.org/#concept-headers-append - * @param {Headers} headers - * @param {string} name * @param {string} value + * @returns {boolean} */ -function appendHeader (headers, name, value) { - // 1. Normalize value. - value = headerValueNormalize(value) +function isCTLExcludingHtab (value) { + for (let i = 0; i < value.length; ++i) { + const code = value.charCodeAt(i) - // 2. If name is not a header name or value is not a - // header value, then throw a TypeError. - if (!isValidHeaderName(name)) { - throw webidl.errors.invalidArgument({ - prefix: 'Headers.append', - value: name, - type: 'header name' - }) - } else if (!isValidHeaderValue(value)) { - throw webidl.errors.invalidArgument({ - prefix: 'Headers.append', - value, - type: 'header value' - }) + if ( + (code >= 0x00 && code <= 0x08) || + (code >= 0x0A && code <= 0x1F) || + code === 0x7F + ) { + return true + } } + return false +} - // 3. If headers’s guard is "immutable", then throw a TypeError. - // 4. Otherwise, if headers’s guard is "request" and name is a - // forbidden header name, return. - // 5. Otherwise, if headers’s guard is "request-no-cors": - // TODO - // Note: undici does not implement forbidden header names - if (getHeadersGuard(headers) === 'immutable') { - throw new TypeError('immutable') +/** + CHAR = + token = 1* + separators = "(" | ")" | "<" | ">" | "@" + | "," | ";" | ":" | "\" | <"> + | "/" | "[" | "]" | "?" | "=" + | "{" | "}" | SP | HT + * @param {string} name + */ +function validateCookieName (name) { + for (let i = 0; i < name.length; ++i) { + const code = name.charCodeAt(i) + + if ( + code < 0x21 || // exclude CTLs (0-31), SP and HT + code > 0x7E || // exclude non-ascii and DEL + code === 0x22 || // " + code === 0x28 || // ( + code === 0x29 || // ) + code === 0x3C || // < + code === 0x3E || // > + code === 0x40 || // @ + code === 0x2C || // , + code === 0x3B || // ; + code === 0x3A || // : + code === 0x5C || // \ + code === 0x2F || // / + code === 0x5B || // [ + code === 0x5D || // ] + code === 0x3F || // ? + code === 0x3D || // = + code === 0x7B || // { + code === 0x7D // } + ) { + throw new Error('Invalid cookie name') + } } +} - // 6. Otherwise, if headers’s guard is "response" and name is a - // forbidden response-header name, return. +/** + cookie-value = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE ) + cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E + ; US-ASCII characters excluding CTLs, + ; whitespace DQUOTE, comma, semicolon, + ; and backslash + * @param {string} value + */ +function validateCookieValue (value) { + let len = value.length + let i = 0 - // 7. Append (name, value) to headers’s header list. - return getHeadersList(headers).append(name, value, false) + // if the value is wrapped in DQUOTE + if (value[0] === '"') { + if (len === 1 || value[len - 1] !== '"') { + throw new Error('Invalid cookie value') + } + --len + ++i + } - // 8. If headers’s guard is "request-no-cors", then remove - // privileged no-CORS request headers from headers + while (i < len) { + const code = value.charCodeAt(i++) + + if ( + code < 0x21 || // exclude CTLs (0-31) + code > 0x7E || // non-ascii and DEL (127) + code === 0x22 || // " + code === 0x2C || // , + code === 0x3B || // ; + code === 0x5C // \ + ) { + throw new Error('Invalid cookie value') + } + } } -// https://fetch.spec.whatwg.org/#concept-header-list-sort-and-combine /** - * @param {Headers} target + * path-value = + * @param {string} path */ -function headersListSortAndCombine (target) { - const headersList = getHeadersList(target) +function validateCookiePath (path) { + for (let i = 0; i < path.length; ++i) { + const code = path.charCodeAt(i) - if (!headersList) { - return [] + if ( + code < 0x20 || // exclude CTLs (0-31) + code === 0x7F || // DEL + code === 0x3B // ; + ) { + throw new Error('Invalid cookie path') + } } +} - if (headersList.sortedMap) { - return headersList.sortedMap +/** + * I have no idea why these values aren't allowed to be honest, + * but Deno tests these. - Khafra + * @param {string} domain + */ +function validateCookieDomain (domain) { + if ( + domain.startsWith('-') || + domain.endsWith('.') || + domain.endsWith('-') + ) { + throw new Error('Invalid cookie domain') } +} - // 1. Let headers be an empty list of headers with the key being the name - // and value the value. - const headers = [] +const IMFDays = [ + 'Sun', 'Mon', 'Tue', 'Wed', + 'Thu', 'Fri', 'Sat' +] - // 2. Let names be the result of convert header names to a sorted-lowercase - // set with all the names of the headers in list. - const names = headersList.toSortedArray() +const IMFMonths = [ + 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', + 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' +] - const cookies = headersList.cookies +const IMFPaddedNumbers = Array(61).fill(0).map((_, i) => i.toString().padStart(2, '0')) - // fast-path - if (cookies === null || cookies.length === 1) { - // Note: The non-null assertion of value has already been done by `HeadersList#toSortedArray` - return (headersList.sortedMap = names) - } +/** + * @see https://www.rfc-editor.org/rfc/rfc7231#section-7.1.1.1 + * @param {number|Date} date + IMF-fixdate = day-name "," SP date1 SP time-of-day SP GMT + ; fixed length/zone/capitalization subset of the format + ; see Section 3.3 of [RFC5322] - // 3. For each name of names: - for (let i = 0; i < names.length; ++i) { - const { 0: name, 1: value } = names[i] - // 1. If name is `set-cookie`, then: - if (name === 'set-cookie') { - // 1. Let values be a list of all values of headers in list whose name - // is a byte-case-insensitive match for name, in order. + day-name = %x4D.6F.6E ; "Mon", case-sensitive + / %x54.75.65 ; "Tue", case-sensitive + / %x57.65.64 ; "Wed", case-sensitive + / %x54.68.75 ; "Thu", case-sensitive + / %x46.72.69 ; "Fri", case-sensitive + / %x53.61.74 ; "Sat", case-sensitive + / %x53.75.6E ; "Sun", case-sensitive + date1 = day SP month SP year + ; e.g., 02 Jun 1982 - // 2. For each value of values: - // 1. Append (name, value) to headers. - for (let j = 0; j < cookies.length; ++j) { - headers.push([name, cookies[j]]) - } - } else { - // 2. Otherwise: + day = 2DIGIT + month = %x4A.61.6E ; "Jan", case-sensitive + / %x46.65.62 ; "Feb", case-sensitive + / %x4D.61.72 ; "Mar", case-sensitive + / %x41.70.72 ; "Apr", case-sensitive + / %x4D.61.79 ; "May", case-sensitive + / %x4A.75.6E ; "Jun", case-sensitive + / %x4A.75.6C ; "Jul", case-sensitive + / %x41.75.67 ; "Aug", case-sensitive + / %x53.65.70 ; "Sep", case-sensitive + / %x4F.63.74 ; "Oct", case-sensitive + / %x4E.6F.76 ; "Nov", case-sensitive + / %x44.65.63 ; "Dec", case-sensitive + year = 4DIGIT - // 1. Let value be the result of getting name from list. + GMT = %x47.4D.54 ; "GMT", case-sensitive - // 2. Assert: value is non-null. - // Note: This operation was done by `HeadersList#toSortedArray`. + time-of-day = hour ":" minute ":" second + ; 00:00:00 - 23:59:60 (leap second) - // 3. Append (name, value) to headers. - headers.push([name, value]) - } + hour = 2DIGIT + minute = 2DIGIT + second = 2DIGIT + */ +function toIMFDate (date) { + if (typeof date === 'number') { + date = new Date(date) } - // 4. Return headers. - return (headersList.sortedMap = headers) + return `${IMFDays[date.getUTCDay()]}, ${IMFPaddedNumbers[date.getUTCDate()]} ${IMFMonths[date.getUTCMonth()]} ${date.getUTCFullYear()} ${IMFPaddedNumbers[date.getUTCHours()]}:${IMFPaddedNumbers[date.getUTCMinutes()]}:${IMFPaddedNumbers[date.getUTCSeconds()]} GMT` } -function compareHeaderName (a, b) { - return a[0] < b[0] ? -1 : 1 +/** + max-age-av = "Max-Age=" non-zero-digit *DIGIT + ; In practice, both expires-av and max-age-av + ; are limited to dates representable by the + ; user agent. + * @param {number} maxAge + */ +function validateCookieMaxAge (maxAge) { + if (maxAge < 0) { + throw new Error('Invalid cookie max-age') + } } -class HeadersList { - /** @type {[string, string][]|null} */ - cookies = null +/** + * @see https://www.rfc-editor.org/rfc/rfc6265#section-4.1.1 + * @param {import('./index').Cookie} cookie + */ +function stringify (cookie) { + if (cookie.name.length === 0) { + return null + } - sortedMap - headersMap + validateCookieName(cookie.name) + validateCookieValue(cookie.value) - constructor (init) { - if (init instanceof HeadersList) { - this.headersMap = new Map(init.headersMap) - this.sortedMap = init.sortedMap - this.cookies = init.cookies === null ? null : [...init.cookies] - } else { - this.headersMap = new Map(init) - this.sortedMap = null - } + const out = [`${cookie.name}=${cookie.value}`] + + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-cookie-prefixes-00#section-3.1 + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-cookie-prefixes-00#section-3.2 + if (cookie.name.startsWith('__Secure-')) { + cookie.secure = true } - /** - * @see https://fetch.spec.whatwg.org/#header-list-contains - * @param {string} name - * @param {boolean} isLowerCase - */ - contains (name, isLowerCase) { - // A header list list contains a header name name if list - // contains a header whose name is a byte-case-insensitive - // match for name. + if (cookie.name.startsWith('__Host-')) { + cookie.secure = true + cookie.domain = null + cookie.path = '/' + } - return this.headersMap.has(isLowerCase ? name : name.toLowerCase()) + if (cookie.secure) { + out.push('Secure') } - clear () { - this.headersMap.clear() - this.sortedMap = null - this.cookies = null + if (cookie.httpOnly) { + out.push('HttpOnly') } - /** - * @see https://fetch.spec.whatwg.org/#concept-header-list-append - * @param {string} name - * @param {string} value - * @param {boolean} isLowerCase - */ - append (name, value, isLowerCase) { - this.sortedMap = null + if (typeof cookie.maxAge === 'number') { + validateCookieMaxAge(cookie.maxAge) + out.push(`Max-Age=${cookie.maxAge}`) + } - // 1. If list contains name, then set name to the first such - // header’s name. - const lowercaseName = isLowerCase ? name : name.toLowerCase() - const exists = this.headersMap.get(lowercaseName) + if (cookie.domain) { + validateCookieDomain(cookie.domain) + out.push(`Domain=${cookie.domain}`) + } - // 2. Append (name, value) to list. - if (exists) { - const delimiter = lowercaseName === 'cookie' ? '; ' : ', ' - this.headersMap.set(lowercaseName, { - name: exists.name, - value: `${exists.value}${delimiter}${value}` - }) - } else { - this.headersMap.set(lowercaseName, { name, value }) - } + if (cookie.path) { + validateCookiePath(cookie.path) + out.push(`Path=${cookie.path}`) + } - if (lowercaseName === 'set-cookie') { - (this.cookies ??= []).push(value) - } + if (cookie.expires && cookie.expires.toString() !== 'Invalid Date') { + out.push(`Expires=${toIMFDate(cookie.expires)}`) } - /** - * @see https://fetch.spec.whatwg.org/#concept-header-list-set - * @param {string} name - * @param {string} value - * @param {boolean} isLowerCase - */ - set (name, value, isLowerCase) { - this.sortedMap = null - const lowercaseName = isLowerCase ? name : name.toLowerCase() + if (cookie.sameSite) { + out.push(`SameSite=${cookie.sameSite}`) + } - if (lowercaseName === 'set-cookie') { - this.cookies = [value] + for (const part of cookie.unparsed) { + if (!part.includes('=')) { + throw new Error('Invalid unparsed') } - // 1. If list contains name, then set the value of - // the first such header to value and remove the - // others. - // 2. Otherwise, append header (name, value) to list. - this.headersMap.set(lowercaseName, { name, value }) + const [key, ...value] = part.split('=') + + out.push(`${key.trim()}=${value.join('=')}`) } + return out.join('; ') +} + +module.exports = { + isCTLExcludingHtab, + validateCookieName, + validateCookiePath, + validateCookieValue, + toIMFDate, + stringify +} + + +/***/ }), + +/***/ 321: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + + +const { Transform } = __nccwpck_require__(7075) +const { isASCIINumber, isValidLastEventId } = __nccwpck_require__(8445) + +/** + * @type {number[]} BOM + */ +const BOM = [0xEF, 0xBB, 0xBF] +/** + * @type {10} LF + */ +const LF = 0x0A +/** + * @type {13} CR + */ +const CR = 0x0D +/** + * @type {58} COLON + */ +const COLON = 0x3A +/** + * @type {32} SPACE + */ +const SPACE = 0x20 + +/** + * @typedef {object} EventSourceStreamEvent + * @type {object} + * @property {string} [event] The event type. + * @property {string} [data] The data of the message. + * @property {string} [id] A unique ID for the event. + * @property {string} [retry] The reconnection time, in milliseconds. + */ + +/** + * @typedef eventSourceSettings + * @type {object} + * @property {string} [lastEventId] The last event ID received from the server. + * @property {string} [origin] The origin of the event source. + * @property {number} [reconnectionTime] The reconnection time, in milliseconds. + */ + +class EventSourceStream extends Transform { /** - * @see https://fetch.spec.whatwg.org/#concept-header-list-delete - * @param {string} name - * @param {boolean} isLowerCase + * @type {eventSourceSettings} */ - delete (name, isLowerCase) { - this.sortedMap = null - if (!isLowerCase) name = name.toLowerCase() - - if (name === 'set-cookie') { - this.cookies = null - } + state - this.headersMap.delete(name) - } + /** + * Leading byte-order-mark check. + * @type {boolean} + */ + checkBOM = true /** - * @see https://fetch.spec.whatwg.org/#concept-header-list-get - * @param {string} name - * @param {boolean} isLowerCase - * @returns {string | null} + * @type {boolean} */ - get (name, isLowerCase) { - // 1. If list does not contain name, then return null. - // 2. Return the values of all headers in list whose name - // is a byte-case-insensitive match for name, - // separated from each other by 0x2C 0x20, in order. - return this.headersMap.get(isLowerCase ? name : name.toLowerCase())?.value ?? null - } + crlfCheck = false - * [Symbol.iterator] () { - // use the lowercased name - for (const { 0: name, 1: { value } } of this.headersMap) { - yield [name, value] - } - } + /** + * @type {boolean} + */ + eventEndCheck = false - get entries () { - const headers = {} + /** + * @type {Buffer|null} + */ + buffer = null - if (this.headersMap.size !== 0) { - for (const { name, value } of this.headersMap.values()) { - headers[name] = value - } - } + pos = 0 - return headers + event = { + data: undefined, + event: undefined, + id: undefined, + retry: undefined } - rawValues () { - return this.headersMap.values() - } + /** + * @param {object} options + * @param {boolean} [options.readableObjectMode] + * @param {eventSourceSettings} [options.eventSourceSettings] + * @param {(chunk: any, encoding?: BufferEncoding | undefined) => boolean} [options.push] + */ + constructor (options = {}) { + // Enable object mode as EventSourceStream emits objects of shape + // EventSourceStreamEvent + options.readableObjectMode = true - get entriesList () { - const headers = [] + super(options) - if (this.headersMap.size !== 0) { - for (const { 0: lowerName, 1: { name, value } } of this.headersMap) { - if (lowerName === 'set-cookie') { - for (const cookie of this.cookies) { - headers.push([name, cookie]) - } - } else { - headers.push([name, value]) - } - } - } - - return headers - } - - // https://fetch.spec.whatwg.org/#convert-header-names-to-a-sorted-lowercase-set - toSortedArray () { - const size = this.headersMap.size - const array = new Array(size) - // In most cases, you will use the fast-path. - // fast-path: Use binary insertion sort for small arrays. - if (size <= 32) { - if (size === 0) { - // If empty, it is an empty array. To avoid the first index assignment. - return array - } - // Improve performance by unrolling loop and avoiding double-loop. - // Double-loop-less version of the binary insertion sort. - const iterator = this.headersMap[Symbol.iterator]() - const firstValue = iterator.next().value - // set [name, value] to first index. - array[0] = [firstValue[0], firstValue[1].value] - // https://fetch.spec.whatwg.org/#concept-header-list-sort-and-combine - // 3.2.2. Assert: value is non-null. - assert(firstValue[1].value !== null) - for ( - let i = 1, j = 0, right = 0, left = 0, pivot = 0, x, value; - i < size; - ++i - ) { - // get next value - value = iterator.next().value - // set [name, value] to current index. - x = array[i] = [value[0], value[1].value] - // https://fetch.spec.whatwg.org/#concept-header-list-sort-and-combine - // 3.2.2. Assert: value is non-null. - assert(x[1] !== null) - left = 0 - right = i - // binary search - while (left < right) { - // middle index - pivot = left + ((right - left) >> 1) - // compare header name - if (array[pivot][0] <= x[0]) { - left = pivot + 1 - } else { - right = pivot - } - } - if (i !== pivot) { - j = i - while (j > left) { - array[j] = array[--j] - } - array[left] = x - } - } - /* c8 ignore next 4 */ - if (!iterator.next().done) { - // This is for debugging and will never be called. - throw new TypeError('Unreachable') - } - return array - } else { - // This case would be a rare occurrence. - // slow-path: fallback - let i = 0 - for (const { 0: name, 1: { value } } of this.headersMap) { - array[i++] = [name, value] - // https://fetch.spec.whatwg.org/#concept-header-list-sort-and-combine - // 3.2.2. Assert: value is non-null. - assert(value !== null) - } - return array.sort(compareHeaderName) + this.state = options.eventSourceSettings || {} + if (options.push) { + this.push = options.push } } -} - -// https://fetch.spec.whatwg.org/#headers-class -class Headers { - #guard - /** - * @type {HeadersList} - */ - #headersList /** - * @param {HeadersInit|Symbol} [init] - * @returns + * @param {Buffer} chunk + * @param {string} _encoding + * @param {Function} callback + * @returns {void} */ - constructor (init = undefined) { - webidl.util.markAsUncloneable(this) - - if (init === kConstruct) { + _transform (chunk, _encoding, callback) { + if (chunk.length === 0) { + callback() return } - this.#headersList = new HeadersList() + // Cache the chunk in the buffer, as the data might not be complete while + // processing it + // TODO: Investigate if there is a more performant way to handle + // incoming chunks + // see: https://github.com/nodejs/undici/issues/2630 + if (this.buffer) { + this.buffer = Buffer.concat([this.buffer, chunk]) + } else { + this.buffer = chunk + } - // The new Headers(init) constructor steps are: + // Strip leading byte-order-mark if we opened the stream and started + // the processing of the incoming data + if (this.checkBOM) { + switch (this.buffer.length) { + case 1: + // Check if the first byte is the same as the first byte of the BOM + if (this.buffer[0] === BOM[0]) { + // If it is, we need to wait for more data + callback() + return + } + // Set the checkBOM flag to false as we don't need to check for the + // BOM anymore + this.checkBOM = false - // 1. Set this’s guard to "none". - this.#guard = 'none' + // The buffer only contains one byte so we need to wait for more data + callback() + return + case 2: + // Check if the first two bytes are the same as the first two bytes + // of the BOM + if ( + this.buffer[0] === BOM[0] && + this.buffer[1] === BOM[1] + ) { + // If it is, we need to wait for more data, because the third byte + // is needed to determine if it is the BOM or not + callback() + return + } - // 2. If init is given, then fill this with init. - if (init !== undefined) { - init = webidl.converters.HeadersInit(init, 'Headers constructor', 'init') - fill(this, init) + // Set the checkBOM flag to false as we don't need to check for the + // BOM anymore + this.checkBOM = false + break + case 3: + // Check if the first three bytes are the same as the first three + // bytes of the BOM + if ( + this.buffer[0] === BOM[0] && + this.buffer[1] === BOM[1] && + this.buffer[2] === BOM[2] + ) { + // If it is, we can drop the buffered data, as it is only the BOM + this.buffer = Buffer.alloc(0) + // Set the checkBOM flag to false as we don't need to check for the + // BOM anymore + this.checkBOM = false + + // Await more data + callback() + return + } + // If it is not the BOM, we can start processing the data + this.checkBOM = false + break + default: + // The buffer is longer than 3 bytes, so we can drop the BOM if it is + // present + if ( + this.buffer[0] === BOM[0] && + this.buffer[1] === BOM[1] && + this.buffer[2] === BOM[2] + ) { + // Remove the BOM from the buffer + this.buffer = this.buffer.subarray(3) + } + + // Set the checkBOM flag to false as we don't need to check for the + this.checkBOM = false + break + } } - } - // https://fetch.spec.whatwg.org/#dom-headers-append - append (name, value) { - webidl.brandCheck(this, Headers) + while (this.pos < this.buffer.length) { + // If the previous line ended with an end-of-line, we need to check + // if the next character is also an end-of-line. + if (this.eventEndCheck) { + // If the the current character is an end-of-line, then the event + // is finished and we can process it - webidl.argumentLengthCheck(arguments, 2, 'Headers.append') + // If the previous line ended with a carriage return, we need to + // check if the current character is a line feed and remove it + // from the buffer. + if (this.crlfCheck) { + // If the current character is a line feed, we can remove it + // from the buffer and reset the crlfCheck flag + if (this.buffer[this.pos] === LF) { + this.buffer = this.buffer.subarray(this.pos + 1) + this.pos = 0 + this.crlfCheck = false - const prefix = 'Headers.append' - name = webidl.converters.ByteString(name, prefix, 'name') - value = webidl.converters.ByteString(value, prefix, 'value') + // It is possible that the line feed is not the end of the + // event. We need to check if the next character is an + // end-of-line character to determine if the event is + // finished. We simply continue the loop to check the next + // character. - return appendHeader(this, name, value) - } + // As we removed the line feed from the buffer and set the + // crlfCheck flag to false, we basically don't make any + // distinction between a line feed and a carriage return. + continue + } + this.crlfCheck = false + } - // https://fetch.spec.whatwg.org/#dom-headers-delete - delete (name) { - webidl.brandCheck(this, Headers) + if (this.buffer[this.pos] === LF || this.buffer[this.pos] === CR) { + // If the current character is a carriage return, we need to + // set the crlfCheck flag to true, as we need to check if the + // next character is a line feed so we can remove it from the + // buffer + if (this.buffer[this.pos] === CR) { + this.crlfCheck = true + } - webidl.argumentLengthCheck(arguments, 1, 'Headers.delete') + this.buffer = this.buffer.subarray(this.pos + 1) + this.pos = 0 + if ( + this.event.data !== undefined || this.event.event || this.event.id !== undefined || this.event.retry) { + this.processEvent(this.event) + } + this.clearEvent() + continue + } + // If the current character is not an end-of-line, then the event + // is not finished and we have to reset the eventEndCheck flag + this.eventEndCheck = false + continue + } - const prefix = 'Headers.delete' - name = webidl.converters.ByteString(name, prefix, 'name') + // If the current character is an end-of-line, we can process the + // line + if (this.buffer[this.pos] === LF || this.buffer[this.pos] === CR) { + // If the current character is a carriage return, we need to + // set the crlfCheck flag to true, as we need to check if the + // next character is a line feed + if (this.buffer[this.pos] === CR) { + this.crlfCheck = true + } - // 1. If name is not a header name, then throw a TypeError. - if (!isValidHeaderName(name)) { - throw webidl.errors.invalidArgument({ - prefix: 'Headers.delete', - value: name, - type: 'header name' - }) - } + // In any case, we can process the line as we reached an + // end-of-line character + this.parseLine(this.buffer.subarray(0, this.pos), this.event) - // 2. If this’s guard is "immutable", then throw a TypeError. - // 3. Otherwise, if this’s guard is "request" and name is a - // forbidden header name, return. - // 4. Otherwise, if this’s guard is "request-no-cors", name - // is not a no-CORS-safelisted request-header name, and - // name is not a privileged no-CORS request-header name, - // return. - // 5. Otherwise, if this’s guard is "response" and name is - // a forbidden response-header name, return. - // Note: undici does not implement forbidden header names - if (this.#guard === 'immutable') { - throw new TypeError('immutable') - } + // Remove the processed line from the buffer + this.buffer = this.buffer.subarray(this.pos + 1) + // Reset the position as we removed the processed line from the buffer + this.pos = 0 + // A line was processed and this could be the end of the event. We need + // to check if the next line is empty to determine if the event is + // finished. + this.eventEndCheck = true + continue + } - // 6. If this’s header list does not contain name, then - // return. - if (!this.#headersList.contains(name, false)) { - return + this.pos++ } - // 7. Delete name from this’s header list. - // 8. If this’s guard is "request-no-cors", then remove - // privileged no-CORS request headers from this. - this.#headersList.delete(name, false) + callback() } - // https://fetch.spec.whatwg.org/#dom-headers-get - get (name) { - webidl.brandCheck(this, Headers) - - webidl.argumentLengthCheck(arguments, 1, 'Headers.get') - - const prefix = 'Headers.get' - name = webidl.converters.ByteString(name, prefix, 'name') - - // 1. If name is not a header name, then throw a TypeError. - if (!isValidHeaderName(name)) { - throw webidl.errors.invalidArgument({ - prefix, - value: name, - type: 'header name' - }) + /** + * @param {Buffer} line + * @param {EventSourceStreamEvent} event + */ + parseLine (line, event) { + // If the line is empty (a blank line) + // Dispatch the event, as defined below. + // This will be handled in the _transform method + if (line.length === 0) { + return } - // 2. Return the result of getting name from this’s header - // list. - return this.#headersList.get(name, false) - } + // If the line starts with a U+003A COLON character (:) + // Ignore the line. + const colonPosition = line.indexOf(COLON) + if (colonPosition === 0) { + return + } - // https://fetch.spec.whatwg.org/#dom-headers-has - has (name) { - webidl.brandCheck(this, Headers) + let field = '' + let value = '' - webidl.argumentLengthCheck(arguments, 1, 'Headers.has') + // If the line contains a U+003A COLON character (:) + if (colonPosition !== -1) { + // Collect the characters on the line before the first U+003A COLON + // character (:), and let field be that string. + // TODO: Investigate if there is a more performant way to extract the + // field + // see: https://github.com/nodejs/undici/issues/2630 + field = line.subarray(0, colonPosition).toString('utf8') - const prefix = 'Headers.has' - name = webidl.converters.ByteString(name, prefix, 'name') + // Collect the characters on the line after the first U+003A COLON + // character (:), and let value be that string. + // If value starts with a U+0020 SPACE character, remove it from value. + let valueStart = colonPosition + 1 + if (line[valueStart] === SPACE) { + ++valueStart + } + // TODO: Investigate if there is a more performant way to extract the + // value + // see: https://github.com/nodejs/undici/issues/2630 + value = line.subarray(valueStart).toString('utf8') - // 1. If name is not a header name, then throw a TypeError. - if (!isValidHeaderName(name)) { - throw webidl.errors.invalidArgument({ - prefix, - value: name, - type: 'header name' - }) + // Otherwise, the string is not empty but does not contain a U+003A COLON + // character (:) + } else { + // Process the field using the steps described below, using the whole + // line as the field name, and the empty string as the field value. + field = line.toString('utf8') + value = '' } - // 2. Return true if this’s header list contains name; - // otherwise false. - return this.#headersList.contains(name, false) + // Modify the event with the field name and value. The value is also + // decoded as UTF-8 + switch (field) { + case 'data': + if (event[field] === undefined) { + event[field] = value + } else { + event[field] += `\n${value}` + } + break + case 'retry': + if (isASCIINumber(value)) { + event[field] = value + } + break + case 'id': + if (isValidLastEventId(value)) { + event[field] = value + } + break + case 'event': + if (value.length > 0) { + event[field] = value + } + break + } } - // https://fetch.spec.whatwg.org/#dom-headers-set - set (name, value) { - webidl.brandCheck(this, Headers) - - webidl.argumentLengthCheck(arguments, 2, 'Headers.set') - - const prefix = 'Headers.set' - name = webidl.converters.ByteString(name, prefix, 'name') - value = webidl.converters.ByteString(value, prefix, 'value') + /** + * @param {EventSourceStreamEvent} event + */ + processEvent (event) { + if (event.retry && isASCIINumber(event.retry)) { + this.state.reconnectionTime = parseInt(event.retry, 10) + } - // 1. Normalize value. - value = headerValueNormalize(value) + if (event.id !== undefined && isValidLastEventId(event.id)) { + this.state.lastEventId = event.id + } - // 2. If name is not a header name or value is not a - // header value, then throw a TypeError. - if (!isValidHeaderName(name)) { - throw webidl.errors.invalidArgument({ - prefix, - value: name, - type: 'header name' - }) - } else if (!isValidHeaderValue(value)) { - throw webidl.errors.invalidArgument({ - prefix, - value, - type: 'header value' + // only dispatch event, when data is provided + if (event.data !== undefined) { + this.push({ + type: event.event || 'message', + options: { + data: event.data, + lastEventId: this.state.lastEventId, + origin: this.state.origin + } }) } + } - // 3. If this’s guard is "immutable", then throw a TypeError. - // 4. Otherwise, if this’s guard is "request" and name is a - // forbidden header name, return. - // 5. Otherwise, if this’s guard is "request-no-cors" and - // name/value is not a no-CORS-safelisted request-header, - // return. - // 6. Otherwise, if this’s guard is "response" and name is a - // forbidden response-header name, return. - // Note: undici does not implement forbidden header names - if (this.#guard === 'immutable') { - throw new TypeError('immutable') + clearEvent () { + this.event = { + data: undefined, + event: undefined, + id: undefined, + retry: undefined } - - // 7. Set (name, value) in this’s header list. - // 8. If this’s guard is "request-no-cors", then remove - // privileged no-CORS request headers from this - this.#headersList.set(name, value, false) } +} - // https://fetch.spec.whatwg.org/#dom-headers-getsetcookie - getSetCookie () { - webidl.brandCheck(this, Headers) +module.exports = { + EventSourceStream +} - // 1. If this’s header list does not contain `Set-Cookie`, then return « ». - // 2. Return the values of all headers in this’s header list whose name is - // a byte-case-insensitive match for `Set-Cookie`, in order. - const list = this.#headersList.cookies +/***/ }), - if (list) { - return [...list] - } +/***/ 436: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - return [] - } - [util.inspect.custom] (depth, options) { - options.depth ??= depth - return `Headers ${util.formatWithOptions(options, this.#headersList.entries)}` - } +const { pipeline } = __nccwpck_require__(7075) +const { fetching } = __nccwpck_require__(5288) +const { makeRequest } = __nccwpck_require__(4517) +const { webidl } = __nccwpck_require__(909) +const { EventSourceStream } = __nccwpck_require__(321) +const { parseMIMEType } = __nccwpck_require__(1410) +const { createFastMessageEvent } = __nccwpck_require__(1954) +const { isNetworkError } = __nccwpck_require__(4545) +const { kEnumerableProperty } = __nccwpck_require__(2550) +const { environmentSettingsObject } = __nccwpck_require__(3106) - static getHeadersGuard (o) { - return o.#guard - } +let experimentalWarned = false - static setHeadersGuard (o, guard) { - o.#guard = guard +/** + * A reconnection time, in milliseconds. This must initially be an implementation-defined value, + * probably in the region of a few seconds. + * + * In Comparison: + * - Chrome uses 3000ms. + * - Deno uses 5000ms. + * + * @type {3000} + */ +const defaultReconnectionTime = 3000 + +/** + * The readyState attribute represents the state of the connection. + * @typedef ReadyState + * @type {0|1|2} + * @readonly + * @see https://html.spec.whatwg.org/multipage/server-sent-events.html#dom-eventsource-readystate-dev + */ + +/** + * The connection has not yet been established, or it was closed and the user + * agent is reconnecting. + * @type {0} + */ +const CONNECTING = 0 + +/** + * The user agent has an open connection and is dispatching events as it + * receives them. + * @type {1} + */ +const OPEN = 1 + +/** + * The connection is not open, and the user agent is not trying to reconnect. + * @type {2} + */ +const CLOSED = 2 + +/** + * Requests for the element will have their mode set to "cors" and their credentials mode set to "same-origin". + * @type {'anonymous'} + */ +const ANONYMOUS = 'anonymous' + +/** + * Requests for the element will have their mode set to "cors" and their credentials mode set to "include". + * @type {'use-credentials'} + */ +const USE_CREDENTIALS = 'use-credentials' + +/** + * The EventSource interface is used to receive server-sent events. It + * connects to a server over HTTP and receives events in text/event-stream + * format without closing the connection. + * @extends {EventTarget} + * @see https://html.spec.whatwg.org/multipage/server-sent-events.html#server-sent-events + * @api public + */ +class EventSource extends EventTarget { + #events = { + open: null, + error: null, + message: null } + #url + #withCredentials = false + /** - * @param {Headers} o + * @type {ReadyState} */ - static getHeadersList (o) { - return o.#headersList - } + #readyState = CONNECTING + + #request = null + #controller = null + + #dispatcher /** - * @param {Headers} target - * @param {HeadersList} list + * @type {import('./eventsource-stream').eventSourceSettings} */ - static setHeadersList (target, list) { - target.#headersList = list - } -} - -const { getHeadersGuard, setHeadersGuard, getHeadersList, setHeadersList } = Headers -Reflect.deleteProperty(Headers, 'getHeadersGuard') -Reflect.deleteProperty(Headers, 'setHeadersGuard') -Reflect.deleteProperty(Headers, 'getHeadersList') -Reflect.deleteProperty(Headers, 'setHeadersList') + #state -iteratorMixin('Headers', Headers, headersListSortAndCombine, 0, 1) + /** + * Creates a new EventSource object. + * @param {string} url + * @param {EventSourceInit} [eventSourceInitDict={}] + * @see https://html.spec.whatwg.org/multipage/server-sent-events.html#the-eventsource-interface + */ + constructor (url, eventSourceInitDict = {}) { + // 1. Let ev be a new EventSource object. + super() -Object.defineProperties(Headers.prototype, { - append: kEnumerableProperty, - delete: kEnumerableProperty, - get: kEnumerableProperty, - has: kEnumerableProperty, - set: kEnumerableProperty, - getSetCookie: kEnumerableProperty, - [Symbol.toStringTag]: { - value: 'Headers', - configurable: true - }, - [util.inspect.custom]: { - enumerable: false - } -}) + webidl.util.markAsUncloneable(this) -webidl.converters.HeadersInit = function (V, prefix, argument) { - if (webidl.util.Type(V) === webidl.util.Types.OBJECT) { - const iterator = Reflect.get(V, Symbol.iterator) + const prefix = 'EventSource constructor' + webidl.argumentLengthCheck(arguments, 1, prefix) - // A work-around to ensure we send the properly-cased Headers when V is a Headers object. - // Read https://github.com/nodejs/undici/pull/3159#issuecomment-2075537226 before touching, please. - if (!util.types.isProxy(V) && iterator === Headers.prototype.entries) { // Headers object - try { - return getHeadersList(V).entriesList - } catch { - // fall-through - } + if (!experimentalWarned) { + experimentalWarned = true + process.emitWarning('EventSource is experimental, expect them to change at any time.', { + code: 'UNDICI-ES' + }) } - if (typeof iterator === 'function') { - return webidl.converters['sequence>'](V, prefix, argument, iterator.bind(V)) - } + url = webidl.converters.USVString(url) + eventSourceInitDict = webidl.converters.EventSourceInitDict(eventSourceInitDict, prefix, 'eventSourceInitDict') - return webidl.converters['record'](V, prefix, argument) - } + this.#dispatcher = eventSourceInitDict.node.dispatcher || eventSourceInitDict.dispatcher + this.#state = { + lastEventId: '', + reconnectionTime: eventSourceInitDict.node.reconnectionTime + } - throw webidl.errors.conversionFailed({ - prefix: 'Headers constructor', - argument: 'Argument 1', - types: ['sequence>', 'record'] - }) -} + // 2. Let settings be ev's relevant settings object. + // https://html.spec.whatwg.org/multipage/webappapis.html#environment-settings-object + const settings = environmentSettingsObject -module.exports = { - fill, - // for test. - compareHeaderName, - Headers, - HeadersList, - getHeadersGuard, - setHeadersGuard, - setHeadersList, - getHeadersList -} + let urlRecord + try { + // 3. Let urlRecord be the result of encoding-parsing a URL given url, relative to settings. + urlRecord = new URL(url, settings.settingsObject.baseUrl) + this.#state.origin = urlRecord.origin + } catch (e) { + // 4. If urlRecord is failure, then throw a "SyntaxError" DOMException. + throw new DOMException(e, 'SyntaxError') + } -/***/ }), + // 5. Set ev's url to urlRecord. + this.#url = urlRecord.href -/***/ 6377: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // 6. Let corsAttributeState be Anonymous. + let corsAttributeState = ANONYMOUS -"use strict"; -// https://github.com/Ethan-Arrowood/undici-fetch + // 7. If the value of eventSourceInitDict's withCredentials member is true, + // then set corsAttributeState to Use Credentials and set ev's + // withCredentials attribute to true. + if (eventSourceInitDict.withCredentials === true) { + corsAttributeState = USE_CREDENTIALS + this.#withCredentials = true + } + // 8. Let request be the result of creating a potential-CORS request given + // urlRecord, the empty string, and corsAttributeState. + const initRequest = { + redirect: 'follow', + keepalive: true, + // @see https://html.spec.whatwg.org/multipage/urls-and-fetching.html#cors-settings-attributes + mode: 'cors', + credentials: corsAttributeState === 'anonymous' + ? 'same-origin' + : 'omit', + referrer: 'no-referrer' + } + // 9. Set request's client to settings. + initRequest.client = environmentSettingsObject.settingsObject -const { - makeNetworkError, - makeAppropriateNetworkError, - filterResponse, - makeResponse, - fromInnerResponse, - getResponseState -} = __nccwpck_require__(9294) -const { HeadersList } = __nccwpck_require__(8447) -const { Request, cloneRequest, getRequestDispatcher, getRequestState } = __nccwpck_require__(8140) -const zlib = __nccwpck_require__(8522) -const { - makePolicyContainer, - clonePolicyContainer, - requestBadPort, - TAOCheck, - appendRequestOriginHeader, - responseLocationURL, - requestCurrentURL, - setRequestReferrerPolicyOnRedirect, - tryUpgradeRequestToAPotentiallyTrustworthyURL, - createOpaqueTimingInfo, - appendFetchMetadata, - corsCheck, - crossOriginResourcePolicyCheck, - determineRequestsReferrer, - coarsenedSharedCurrentTime, - sameOrigin, - isCancelled, - isAborted, - isErrorLike, - fullyReadBody, - readableStreamClose, - urlIsLocal, - urlIsHttpHttpsScheme, - urlHasHttpsScheme, - clampAndCoarsenConnectionTimingInfo, - simpleRangeHeaderValue, - buildContentRange, - createInflate, - extractMimeType, - hasAuthenticationEntry, - includesCredentials, - isTraversableNavigable -} = __nccwpck_require__(8913) -const assert = __nccwpck_require__(4589) -const { safelyExtractBody, extractBody } = __nccwpck_require__(2921) -const { - redirectStatusSet, - nullBodyStatus, - safeMethodsSet, - requestBodyHeader, - subresourceSet -} = __nccwpck_require__(112) -const EE = __nccwpck_require__(8474) -const { Readable, pipeline, finished, isErrored, isReadable } = __nccwpck_require__(7075) -const { addAbortListener, bufferToLowerCasedHeaderName } = __nccwpck_require__(983) -const { dataURLProcessor, serializeAMimeType, minimizeSupportedMimeType } = __nccwpck_require__(9425) -const { getGlobalDispatcher } = __nccwpck_require__(4456) -const { webidl } = __nccwpck_require__(2318) -const { STATUS_CODES } = __nccwpck_require__(7067) -const { bytesMatch } = __nccwpck_require__(8361) -const { createDeferredPromise } = __nccwpck_require__(9797) -const { isomorphicEncode } = __nccwpck_require__(3883) -const { runtimeFeatures } = __nccwpck_require__(1422) + // 10. User agents may set (`Accept`, `text/event-stream`) in request's header list. + initRequest.headersList = [['accept', { name: 'accept', value: 'text/event-stream' }]] -// Node.js v23.8.0+ and v22.15.0+ supports Zstandard -const hasZstd = runtimeFeatures.has('zstd') + // 11. Set request's cache mode to "no-store". + initRequest.cache = 'no-store' -const GET_OR_HEAD = ['GET', 'HEAD'] + // 12. Set request's initiator type to "other". + initRequest.initiator = 'other' -const defaultUserAgent = typeof __UNDICI_IS_NODE__ !== 'undefined' || typeof esbuildDetection !== 'undefined' - ? 'node' - : 'undici' + initRequest.urlList = [new URL(this.#url)] -/** @type {import('buffer').resolveObjectURL} */ -let resolveObjectURL + // 13. Set ev's request to request. + this.#request = makeRequest(initRequest) -class Fetch extends EE { - constructor (dispatcher) { - super() + this.#connect() + } - this.dispatcher = dispatcher - this.connection = null - this.dump = false - this.state = 'ongoing' + /** + * Returns the state of this EventSource object's connection. It can have the + * values described below. + * @returns {ReadyState} + * @readonly + */ + get readyState () { + return this.#readyState } - terminate (reason) { - if (this.state !== 'ongoing') { - return - } + /** + * Returns the URL providing the event stream. + * @readonly + * @returns {string} + */ + get url () { + return this.#url + } - this.state = 'terminated' - this.connection?.destroy(reason) - this.emit('terminated', reason) + /** + * Returns a boolean indicating whether the EventSource object was + * instantiated with CORS credentials set (true), or not (false, the default). + */ + get withCredentials () { + return this.#withCredentials } - // https://fetch.spec.whatwg.org/#fetch-controller-abort - abort (error) { - if (this.state !== 'ongoing') { - return - } + #connect () { + if (this.#readyState === CLOSED) return - // 1. Set controller’s state to "aborted". - this.state = 'aborted' + this.#readyState = CONNECTING - // 2. Let fallbackError be an "AbortError" DOMException. - // 3. Set error to fallbackError if it is not given. - if (!error) { - error = new DOMException('The operation was aborted.', 'AbortError') + const fetchParams = { + request: this.#request, + dispatcher: this.#dispatcher } - // 4. Let serializedError be StructuredSerialize(error). - // If that threw an exception, catch it, and let - // serializedError be StructuredSerialize(fallbackError). + // 14. Let processEventSourceEndOfBody given response res be the following step: if res is not a network error, then reestablish the connection. + const processEventSourceEndOfBody = (response) => { + if (!isNetworkError(response)) { + return this.#reconnect() + } + } - // 5. Set controller’s serialized abort reason to serializedError. - this.serializedAbortReason = error + // 15. Fetch request, with processResponseEndOfBody set to processEventSourceEndOfBody... + fetchParams.processResponseEndOfBody = processEventSourceEndOfBody - this.connection?.destroy(error) - this.emit('terminated', error) - } -} + // and processResponse set to the following steps given response res: + fetchParams.processResponse = (response) => { + // 1. If res is an aborted network error, then fail the connection. -function handleFetchDone (response) { - finalizeAndReportTiming(response, 'fetch') -} + if (isNetworkError(response)) { + // 1. When a user agent is to fail the connection, the user agent + // must queue a task which, if the readyState attribute is set to a + // value other than CLOSED, sets the readyState attribute to CLOSED + // and fires an event named error at the EventSource object. Once the + // user agent has failed the connection, it does not attempt to + // reconnect. + if (response.aborted) { + this.close() + this.dispatchEvent(new Event('error')) + return + // 2. Otherwise, if res is a network error, then reestablish the + // connection, unless the user agent knows that to be futile, in + // which case the user agent may fail the connection. + } else { + this.#reconnect() + return + } + } -// https://fetch.spec.whatwg.org/#fetch-method -function fetch (input, init = undefined) { - webidl.argumentLengthCheck(arguments, 1, 'globalThis.fetch') + // 3. Otherwise, if res's status is not 200, or if res's `Content-Type` + // is not `text/event-stream`, then fail the connection. + const contentType = response.headersList.get('content-type', true) + const mimeType = contentType !== null ? parseMIMEType(contentType) : 'failure' + const contentTypeValid = mimeType !== 'failure' && mimeType.essence === 'text/event-stream' + if ( + response.status !== 200 || + contentTypeValid === false + ) { + this.close() + this.dispatchEvent(new Event('error')) + return + } - // 1. Let p be a new promise. - let p = createDeferredPromise() + // 4. Otherwise, announce the connection and interpret res's body + // line by line. - // 2. Let requestObject be the result of invoking the initial value of - // Request as constructor with input and init as arguments. If this throws - // an exception, reject p with it and return p. - let requestObject + // When a user agent is to announce the connection, the user agent + // must queue a task which, if the readyState attribute is set to a + // value other than CLOSED, sets the readyState attribute to OPEN + // and fires an event named open at the EventSource object. + // @see https://html.spec.whatwg.org/multipage/server-sent-events.html#sse-processing-model + this.#readyState = OPEN + this.dispatchEvent(new Event('open')) - try { - requestObject = new Request(input, init) - } catch (e) { - p.reject(e) - return p.promise - } + // If redirected to a different origin, set the origin to the new origin. + this.#state.origin = response.urlList[response.urlList.length - 1].origin - // 3. Let request be requestObject’s request. - const request = getRequestState(requestObject) + const eventSourceStream = new EventSourceStream({ + eventSourceSettings: this.#state, + push: (event) => { + this.dispatchEvent(createFastMessageEvent( + event.type, + event.options + )) + } + }) - // 4. If requestObject’s signal’s aborted flag is set, then: - if (requestObject.signal.aborted) { - // 1. Abort the fetch() call with p, request, null, and - // requestObject’s signal’s abort reason. - abortFetch(p, request, null, requestObject.signal.reason) + pipeline(response.body.stream, + eventSourceStream, + (error) => { + if ( + error?.aborted === false + ) { + this.close() + this.dispatchEvent(new Event('error')) + } + }) + } - // 2. Return p. - return p.promise + this.#controller = fetching(fetchParams) } - // 5. Let globalObject be request’s client’s global object. - const globalObject = request.client.globalObject + /** + * @see https://html.spec.whatwg.org/multipage/server-sent-events.html#sse-processing-model + * @returns {void} + */ + #reconnect () { + // When a user agent is to reestablish the connection, the user agent must + // run the following steps. These steps are run in parallel, not as part of + // a task. (The tasks that it queues, of course, are run like normal tasks + // and not themselves in parallel.) - // 6. If globalObject is a ServiceWorkerGlobalScope object, then set - // request’s service-workers mode to "none". - if (globalObject?.constructor?.name === 'ServiceWorkerGlobalScope') { - request.serviceWorkers = 'none' - } + // 1. Queue a task to run the following steps: - // 7. Let responseObject be null. - let responseObject = null + // 1. If the readyState attribute is set to CLOSED, abort the task. + if (this.#readyState === CLOSED) return - // 8. Let relevantRealm be this’s relevant Realm. + // 2. Set the readyState attribute to CONNECTING. + this.#readyState = CONNECTING - // 9. Let locallyAborted be false. - let locallyAborted = false + // 3. Fire an event named error at the EventSource object. + this.dispatchEvent(new Event('error')) - // 10. Let controller be null. - let controller = null + // 2. Wait a delay equal to the reconnection time of the event source. + setTimeout(() => { + // 5. Queue a task to run the following steps: - // 11. Add the following abort steps to requestObject’s signal: - addAbortListener( - requestObject.signal, - () => { - // 1. Set locallyAborted to true. - locallyAborted = true + // 1. If the EventSource object's readyState attribute is not set to + // CONNECTING, then return. + if (this.#readyState !== CONNECTING) return - // 2. Assert: controller is non-null. - assert(controller != null) + // 2. Let request be the EventSource object's request. + // 3. If the EventSource object's last event ID string is not the empty + // string, then: + // 1. Let lastEventIDValue be the EventSource object's last event ID + // string, encoded as UTF-8. + // 2. Set (`Last-Event-ID`, lastEventIDValue) in request's header + // list. + if (this.#state.lastEventId.length) { + this.#request.headersList.set('last-event-id', this.#state.lastEventId, true) + } - // 3. Abort controller with requestObject’s signal’s abort reason. - controller.abort(requestObject.signal.reason) + // 4. Fetch request and process the response obtained in this fashion, if any, as described earlier in this section. + this.#connect() + }, this.#state.reconnectionTime)?.unref() + } - const realResponse = responseObject?.deref() + /** + * Closes the connection, if any, and sets the readyState attribute to + * CLOSED. + */ + close () { + webidl.brandCheck(this, EventSource) - // 4. Abort the fetch() call with p, request, responseObject, - // and requestObject’s signal’s abort reason. - abortFetch(p, request, realResponse, requestObject.signal.reason) - } - ) - - // 12. Let handleFetchDone given response response be to finalize and - // report timing with response, globalObject, and "fetch". - // see function handleFetchDone + if (this.#readyState === CLOSED) return + this.#readyState = CLOSED + this.#controller.abort() + this.#request = null + } - // 13. Set controller to the result of calling fetch given request, - // with processResponseEndOfBody set to handleFetchDone, and processResponse - // given response being these substeps: + get onopen () { + return this.#events.open + } - const processResponse = (response) => { - // 1. If locallyAborted is true, terminate these substeps. - if (locallyAborted) { - return + set onopen (fn) { + if (this.#events.open) { + this.removeEventListener('open', this.#events.open) } - // 2. If response’s aborted flag is set, then: - if (response.aborted) { - // 1. Let deserializedError be the result of deserialize a serialized - // abort reason given controller’s serialized abort reason and - // relevantRealm. - - // 2. Abort the fetch() call with p, request, responseObject, and - // deserializedError. - - abortFetch(p, request, responseObject, controller.serializedAbortReason) - return - } + const listener = webidl.converters.EventHandlerNonNull(fn) - // 3. If response is a network error, then reject p with a TypeError - // and terminate these substeps. - if (response.type === 'error') { - p.reject(new TypeError('fetch failed', { cause: response.error })) - return + if (listener !== null) { + this.addEventListener('open', listener) + this.#events.open = fn + } else { + this.#events.open = null } + } - // 4. Set responseObject to the result of creating a Response object, - // given response, "immutable", and relevantRealm. - responseObject = new WeakRef(fromInnerResponse(response, 'immutable')) - - // 5. Resolve p with responseObject. - p.resolve(responseObject.deref()) - p = null + get onmessage () { + return this.#events.message } - controller = fetching({ - request, - processResponseEndOfBody: handleFetchDone, - processResponse, - dispatcher: getRequestDispatcher(requestObject) // undici - }) + set onmessage (fn) { + if (this.#events.message) { + this.removeEventListener('message', this.#events.message) + } - // 14. Return p. - return p.promise -} + const listener = webidl.converters.EventHandlerNonNull(fn) -// https://fetch.spec.whatwg.org/#finalize-and-report-timing -function finalizeAndReportTiming (response, initiatorType = 'other') { - // 1. If response is an aborted network error, then return. - if (response.type === 'error' && response.aborted) { - return + if (listener !== null) { + this.addEventListener('message', listener) + this.#events.message = fn + } else { + this.#events.message = null + } } - // 2. If response’s URL list is null or empty, then return. - if (!response.urlList?.length) { - return + get onerror () { + return this.#events.error } - // 3. Let originalURL be response’s URL list[0]. - const originalURL = response.urlList[0] - - // 4. Let timingInfo be response’s timing info. - let timingInfo = response.timingInfo + set onerror (fn) { + if (this.#events.error) { + this.removeEventListener('error', this.#events.error) + } - // 5. Let cacheState be response’s cache state. - let cacheState = response.cacheState + const listener = webidl.converters.EventHandlerNonNull(fn) - // 6. If originalURL’s scheme is not an HTTP(S) scheme, then return. - if (!urlIsHttpHttpsScheme(originalURL)) { - return + if (listener !== null) { + this.addEventListener('error', listener) + this.#events.error = fn + } else { + this.#events.error = null + } } +} - // 7. If timingInfo is null, then return. - if (timingInfo === null) { - return +const constantsPropertyDescriptors = { + CONNECTING: { + __proto__: null, + configurable: false, + enumerable: true, + value: CONNECTING, + writable: false + }, + OPEN: { + __proto__: null, + configurable: false, + enumerable: true, + value: OPEN, + writable: false + }, + CLOSED: { + __proto__: null, + configurable: false, + enumerable: true, + value: CLOSED, + writable: false } +} - // 8. If response’s timing allow passed flag is not set, then: - if (!response.timingAllowPassed) { - // 1. Set timingInfo to a the result of creating an opaque timing info for timingInfo. - timingInfo = createOpaqueTimingInfo({ - startTime: timingInfo.startTime - }) - - // 2. Set cacheState to the empty string. - cacheState = '' - } +Object.defineProperties(EventSource, constantsPropertyDescriptors) +Object.defineProperties(EventSource.prototype, constantsPropertyDescriptors) - // 9. Set timingInfo’s end time to the coarsened shared current time - // given global’s relevant settings object’s cross-origin isolated - // capability. - // TODO: given global’s relevant settings object’s cross-origin isolated - // capability? - timingInfo.endTime = coarsenedSharedCurrentTime() +Object.defineProperties(EventSource.prototype, { + close: kEnumerableProperty, + onerror: kEnumerableProperty, + onmessage: kEnumerableProperty, + onopen: kEnumerableProperty, + readyState: kEnumerableProperty, + url: kEnumerableProperty, + withCredentials: kEnumerableProperty +}) - // 10. Set response’s timing info to timingInfo. - response.timingInfo = timingInfo +webidl.converters.EventSourceInitDict = webidl.dictionaryConverter([ + { + key: 'withCredentials', + converter: webidl.converters.boolean, + defaultValue: () => false + }, + { + key: 'dispatcher', // undici only + converter: webidl.converters.any + }, + { + key: 'node', // undici only + converter: webidl.dictionaryConverter([ + { + key: 'reconnectionTime', + converter: webidl.converters['unsigned long'], + defaultValue: () => defaultReconnectionTime + }, + { + key: 'dispatcher', + converter: webidl.converters.any + } + ]), + defaultValue: () => ({}) + } +]) - // 11. Mark resource timing for timingInfo, originalURL, initiatorType, - // global, and cacheState. - markResourceTiming( - timingInfo, - originalURL.href, - initiatorType, - globalThis, - cacheState, - '', // bodyType - response.status - ) +module.exports = { + EventSource, + defaultReconnectionTime } -// https://w3c.github.io/resource-timing/#dfn-mark-resource-timing -const markResourceTiming = performance.markResourceTiming -// https://fetch.spec.whatwg.org/#abort-fetch -function abortFetch (p, request, responseObject, error) { - // 1. Reject promise with error. - if (p) { - // We might have already resolved the promise at this stage - p.reject(error) - } +/***/ }), - // 2. If request’s body is not null and is readable, then cancel request’s - // body with error. - if (request.body?.stream != null && isReadable(request.body.stream)) { - request.body.stream.cancel(error).catch((err) => { - if (err.code === 'ERR_INVALID_STATE') { - // Node bug? - return - } - throw err - }) - } +/***/ 8445: +/***/ ((module) => { - // 3. If responseObject is null, then return. - if (responseObject == null) { - return - } - // 4. Let response be responseObject’s response. - const response = getResponseState(responseObject) - // 5. If response’s body is not null and is readable, then error response’s - // body with error. - if (response.body?.stream != null && isReadable(response.body.stream)) { - response.body.stream.cancel(error).catch((err) => { - if (err.code === 'ERR_INVALID_STATE') { - // Node bug? - return - } - throw err - }) - } +/** + * Checks if the given value is a valid LastEventId. + * @param {string} value + * @returns {boolean} + */ +function isValidLastEventId (value) { + // LastEventId should not contain U+0000 NULL + return value.indexOf('\u0000') === -1 } -// https://fetch.spec.whatwg.org/#fetching -function fetching ({ - request, - processRequestBodyChunkLength, - processRequestEndOfBody, - processResponse, - processResponseEndOfBody, - processResponseConsumeBody, - useParallelQueue = false, - dispatcher = getGlobalDispatcher() // undici -}) { - // Ensure that the dispatcher is set accordingly - assert(dispatcher) +/** + * Checks if the given value is a base 10 digit. + * @param {string} value + * @returns {boolean} + */ +function isASCIINumber (value) { + if (value.length === 0) return false + for (let i = 0; i < value.length; i++) { + if (value.charCodeAt(i) < 0x30 || value.charCodeAt(i) > 0x39) return false + } + return true +} - // 1. Let taskDestination be null. - let taskDestination = null +module.exports = { + isValidLastEventId, + isASCIINumber +} - // 2. Let crossOriginIsolatedCapability be false. - let crossOriginIsolatedCapability = false - // 3. If request’s client is non-null, then: - if (request.client != null) { - // 1. Set taskDestination to request’s client’s global object. - taskDestination = request.client.globalObject +/***/ }), - // 2. Set crossOriginIsolatedCapability to request’s client’s cross-origin - // isolated capability. - crossOriginIsolatedCapability = - request.client.crossOriginIsolatedCapability - } +/***/ 9742: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - // 4. If useParallelQueue is true, then set taskDestination to the result of - // starting a new parallel queue. - // TODO - // 5. Let timingInfo be a new fetch timing info whose start time and - // post-redirect start time are the coarsened shared current time given - // crossOriginIsolatedCapability. - const currentTime = coarsenedSharedCurrentTime(crossOriginIsolatedCapability) - const timingInfo = createOpaqueTimingInfo({ - startTime: currentTime - }) - // 6. Let fetchParams be a new fetch params whose - // request is request, - // timing info is timingInfo, - // process request body chunk length is processRequestBodyChunkLength, - // process request end-of-body is processRequestEndOfBody, - // process response is processResponse, - // process response consume body is processResponseConsumeBody, - // process response end-of-body is processResponseEndOfBody, - // task destination is taskDestination, - // and cross-origin isolated capability is crossOriginIsolatedCapability. - const fetchParams = { - controller: new Fetch(dispatcher), - request, - timingInfo, - processRequestBodyChunkLength, - processRequestEndOfBody, - processResponse, - processResponseConsumeBody, - processResponseEndOfBody, - taskDestination, - crossOriginIsolatedCapability - } +const util = __nccwpck_require__(2550) +const { + ReadableStreamFrom, + readableStreamClose, + fullyReadBody, + extractMimeType +} = __nccwpck_require__(3106) +const { FormData, setFormDataState } = __nccwpck_require__(3756) +const { webidl } = __nccwpck_require__(909) +const assert = __nccwpck_require__(4589) +const { isErrored, isDisturbed } = __nccwpck_require__(7075) +const { isUint8Array } = __nccwpck_require__(3429) +const { serializeAMimeType } = __nccwpck_require__(1410) +const { multipartFormDataParser } = __nccwpck_require__(1682) +const { createDeferredPromise } = __nccwpck_require__(3022) +const { parseJSONFromBytes } = __nccwpck_require__(5074) +const { utf8DecodeBytes } = __nccwpck_require__(6546) +const { runtimeFeatures } = __nccwpck_require__(3895) - // 7. If request’s body is a byte sequence, then set request’s body to - // request’s body as a body. - // NOTE: Since fetching is only called from fetch, body should already be - // extracted. - assert(!request.body || request.body.stream) +const random = runtimeFeatures.has('crypto') + ? (__nccwpck_require__(7598).randomInt) + : (max) => Math.floor(Math.random() * max) - // 8. If request’s window is "client", then set request’s window to request’s - // client, if request’s client’s global object is a Window object; otherwise - // "no-window". - if (request.window === 'client') { - // TODO: What if request.client is null? - request.window = - request.client?.globalObject?.constructor?.name === 'Window' - ? request.client - : 'no-window' - } +const textEncoder = new TextEncoder() +function noop () {} - // 9. If request’s origin is "client", then set request’s origin to request’s - // client’s origin. - if (request.origin === 'client') { - request.origin = request.client.origin +const streamRegistry = new FinalizationRegistry((weakRef) => { + const stream = weakRef.deref() + if (stream && !stream.locked && !isDisturbed(stream) && !isErrored(stream)) { + stream.cancel('Response object has been garbage collected').catch(noop) } +}) - // 10. If all of the following conditions are true: - // TODO +/** + * Extract a body with type from a byte sequence or BodyInit object + * + * @param {import('../../../types').BodyInit} object - The BodyInit object to extract from + * @param {boolean} [keepalive=false] - If true, indicates that the body + * @returns {[{stream: ReadableStream, source: any, length: number | null}, string | null]} - Returns a tuple containing the body and its type + * + * @see https://fetch.spec.whatwg.org/#concept-bodyinit-extract + */ +function extractBody (object, keepalive = false) { + // 1. Let stream be null. + let stream = null + let controller = null - // 11. If request’s policy container is "client", then: - if (request.policyContainer === 'client') { - // 1. If request’s client is non-null, then set request’s policy - // container to a clone of request’s client’s policy container. [HTML] - if (request.client != null) { - request.policyContainer = clonePolicyContainer( - request.client.policyContainer - ) - } else { - // 2. Otherwise, set request’s policy container to a new policy - // container. - request.policyContainer = makePolicyContainer() - } + // 2. If object is a ReadableStream object, then set stream to object. + if (webidl.is.ReadableStream(object)) { + stream = object + } else if (webidl.is.Blob(object)) { + // 3. Otherwise, if object is a Blob object, set stream to the + // result of running object’s get stream. + stream = object.stream() + } else { + // 4. Otherwise, set stream to a new ReadableStream object, and set + // up stream with byte reading support. + stream = new ReadableStream({ + pull () {}, + start (c) { + controller = c + }, + cancel () {}, + type: 'bytes' + }) } - // 12. If request’s header list does not contain `Accept`, then: - if (!request.headersList.contains('accept', true)) { - // 1. Let value be `*/*`. - const value = '*/*' + // 5. Assert: stream is a ReadableStream object. + assert(webidl.is.ReadableStream(stream)) - // 2. A user agent should set value to the first matching statement, if - // any, switching on request’s destination: - // "document" - // "frame" - // "iframe" - // `text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8` - // "image" - // `image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5` - // "style" - // `text/css,*/*;q=0.1` - // TODO + // 6. Let action be null. + let action = null - // 3. Append `Accept`/value to request’s header list. - request.headersList.append('accept', value, true) - } + // 7. Let source be null. + let source = null - // 13. If request’s header list does not contain `Accept-Language`, then - // user agents should append `Accept-Language`/an appropriate value to - // request’s header list. - if (!request.headersList.contains('accept-language', true)) { - request.headersList.append('accept-language', '*', true) - } + // 8. Let length be null. + let length = null - // 14. If request’s priority is null, then use request’s initiator and - // destination appropriately in setting request’s priority to a - // user-agent-defined object. - if (request.priority === null) { - // TODO - } + // 9. Let type be null. + let type = null - // 15. If request is a subresource request, then: - if (subresourceSet.has(request.destination)) { - // TODO - } + // 10. Switch on object: + if (typeof object === 'string') { + // Set source to the UTF-8 encoding of object. + // Note: setting source to a Uint8Array here breaks some mocking assumptions. + source = object - // 16. Run main fetch given fetchParams. - mainFetch(fetchParams, false) + // Set type to `text/plain;charset=UTF-8`. + type = 'text/plain;charset=UTF-8' + } else if (webidl.is.URLSearchParams(object)) { + // URLSearchParams - // 17. Return fetchParam's controller - return fetchParams.controller -} + // spec says to run application/x-www-form-urlencoded on body.list + // this is implemented in Node.js as apart of an URLSearchParams instance toString method + // See: https://github.com/nodejs/node/blob/e46c680bf2b211bbd52cf959ca17ee98c7f657f5/lib/internal/url.js#L490 + // and https://github.com/nodejs/node/blob/e46c680bf2b211bbd52cf959ca17ee98c7f657f5/lib/internal/url.js#L1100 -// https://fetch.spec.whatwg.org/#concept-main-fetch -async function mainFetch (fetchParams, recursive) { - try { - // 1. Let request be fetchParams’s request. - const request = fetchParams.request + // Set source to the result of running the application/x-www-form-urlencoded serializer with object’s list. + source = object.toString() - // 2. Let response be null. - let response = null + // Set type to `application/x-www-form-urlencoded;charset=UTF-8`. + type = 'application/x-www-form-urlencoded;charset=UTF-8' + } else if (webidl.is.BufferSource(object)) { + // Set source to a copy of the bytes held by object. + source = webidl.util.getCopyOfBytesHeldByBufferSource(object) + } else if (webidl.is.FormData(object)) { + const boundary = `----formdata-undici-0${`${random(1e11)}`.padStart(11, '0')}` + const prefix = `--${boundary}\r\nContent-Disposition: form-data` - // 3. If request’s local-URLs-only flag is set and request’s current URL is - // not local, then set response to a network error. - if (request.localURLsOnly && !urlIsLocal(requestCurrentURL(request))) { - response = makeNetworkError('local URLs only') - } + /*! formdata-polyfill. MIT License. Jimmy Wärting */ + const formdataEscape = (str) => + str.replace(/\n/g, '%0A').replace(/\r/g, '%0D').replace(/"/g, '%22') + const normalizeLinefeeds = (value) => value.replace(/\r?\n|\r/g, '\r\n') - // 4. Run report Content Security Policy violations for request. - // TODO + // Set action to this step: run the multipart/form-data + // encoding algorithm, with object’s entry list and UTF-8. + // - This ensures that the body is immutable and can't be changed afterwords + // - That the content-length is calculated in advance. + // - And that all parts are pre-encoded and ready to be sent. - // 5. Upgrade request to a potentially trustworthy URL, if appropriate. - tryUpgradeRequestToAPotentiallyTrustworthyURL(request) + const blobParts = [] + const rn = new Uint8Array([13, 10]) // '\r\n' + length = 0 + let hasUnknownSizeValue = false - // 6. If should request be blocked due to a bad port, should fetching request - // be blocked as mixed content, or should request be blocked by Content - // Security Policy returns blocked, then set response to a network error. - if (requestBadPort(request) === 'blocked') { - response = makeNetworkError('bad port') - } - // TODO: should fetching request be blocked as mixed content? - // TODO: should request be blocked by Content Security Policy? - - // 7. If request’s referrer policy is the empty string, then set request’s - // referrer policy to request’s policy container’s referrer policy. - if (request.referrerPolicy === '') { - request.referrerPolicy = request.policyContainer.referrerPolicy - } - - // 8. If request’s referrer is not "no-referrer", then set request’s - // referrer to the result of invoking determine request’s referrer. - if (request.referrer !== 'no-referrer') { - request.referrer = determineRequestsReferrer(request) - } - - // 9. Set request’s current URL’s scheme to "https" if all of the following - // conditions are true: - // - request’s current URL’s scheme is "http" - // - request’s current URL’s host is a domain - // - Matching request’s current URL’s host per Known HSTS Host Domain Name - // Matching results in either a superdomain match with an asserted - // includeSubDomains directive or a congruent match (with or without an - // asserted includeSubDomains directive). [HSTS] - // TODO - - // 10. If recursive is false, then run the remaining steps in parallel. - // TODO - - // 11. If response is null, then set response to the result of running - // the steps corresponding to the first matching statement: - if (response === null) { - const currentURL = requestCurrentURL(request) - if ( - // - request’s current URL’s origin is same origin with request’s origin, - // and request’s response tainting is "basic" - (sameOrigin(currentURL, request.url) && request.responseTainting === 'basic') || - // request’s current URL’s scheme is "data" - (currentURL.protocol === 'data:') || - // - request’s mode is "navigate" or "websocket" - (request.mode === 'navigate' || request.mode === 'websocket') - ) { - // 1. Set request’s response tainting to "basic". - request.responseTainting = 'basic' - - // 2. Return the result of running scheme fetch given fetchParams. - response = await schemeFetch(fetchParams) - - // request’s mode is "same-origin" - } else if (request.mode === 'same-origin') { - // 1. Return a network error. - response = makeNetworkError('request mode cannot be "same-origin"') - - // request’s mode is "no-cors" - } else if (request.mode === 'no-cors') { - // 1. If request’s redirect mode is not "follow", then return a network - // error. - if (request.redirect !== 'follow') { - response = makeNetworkError( - 'redirect mode cannot be "follow" for "no-cors" request' - ) + for (const [name, value] of object) { + if (typeof value === 'string') { + const chunk = textEncoder.encode(prefix + + `; name="${formdataEscape(normalizeLinefeeds(name))}"` + + `\r\n\r\n${normalizeLinefeeds(value)}\r\n`) + blobParts.push(chunk) + length += chunk.byteLength + } else { + const chunk = textEncoder.encode(`${prefix}; name="${formdataEscape(normalizeLinefeeds(name))}"` + + (value.name ? `; filename="${formdataEscape(value.name)}"` : '') + '\r\n' + + `Content-Type: ${ + value.type || 'application/octet-stream' + }\r\n\r\n`) + blobParts.push(chunk, value, rn) + if (typeof value.size === 'number') { + length += chunk.byteLength + value.size + rn.byteLength } else { - // 2. Set request’s response tainting to "opaque". - request.responseTainting = 'opaque' - - // 3. Return the result of running scheme fetch given fetchParams. - response = await schemeFetch(fetchParams) + hasUnknownSizeValue = true } - // request’s current URL’s scheme is not an HTTP(S) scheme - } else if (!urlIsHttpHttpsScheme(requestCurrentURL(request))) { - // Return a network error. - response = makeNetworkError('URL scheme must be a HTTP(S) scheme') - - // - request’s use-CORS-preflight flag is set - // - request’s unsafe-request flag is set and either request’s method is - // not a CORS-safelisted method or CORS-unsafe request-header names with - // request’s header list is not empty - // 1. Set request’s response tainting to "cors". - // 2. Let corsWithPreflightResponse be the result of running HTTP fetch - // given fetchParams and true. - // 3. If corsWithPreflightResponse is a network error, then clear cache - // entries using request. - // 4. Return corsWithPreflightResponse. - // TODO - - // Otherwise - } else { - // 1. Set request’s response tainting to "cors". - request.responseTainting = 'cors' - - // 2. Return the result of running HTTP fetch given fetchParams. - response = await httpFetch(fetchParams) } } - // 12. If recursive is true, then return response. - if (recursive) { - return response + // CRLF is appended to the body to function with legacy servers and match other implementations. + // https://github.com/curl/curl/blob/3434c6b46e682452973972e8313613dfa58cd690/lib/mime.c#L1029-L1030 + // https://github.com/form-data/form-data/issues/63 + const chunk = textEncoder.encode(`--${boundary}--\r\n`) + blobParts.push(chunk) + length += chunk.byteLength + if (hasUnknownSizeValue) { + length = null } - // 13. If response is not a network error and response is not a filtered - // response, then: - if (response.status !== 0 && !response.internalResponse) { - // If request’s response tainting is "cors", then: - if (request.responseTainting === 'cors') { - // 1. Let headerNames be the result of extracting header list values - // given `Access-Control-Expose-Headers` and response’s header list. - // TODO - // 2. If request’s credentials mode is not "include" and headerNames - // contains `*`, then set response’s CORS-exposed header-name list to - // all unique header names in response’s header list. - // TODO - // 3. Otherwise, if headerNames is not null or failure, then set - // response’s CORS-exposed header-name list to headerNames. - // TODO - } + // Set source to object. + source = object - // Set response to the following filtered response with response as its - // internal response, depending on request’s response tainting: - if (request.responseTainting === 'basic') { - response = filterResponse(response, 'basic') - } else if (request.responseTainting === 'cors') { - response = filterResponse(response, 'cors') - } else if (request.responseTainting === 'opaque') { - response = filterResponse(response, 'opaque') - } else { - assert(false) + action = async function * () { + for (const part of blobParts) { + if (part.stream) { + yield * part.stream() + } else { + yield part + } } } - // 14. Let internalResponse be response, if response is a network error, - // and response’s internal response otherwise. - let internalResponse = - response.status === 0 ? response : response.internalResponse - - // 15. If internalResponse’s URL list is empty, then set it to a clone of - // request’s URL list. - if (internalResponse.urlList.length === 0) { - internalResponse.urlList.push(...request.urlList) - } + // Set type to `multipart/form-data; boundary=`, + // followed by the multipart/form-data boundary string generated + // by the multipart/form-data encoding algorithm. + type = `multipart/form-data; boundary=${boundary}` + } else if (webidl.is.Blob(object)) { + // Blob - // 16. If request’s timing allow failed flag is unset, then set - // internalResponse’s timing allow passed flag. - if (!request.timingAllowFailed) { - response.timingAllowPassed = true - } + // Set source to object. + source = object - // 17. If response is not a network error and any of the following returns - // blocked - // - should internalResponse to request be blocked as mixed content - // - should internalResponse to request be blocked by Content Security Policy - // - should internalResponse to request be blocked due to its MIME type - // - should internalResponse to request be blocked due to nosniff - // TODO + // Set length to object’s size. + length = object.size - // 18. If response’s type is "opaque", internalResponse’s status is 206, - // internalResponse’s range-requested flag is set, and request’s header - // list does not contain `Range`, then set response and internalResponse - // to a network error. - if ( - response.type === 'opaque' && - internalResponse.status === 206 && - internalResponse.rangeRequested && - !request.headers.contains('range', true) - ) { - response = internalResponse = makeNetworkError() + // If object’s type attribute is not the empty byte sequence, set + // type to its value. + if (object.type) { + type = object.type + } + } else if (typeof object[Symbol.asyncIterator] === 'function') { + // If keepalive is true, then throw a TypeError. + if (keepalive) { + throw new TypeError('keepalive') } - // 19. If response is not a network error and either request’s method is - // `HEAD` or `CONNECT`, or internalResponse’s status is a null body status, - // set internalResponse’s body to null and disregard any enqueuing toward - // it (if any). - if ( - response.status !== 0 && - (request.method === 'HEAD' || - request.method === 'CONNECT' || - nullBodyStatus.includes(internalResponse.status)) - ) { - internalResponse.body = null - fetchParams.controller.dump = true + // If object is disturbed or locked, then throw a TypeError. + if (util.isDisturbed(object) || object.locked) { + throw new TypeError( + 'Response body object should not be disturbed or locked' + ) } - // 20. If request’s integrity metadata is not the empty string, then: - if (request.integrity) { - // 1. Let processBodyError be this step: run fetch finale given fetchParams - // and a network error. - const processBodyError = (reason) => - fetchFinale(fetchParams, makeNetworkError(reason)) + stream = + webidl.is.ReadableStream(object) ? object : ReadableStreamFrom(object) + } - // 2. If request’s response tainting is "opaque", or response’s body is null, - // then run processBodyError and abort these steps. - if (request.responseTainting === 'opaque' || response.body == null) { - processBodyError(response.error) - return - } + // 11. If source is a byte sequence, then set action to a + // step that returns source and length to source’s length. + if (typeof source === 'string' || isUint8Array(source)) { + action = () => { + length = typeof source === 'string' ? Buffer.byteLength(source) : source.length + return source + } + } - // 3. Let processBody given bytes be these steps: - const processBody = (bytes) => { - // 1. If bytes do not match request’s integrity metadata, - // then run processBodyError and abort these steps. [SRI] - if (!bytesMatch(bytes, request.integrity)) { - processBodyError('integrity mismatch') - return + // 12. If action is non-null, then run these steps in parallel: + if (action != null) { + ;(async () => { + // 1. Run action. + const result = action() + + // 2. Whenever one or more bytes are available and stream is not errored, + // enqueue the result of creating a Uint8Array from the available bytes into stream. + const iterator = result?.[Symbol.asyncIterator]?.() + if (iterator) { + for await (const bytes of iterator) { + if (isErrored(stream)) break + if (bytes.length) { + controller.enqueue(new Uint8Array(bytes)) + } } - - // 2. Set response’s body to bytes as a body. - response.body = safelyExtractBody(bytes)[0] - - // 3. Run fetch finale given fetchParams and response. - fetchFinale(fetchParams, response) + } else if (result?.length && !isErrored(stream)) { + controller.enqueue(typeof result === 'string' ? textEncoder.encode(result) : new Uint8Array(result)) } - // 4. Fully read response’s body given processBody and processBodyError. - fullyReadBody(response.body, processBody, processBodyError) - } else { - // 21. Otherwise, run fetch finale given fetchParams and response. - fetchFinale(fetchParams, response) - } - } catch (err) { - fetchParams.controller.terminate(err) + // 3. When running action is done, close stream. + queueMicrotask(() => readableStreamClose(controller)) + })() } -} -// https://fetch.spec.whatwg.org/#concept-scheme-fetch -// given a fetch params fetchParams -function schemeFetch (fetchParams) { - // Note: since the connection is destroyed on redirect, which sets fetchParams to a - // cancelled state, we do not want this condition to trigger *unless* there have been - // no redirects. See https://github.com/nodejs/undici/issues/1776 - // 1. If fetchParams is canceled, then return the appropriate network error for fetchParams. - if (isCancelled(fetchParams) && fetchParams.request.redirectCount === 0) { - return Promise.resolve(makeAppropriateNetworkError(fetchParams)) - } + // 13. Let body be a body whose stream is stream, source is source, + // and length is length. + const body = { stream, source, length } - // 2. Let request be fetchParams’s request. - const { request } = fetchParams + // 14. Return (body, type). + return [body, type] +} - const { protocol: scheme } = requestCurrentURL(request) +/** + * @typedef {object} ExtractBodyResult + * @property {ReadableStream>} stream - The ReadableStream containing the body data + * @property {any} source - The original source of the body data + * @property {number | null} length - The length of the body data, or null + */ - // 3. Switch on request’s current URL’s scheme and run the associated steps: - switch (scheme) { - case 'about:': { - // If request’s current URL’s path is the string "blank", then return a new response - // whose status message is `OK`, header list is « (`Content-Type`, `text/html;charset=utf-8`) », - // and body is the empty byte sequence as a body. +/** + * Safely extract a body with type from a byte sequence or BodyInit object. + * + * @param {import('../../../types').BodyInit} object - The BodyInit object to extract from + * @param {boolean} [keepalive=false] - If true, indicates that the body + * @returns {[ExtractBodyResult, string | null]} - Returns a tuple containing the body and its type + * + * @see https://fetch.spec.whatwg.org/#bodyinit-safely-extract + */ +function safelyExtractBody (object, keepalive = false) { + // To safely extract a body and a `Content-Type` value from + // a byte sequence or BodyInit object object, run these steps: - // Otherwise, return a network error. - return Promise.resolve(makeNetworkError('about scheme is not supported')) - } - case 'blob:': { - if (!resolveObjectURL) { - resolveObjectURL = (__nccwpck_require__(4573).resolveObjectURL) - } + // 1. If object is a ReadableStream object, then: + if (webidl.is.ReadableStream(object)) { + // Assert: object is neither disturbed nor locked. + assert(!util.isDisturbed(object), 'The body has already been consumed.') + assert(!object.locked, 'The stream is locked.') + } - // 1. Let blobURLEntry be request’s current URL’s blob URL entry. - const blobURLEntry = requestCurrentURL(request) + // 2. Return the results of extracting object. + return extractBody(object, keepalive) +} - // https://github.com/web-platform-tests/wpt/blob/7b0ebaccc62b566a1965396e5be7bb2bc06f841f/FileAPI/url/resources/fetch-tests.js#L52-L56 - // Buffer.resolveObjectURL does not ignore URL queries. - if (blobURLEntry.search.length !== 0) { - return Promise.resolve(makeNetworkError('NetworkError when attempting to fetch resource.')) - } +function cloneBody (body) { + // To clone a body body, run these steps: - const blob = resolveObjectURL(blobURLEntry.toString()) + // https://fetch.spec.whatwg.org/#concept-body-clone - // 2. If request’s method is not `GET`, blobURLEntry is null, or blobURLEntry’s - // object is not a Blob object, then return a network error. - if (request.method !== 'GET' || !webidl.is.Blob(blob)) { - return Promise.resolve(makeNetworkError('invalid method')) - } + // 1. Let « out1, out2 » be the result of teeing body’s stream. + const { 0: out1, 1: out2 } = body.stream.tee() - // 3. Let blob be blobURLEntry’s object. - // Note: done above + // 2. Set body’s stream to out1. + body.stream = out1 - // 4. Let response be a new response. - const response = makeResponse() + // 3. Return a body whose stream is out2 and other members are copied from body. + return { + stream: out2, + length: body.length, + source: body.source + } +} - // 5. Let fullLength be blob’s size. - const fullLength = blob.size +function bodyMixinMethods (instance, getInternalState) { + const methods = { + blob () { + // The blob() method steps are to return the result of + // running consume body with this and the following step + // given a byte sequence bytes: return a Blob whose + // contents are bytes and whose type attribute is this’s + // MIME type. + return consumeBody(this, (bytes) => { + let mimeType = bodyMimeType(getInternalState(this)) - // 6. Let serializedFullLength be fullLength, serialized and isomorphic encoded. - const serializedFullLength = isomorphicEncode(`${fullLength}`) + if (mimeType === null) { + mimeType = '' + } else if (mimeType) { + mimeType = serializeAMimeType(mimeType) + } - // 7. Let type be blob’s type. - const type = blob.type + // Return a Blob whose contents are bytes and type attribute + // is mimeType. + return new Blob([bytes], { type: mimeType }) + }, instance, getInternalState) + }, - // 8. If request’s header list does not contain `Range`: - // 9. Otherwise: - if (!request.headersList.contains('range', true)) { - // 1. Let bodyWithType be the result of safely extracting blob. - // Note: in the FileAPI a blob "object" is a Blob *or* a MediaSource. - // In node, this can only ever be a Blob. Therefore we can safely - // use extractBody directly. - const bodyWithType = extractBody(blob) + arrayBuffer () { + // The arrayBuffer() method steps are to return the result + // of running consume body with this and the following step + // given a byte sequence bytes: return a new ArrayBuffer + // whose contents are bytes. + return consumeBody(this, (bytes) => { + return new Uint8Array(bytes).buffer + }, instance, getInternalState) + }, - // 2. Set response’s status message to `OK`. - response.statusText = 'OK' + text () { + // The text() method steps are to return the result of running + // consume body with this and UTF-8 decode. + return consumeBody(this, utf8DecodeBytes, instance, getInternalState) + }, - // 3. Set response’s body to bodyWithType’s body. - response.body = bodyWithType[0] + json () { + // The json() method steps are to return the result of running + // consume body with this and parse JSON from bytes. + return consumeBody(this, parseJSONFromBytes, instance, getInternalState) + }, - // 4. Set response’s header list to « (`Content-Length`, serializedFullLength), (`Content-Type`, type) ». - response.headersList.set('content-length', serializedFullLength, true) - response.headersList.set('content-type', type, true) - } else { - // 1. Set response’s range-requested flag. - response.rangeRequested = true + formData () { + // The formData() method steps are to return the result of running + // consume body with this and the following step given a byte sequence bytes: + return consumeBody(this, (value) => { + // 1. Let mimeType be the result of get the MIME type with this. + const mimeType = bodyMimeType(getInternalState(this)) - // 2. Let rangeHeader be the result of getting `Range` from request’s header list. - const rangeHeader = request.headersList.get('range', true) + // 2. If mimeType is non-null, then switch on mimeType’s essence and run + // the corresponding steps: + if (mimeType !== null) { + switch (mimeType.essence) { + case 'multipart/form-data': { + // 1. ... [long step] + // 2. If that fails for some reason, then throw a TypeError. + const parsed = multipartFormDataParser(value, mimeType) - // 3. Let rangeValue be the result of parsing a single range header value given rangeHeader and true. - const rangeValue = simpleRangeHeaderValue(rangeHeader, true) + // 3. Return a new FormData object, appending each entry, + // resulting from the parsing operation, to its entry list. + const fd = new FormData() + setFormDataState(fd, parsed) - // 4. If rangeValue is failure, then return a network error. - if (rangeValue === 'failure') { - return Promise.resolve(makeNetworkError('failed to fetch the data URL')) - } + return fd + } + case 'application/x-www-form-urlencoded': { + // 1. Let entries be the result of parsing bytes. + const entries = new URLSearchParams(value.toString()) - // 5. Let (rangeStart, rangeEnd) be rangeValue. - let { rangeStartValue: rangeStart, rangeEndValue: rangeEnd } = rangeValue + // 2. If entries is failure, then throw a TypeError. - // 6. If rangeStart is null: - // 7. Otherwise: - if (rangeStart === null) { - // 1. Set rangeStart to fullLength − rangeEnd. - rangeStart = fullLength - rangeEnd + // 3. Return a new FormData object whose entry list is entries. + const fd = new FormData() - // 2. Set rangeEnd to rangeStart + rangeEnd − 1. - rangeEnd = rangeStart + rangeEnd - 1 - } else { - // 1. If rangeStart is greater than or equal to fullLength, then return a network error. - if (rangeStart >= fullLength) { - return Promise.resolve(makeNetworkError('Range start is greater than the blob\'s size.')) - } + for (const [name, value] of entries) { + fd.append(name, value) + } - // 2. If rangeEnd is null or rangeEnd is greater than or equal to fullLength, then set - // rangeEnd to fullLength − 1. - if (rangeEnd === null || rangeEnd >= fullLength) { - rangeEnd = fullLength - 1 + return fd + } } } - // 8. Let slicedBlob be the result of invoking slice blob given blob, rangeStart, - // rangeEnd + 1, and type. - const slicedBlob = blob.slice(rangeStart, rangeEnd + 1, type) - - // 9. Let slicedBodyWithType be the result of safely extracting slicedBlob. - // Note: same reason as mentioned above as to why we use extractBody - const slicedBodyWithType = extractBody(slicedBlob) + // 3. Throw a TypeError. + throw new TypeError( + 'Content-Type was not one of "multipart/form-data" or "application/x-www-form-urlencoded".' + ) + }, instance, getInternalState) + }, - // 10. Set response’s body to slicedBodyWithType’s body. - response.body = slicedBodyWithType[0] + bytes () { + // The bytes() method steps are to return the result of running consume body + // with this and the following step given a byte sequence bytes: return the + // result of creating a Uint8Array from bytes in this’s relevant realm. + return consumeBody(this, (bytes) => { + return new Uint8Array(bytes) + }, instance, getInternalState) + } + } - // 11. Let serializedSlicedLength be slicedBlob’s size, serialized and isomorphic encoded. - const serializedSlicedLength = isomorphicEncode(`${slicedBlob.size}`) + return methods +} - // 12. Let contentRange be the result of invoking build a content range given rangeStart, - // rangeEnd, and fullLength. - const contentRange = buildContentRange(rangeStart, rangeEnd, fullLength) +function mixinBody (prototype, getInternalState) { + Object.assign(prototype.prototype, bodyMixinMethods(prototype, getInternalState)) +} - // 13. Set response’s status to 206. - response.status = 206 +/** + * @see https://fetch.spec.whatwg.org/#concept-body-consume-body + * @param {any} object internal state + * @param {(value: unknown) => unknown} convertBytesToJSValue + * @param {any} instance + * @param {(target: any) => any} getInternalState + */ +function consumeBody (object, convertBytesToJSValue, instance, getInternalState) { + try { + webidl.brandCheck(object, instance) + } catch (e) { + return Promise.reject(e) + } - // 14. Set response’s status message to `Partial Content`. - response.statusText = 'Partial Content' + const state = getInternalState(object) - // 15. Set response’s header list to « (`Content-Length`, serializedSlicedLength), - // (`Content-Type`, type), (`Content-Range`, contentRange) ». - response.headersList.set('content-length', serializedSlicedLength, true) - response.headersList.set('content-type', type, true) - response.headersList.set('content-range', contentRange, true) - } + // 1. If object is unusable, then return a promise rejected + // with a TypeError. + if (bodyUnusable(state)) { + return Promise.reject(new TypeError('Body is unusable: Body has already been read')) + } - // 10. Return response. - return Promise.resolve(response) - } - case 'data:': { - // 1. Let dataURLStruct be the result of running the - // data: URL processor on request’s current URL. - const currentURL = requestCurrentURL(request) - const dataURLStruct = dataURLProcessor(currentURL) + if (state.aborted) { + return Promise.reject(new DOMException('The operation was aborted.', 'AbortError')) + } - // 2. If dataURLStruct is failure, then return a - // network error. - if (dataURLStruct === 'failure') { - return Promise.resolve(makeNetworkError('failed to fetch the data URL')) - } + // 2. Let promise be a new promise. + const promise = createDeferredPromise() - // 3. Let mimeType be dataURLStruct’s MIME type, serialized. - const mimeType = serializeAMimeType(dataURLStruct.mimeType) + // 3. Let errorSteps given error be to reject promise with error. + const errorSteps = promise.reject - // 4. Return a response whose status message is `OK`, - // header list is « (`Content-Type`, mimeType) », - // and body is dataURLStruct’s body as a body. - return Promise.resolve(makeResponse({ - statusText: 'OK', - headersList: [ - ['content-type', { name: 'Content-Type', value: mimeType }] - ], - body: safelyExtractBody(dataURLStruct.body)[0] - })) - } - case 'file:': { - // For now, unfortunate as it is, file URLs are left as an exercise for the reader. - // When in doubt, return a network error. - return Promise.resolve(makeNetworkError('not implemented... yet...')) + // 4. Let successSteps given a byte sequence data be to resolve + // promise with the result of running convertBytesToJSValue + // with data. If that threw an exception, then run errorSteps + // with that exception. + const successSteps = (data) => { + try { + promise.resolve(convertBytesToJSValue(data)) + } catch (e) { + errorSteps(e) } - case 'http:': - case 'https:': { - // Return the result of running HTTP fetch given fetchParams. + } - return httpFetch(fetchParams) - .catch((err) => makeNetworkError(err)) - } - default: { - return Promise.resolve(makeNetworkError('unknown scheme')) - } + // 5. If object’s body is null, then run successSteps with an + // empty byte sequence. + if (state.body == null) { + successSteps(Buffer.allocUnsafe(0)) + return promise.promise } + + // 6. Otherwise, fully read object’s body given successSteps, + // errorSteps, and object’s relevant global object. + fullyReadBody(state.body, successSteps, errorSteps) + + // 7. Return promise. + return promise.promise } -// https://fetch.spec.whatwg.org/#finalize-response -function finalizeResponse (fetchParams, response) { - // 1. Set fetchParams’s request’s done flag. - fetchParams.request.done = true +/** + * @see https://fetch.spec.whatwg.org/#body-unusable + * @param {any} object internal state + */ +function bodyUnusable (object) { + const body = object.body - // 2, If fetchParams’s process response done is not null, then queue a fetch - // task to run fetchParams’s process response done given response, with - // fetchParams’s task destination. - if (fetchParams.processResponseDone != null) { - queueMicrotask(() => fetchParams.processResponseDone(response)) - } + // An object including the Body interface mixin is + // said to be unusable if its body is non-null and + // its body’s stream is disturbed or locked. + return body != null && (body.stream.locked || util.isDisturbed(body.stream)) } -// https://fetch.spec.whatwg.org/#fetch-finale -function fetchFinale (fetchParams, response) { - // 1. Let timingInfo be fetchParams’s timing info. - let timingInfo = fetchParams.timingInfo +/** + * @see https://fetch.spec.whatwg.org/#concept-body-mime-type + * @param {any} requestOrResponse internal state + */ +function bodyMimeType (requestOrResponse) { + // 1. Let headers be null. + // 2. If requestOrResponse is a Request object, then set headers to requestOrResponse’s request’s header list. + // 3. Otherwise, set headers to requestOrResponse’s response’s header list. + /** @type {import('./headers').HeadersList} */ + const headers = requestOrResponse.headersList - // 2. If response is not a network error and fetchParams’s request’s client is a secure context, - // then set timingInfo’s server-timing headers to the result of getting, decoding, and splitting - // `Server-Timing` from response’s internal response’s header list. - // TODO + // 4. Let mimeType be the result of extracting a MIME type from headers. + const mimeType = extractMimeType(headers) - // 3. Let processResponseEndOfBody be the following steps: - const processResponseEndOfBody = () => { - // 1. Let unsafeEndTime be the unsafe shared current time. - const unsafeEndTime = Date.now() // ? + // 5. If mimeType is failure, then return null. + if (mimeType === 'failure') { + return null + } - // 2. If fetchParams’s request’s destination is "document", then set fetchParams’s controller’s - // full timing info to fetchParams’s timing info. - if (fetchParams.request.destination === 'document') { - fetchParams.controller.fullTimingInfo = timingInfo - } + // 6. Return mimeType. + return mimeType +} - // 3. Set fetchParams’s controller’s report timing steps to the following steps given a global object global: - fetchParams.controller.reportTimingSteps = () => { - // 1. If fetchParams’s request’s URL’s scheme is not an HTTP(S) scheme, then return. - if (!urlIsHttpHttpsScheme(fetchParams.request.url)) { - return - } +module.exports = { + extractBody, + safelyExtractBody, + cloneBody, + mixinBody, + streamRegistry, + bodyUnusable +} - // 2. Set timingInfo’s end time to the relative high resolution time given unsafeEndTime and global. - timingInfo.endTime = unsafeEndTime - // 3. Let cacheState be response’s cache state. - let cacheState = response.cacheState +/***/ }), - // 4. Let bodyInfo be response’s body info. - const bodyInfo = response.bodyInfo +/***/ 8973: +/***/ ((module) => { - // 5. If response’s timing allow passed flag is not set, then set timingInfo to the result of creating an - // opaque timing info for timingInfo and set cacheState to the empty string. - if (!response.timingAllowPassed) { - timingInfo = createOpaqueTimingInfo(timingInfo) - cacheState = '' - } - // 6. Let responseStatus be 0. - let responseStatus = 0 +const corsSafeListedMethods = /** @type {const} */ (['GET', 'HEAD', 'POST']) +const corsSafeListedMethodsSet = new Set(corsSafeListedMethods) - // 7. If fetchParams’s request’s mode is not "navigate" or response’s has-cross-origin-redirects is false: - if (fetchParams.request.mode !== 'navigator' || !response.hasCrossOriginRedirects) { - // 1. Set responseStatus to response’s status. - responseStatus = response.status +const nullBodyStatus = /** @type {const} */ ([101, 204, 205, 304]) - // 2. Let mimeType be the result of extracting a MIME type from response’s header list. - const mimeType = extractMimeType(response.headersList) +const redirectStatus = /** @type {const} */ ([301, 302, 303, 307, 308]) +const redirectStatusSet = new Set(redirectStatus) - // 3. If mimeType is not failure, then set bodyInfo’s content type to the result of minimizing a supported MIME type given mimeType. - if (mimeType !== 'failure') { - bodyInfo.contentType = minimizeSupportedMimeType(mimeType) - } - } +/** + * @see https://fetch.spec.whatwg.org/#block-bad-port + */ +const badPorts = /** @type {const} */ ([ + '1', '7', '9', '11', '13', '15', '17', '19', '20', '21', '22', '23', '25', '37', '42', '43', '53', '69', '77', '79', + '87', '95', '101', '102', '103', '104', '109', '110', '111', '113', '115', '117', '119', '123', '135', '137', + '139', '143', '161', '179', '389', '427', '465', '512', '513', '514', '515', '526', '530', '531', '532', + '540', '548', '554', '556', '563', '587', '601', '636', '989', '990', '993', '995', '1719', '1720', '1723', + '2049', '3659', '4045', '4190', '5060', '5061', '6000', '6566', '6665', '6666', '6667', '6668', '6669', '6679', + '6697', '10080' +]) +const badPortsSet = new Set(badPorts) - // 8. If fetchParams’s request’s initiator type is non-null, then mark resource timing given timingInfo, - // fetchParams’s request’s URL, fetchParams’s request’s initiator type, global, cacheState, bodyInfo, - // and responseStatus. - if (fetchParams.request.initiatorType != null) { - markResourceTiming(timingInfo, fetchParams.request.url.href, fetchParams.request.initiatorType, globalThis, cacheState, bodyInfo, responseStatus) - } - } +/** + * @see https://w3c.github.io/webappsec-referrer-policy/#referrer-policy-header + */ +const referrerPolicyTokens = /** @type {const} */ ([ + 'no-referrer', + 'no-referrer-when-downgrade', + 'same-origin', + 'origin', + 'strict-origin', + 'origin-when-cross-origin', + 'strict-origin-when-cross-origin', + 'unsafe-url' +]) - // 4. Let processResponseEndOfBodyTask be the following steps: - const processResponseEndOfBodyTask = () => { - // 1. Set fetchParams’s request’s done flag. - fetchParams.request.done = true +/** + * @see https://w3c.github.io/webappsec-referrer-policy/#referrer-policies + */ +const referrerPolicy = /** @type {const} */ ([ + '', + ...referrerPolicyTokens +]) +const referrerPolicyTokensSet = new Set(referrerPolicyTokens) - // 2. If fetchParams’s process response end-of-body is non-null, then run fetchParams’s process - // response end-of-body given response. - if (fetchParams.processResponseEndOfBody != null) { - queueMicrotask(() => fetchParams.processResponseEndOfBody(response)) - } +const requestRedirect = /** @type {const} */ (['follow', 'manual', 'error']) - // 3. If fetchParams’s request’s initiator type is non-null and fetchParams’s request’s client’s - // global object is fetchParams’s task destination, then run fetchParams’s controller’s report - // timing steps given fetchParams’s request’s client’s global object. - if (fetchParams.request.initiatorType != null) { - fetchParams.controller.reportTimingSteps() - } - } +const safeMethods = /** @type {const} */ (['GET', 'HEAD', 'OPTIONS', 'TRACE']) +const safeMethodsSet = new Set(safeMethods) - // 5. Queue a fetch task to run processResponseEndOfBodyTask with fetchParams’s task destination - queueMicrotask(() => processResponseEndOfBodyTask()) - } +const requestMode = /** @type {const} */ (['navigate', 'same-origin', 'no-cors', 'cors']) - // 4. If fetchParams’s process response is non-null, then queue a fetch task to run fetchParams’s - // process response given response, with fetchParams’s task destination. - if (fetchParams.processResponse != null) { - queueMicrotask(() => { - fetchParams.processResponse(response) - fetchParams.processResponse = null - }) - } +const requestCredentials = /** @type {const} */ (['omit', 'same-origin', 'include']) - // 5. Let internalResponse be response, if response is a network error; otherwise response’s internal response. - const internalResponse = response.type === 'error' ? response : (response.internalResponse ?? response) +const requestCache = /** @type {const} */ ([ + 'default', + 'no-store', + 'reload', + 'no-cache', + 'force-cache', + 'only-if-cached' +]) - // 6. If internalResponse’s body is null, then run processResponseEndOfBody. - // 7. Otherwise: - if (internalResponse.body == null) { - processResponseEndOfBody() - } else { - // mcollina: all the following steps of the specs are skipped. - // The internal transform stream is not needed. - // See https://github.com/nodejs/undici/pull/3093#issuecomment-2050198541 +/** + * @see https://fetch.spec.whatwg.org/#request-body-header-name + */ +const requestBodyHeader = /** @type {const} */ ([ + 'content-encoding', + 'content-language', + 'content-location', + 'content-type', + // See https://github.com/nodejs/undici/issues/2021 + // 'Content-Length' is a forbidden header name, which is typically + // removed in the Headers implementation. However, undici doesn't + // filter out headers, so we add it here. + 'content-length' +]) - // 1. Let transformStream be a new TransformStream. - // 2. Let identityTransformAlgorithm be an algorithm which, given chunk, enqueues chunk in transformStream. - // 3. Set up transformStream with transformAlgorithm set to identityTransformAlgorithm and flushAlgorithm - // set to processResponseEndOfBody. - // 4. Set internalResponse’s body’s stream to the result of internalResponse’s body’s stream piped through transformStream. +/** + * @see https://fetch.spec.whatwg.org/#enumdef-requestduplex + */ +const requestDuplex = /** @type {const} */ ([ + 'half' +]) - finished(internalResponse.body.stream, () => { - processResponseEndOfBody() - }) - } +/** + * @see http://fetch.spec.whatwg.org/#forbidden-method + */ +const forbiddenMethods = /** @type {const} */ (['CONNECT', 'TRACE', 'TRACK']) +const forbiddenMethodsSet = new Set(forbiddenMethods) + +const subresource = /** @type {const} */ ([ + 'audio', + 'audioworklet', + 'font', + 'image', + 'manifest', + 'paintworklet', + 'script', + 'style', + 'track', + 'video', + 'xslt', + '' +]) +const subresourceSet = new Set(subresource) + +module.exports = { + subresource, + forbiddenMethods, + requestBodyHeader, + referrerPolicy, + requestRedirect, + requestMode, + requestCredentials, + requestCache, + redirectStatus, + corsSafeListedMethods, + nullBodyStatus, + safeMethods, + badPorts, + requestDuplex, + subresourceSet, + badPortsSet, + redirectStatusSet, + corsSafeListedMethodsSet, + safeMethodsSet, + forbiddenMethodsSet, + referrerPolicyTokens: referrerPolicyTokensSet } -// https://fetch.spec.whatwg.org/#http-fetch -async function httpFetch (fetchParams) { - // 1. Let request be fetchParams’s request. - const request = fetchParams.request - // 2. Let response be null. - let response = null +/***/ }), - // 3. Let actualResponse be null. - let actualResponse = null +/***/ 1410: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - // 4. Let timingInfo be fetchParams’s timing info. - const timingInfo = fetchParams.timingInfo - // 5. If request’s service-workers mode is "all", then: - if (request.serviceWorkers === 'all') { - // TODO - } - // 6. If response is null, then: - if (response === null) { - // 1. If makeCORSPreflight is true and one of these conditions is true: - // TODO +const assert = __nccwpck_require__(4589) +const { forgivingBase64, collectASequenceOfCodePoints, collectASequenceOfCodePointsFast, isomorphicDecode, removeASCIIWhitespace, removeChars } = __nccwpck_require__(5074) - // 2. If request’s redirect mode is "follow", then set request’s - // service-workers mode to "none". - if (request.redirect === 'follow') { - request.serviceWorkers = 'none' - } +const encoder = new TextEncoder() - // 3. Set response and actualResponse to the result of running - // HTTP-network-or-cache fetch given fetchParams. - actualResponse = response = await httpNetworkOrCacheFetch(fetchParams) +/** + * @see https://mimesniff.spec.whatwg.org/#http-token-code-point + */ +const HTTP_TOKEN_CODEPOINTS = /^[-!#$%&'*+.^_|~A-Za-z0-9]+$/u +const HTTP_WHITESPACE_REGEX = /[\u000A\u000D\u0009\u0020]/u // eslint-disable-line - // 4. If request’s response tainting is "cors" and a CORS check - // for request and response returns failure, then return a network error. - if ( - request.responseTainting === 'cors' && - corsCheck(request, response) === 'failure' - ) { - return makeNetworkError('cors failure') - } +/** + * @see https://mimesniff.spec.whatwg.org/#http-quoted-string-token-code-point + */ +const HTTP_QUOTED_STRING_TOKENS = /^[\u0009\u0020-\u007E\u0080-\u00FF]+$/u // eslint-disable-line - // 5. If the TAO check for request and response returns failure, then set - // request’s timing allow failed flag. - if (TAOCheck(request, response) === 'failure') { - request.timingAllowFailed = true - } - } +// https://fetch.spec.whatwg.org/#data-url-processor +/** @param {URL} dataURL */ +function dataURLProcessor (dataURL) { + // 1. Assert: dataURL’s scheme is "data". + assert(dataURL.protocol === 'data:') - // 7. If either request’s response tainting or response’s type - // is "opaque", and the cross-origin resource policy check with - // request’s origin, request’s client, request’s destination, - // and actualResponse returns blocked, then return a network error. - if ( - (request.responseTainting === 'opaque' || response.type === 'opaque') && - crossOriginResourcePolicyCheck( - request.origin, - request.client, - request.destination, - actualResponse - ) === 'blocked' - ) { - return makeNetworkError('blocked') - } + // 2. Let input be the result of running the URL + // serializer on dataURL with exclude fragment + // set to true. + let input = URLSerializer(dataURL, true) - // 8. If actualResponse’s status is a redirect status, then: - if (redirectStatusSet.has(actualResponse.status)) { - // 1. If actualResponse’s status is not 303, request’s body is not null, - // and the connection uses HTTP/2, then user agents may, and are even - // encouraged to, transmit an RST_STREAM frame. - // See, https://github.com/whatwg/fetch/issues/1288 - if (request.redirect !== 'manual') { - fetchParams.controller.connection.destroy(undefined, false) - } + // 3. Remove the leading "data:" string from input. + input = input.slice(5) - // 2. Switch on request’s redirect mode: - if (request.redirect === 'error') { - // Set response to a network error. - response = makeNetworkError('unexpected redirect') - } else if (request.redirect === 'manual') { - // Set response to an opaque-redirect filtered response whose internal - // response is actualResponse. - // NOTE(spec): On the web this would return an `opaqueredirect` response, - // but that doesn't make sense server side. - // See https://github.com/nodejs/undici/issues/1193. - response = actualResponse - } else if (request.redirect === 'follow') { - // Set response to the result of running HTTP-redirect fetch given - // fetchParams and response. - response = await httpRedirectFetch(fetchParams, response) - } else { - assert(false) - } - } + // 4. Let position point at the start of input. + const position = { position: 0 } - // 9. Set response’s timing info to timingInfo. - response.timingInfo = timingInfo + // 5. Let mimeType be the result of collecting a + // sequence of code points that are not equal + // to U+002C (,), given position. + let mimeType = collectASequenceOfCodePointsFast( + ',', + input, + position + ) - // 10. Return response. - return response -} + // 6. Strip leading and trailing ASCII whitespace + // from mimeType. + // Undici implementation note: we need to store the + // length because if the mimetype has spaces removed, + // the wrong amount will be sliced from the input in + // step #9 + const mimeTypeLength = mimeType.length + mimeType = removeASCIIWhitespace(mimeType, true, true) -// https://fetch.spec.whatwg.org/#http-redirect-fetch -function httpRedirectFetch (fetchParams, response) { - // 1. Let request be fetchParams’s request. - const request = fetchParams.request + // 7. If position is past the end of input, then + // return failure + if (position.position >= input.length) { + return 'failure' + } - // 2. Let actualResponse be response, if response is not a filtered response, - // and response’s internal response otherwise. - const actualResponse = response.internalResponse - ? response.internalResponse - : response + // 8. Advance position by 1. + position.position++ - // 3. Let locationURL be actualResponse’s location URL given request’s current - // URL’s fragment. - let locationURL + // 9. Let encodedBody be the remainder of input. + const encodedBody = input.slice(mimeTypeLength + 1) - try { - locationURL = responseLocationURL( - actualResponse, - requestCurrentURL(request).hash - ) + // 10. Let body be the percent-decoding of encodedBody. + let body = stringPercentDecode(encodedBody) - // 4. If locationURL is null, then return response. - if (locationURL == null) { - return response - } - } catch (err) { - // 5. If locationURL is failure, then return a network error. - return Promise.resolve(makeNetworkError(err)) - } + // 11. If mimeType ends with U+003B (;), followed by + // zero or more U+0020 SPACE, followed by an ASCII + // case-insensitive match for "base64", then: + if (/;(?:\u0020*)base64$/ui.test(mimeType)) { + // 1. Let stringBody be the isomorphic decode of body. + const stringBody = isomorphicDecode(body) - // 6. If locationURL’s scheme is not an HTTP(S) scheme, then return a network - // error. - if (!urlIsHttpHttpsScheme(locationURL)) { - return Promise.resolve(makeNetworkError('URL scheme must be a HTTP(S) scheme')) - } + // 2. Set body to the forgiving-base64 decode of + // stringBody. + body = forgivingBase64(stringBody) - // 7. If request’s redirect count is 20, then return a network error. - if (request.redirectCount === 20) { - return Promise.resolve(makeNetworkError('redirect count exceeded')) - } + // 3. If body is failure, then return failure. + if (body === 'failure') { + return 'failure' + } - // 8. Increase request’s redirect count by 1. - request.redirectCount += 1 + // 4. Remove the last 6 code points from mimeType. + mimeType = mimeType.slice(0, -6) - // 9. If request’s mode is "cors", locationURL includes credentials, and - // request’s origin is not same origin with locationURL’s origin, then return - // a network error. - if ( - request.mode === 'cors' && - (locationURL.username || locationURL.password) && - !sameOrigin(request, locationURL) - ) { - return Promise.resolve(makeNetworkError('cross origin not allowed for request mode "cors"')) - } + // 5. Remove trailing U+0020 SPACE code points from mimeType, + // if any. + mimeType = mimeType.replace(/(\u0020+)$/u, '') - // 10. If request’s response tainting is "cors" and locationURL includes - // credentials, then return a network error. - if ( - request.responseTainting === 'cors' && - (locationURL.username || locationURL.password) - ) { - return Promise.resolve(makeNetworkError( - 'URL cannot contain credentials for request mode "cors"' - )) + // 6. Remove the last U+003B (;) code point from mimeType. + mimeType = mimeType.slice(0, -1) } - // 11. If actualResponse’s status is not 303, request’s body is non-null, - // and request’s body’s source is null, then return a network error. - if ( - actualResponse.status !== 303 && - request.body != null && - request.body.source == null - ) { - return Promise.resolve(makeNetworkError()) + // 12. If mimeType starts with U+003B (;), then prepend + // "text/plain" to mimeType. + if (mimeType.startsWith(';')) { + mimeType = 'text/plain' + mimeType } - // 12. If one of the following is true - // - actualResponse’s status is 301 or 302 and request’s method is `POST` - // - actualResponse’s status is 303 and request’s method is not `GET` or `HEAD` - if ( - ([301, 302].includes(actualResponse.status) && request.method === 'POST') || - (actualResponse.status === 303 && - !GET_OR_HEAD.includes(request.method)) - ) { - // then: - // 1. Set request’s method to `GET` and request’s body to null. - request.method = 'GET' - request.body = null + // 13. Let mimeTypeRecord be the result of parsing + // mimeType. + let mimeTypeRecord = parseMIMEType(mimeType) - // 2. For each headerName of request-body-header name, delete headerName from - // request’s header list. - for (const headerName of requestBodyHeader) { - request.headersList.delete(headerName) - } + // 14. If mimeTypeRecord is failure, then set + // mimeTypeRecord to text/plain;charset=US-ASCII. + if (mimeTypeRecord === 'failure') { + mimeTypeRecord = parseMIMEType('text/plain;charset=US-ASCII') } - // 13. If request’s current URL’s origin is not same origin with locationURL’s - // origin, then for each headerName of CORS non-wildcard request-header name, - // delete headerName from request’s header list. - if (!sameOrigin(requestCurrentURL(request), locationURL)) { - // https://fetch.spec.whatwg.org/#cors-non-wildcard-request-header-name - request.headersList.delete('authorization', true) - - // https://fetch.spec.whatwg.org/#authentication-entries - request.headersList.delete('proxy-authorization', true) - - // "Cookie" and "Host" are forbidden request-headers, which undici doesn't implement. - request.headersList.delete('cookie', true) - request.headersList.delete('host', true) - } + // 15. Return a new data: URL struct whose MIME + // type is mimeTypeRecord and body is body. + // https://fetch.spec.whatwg.org/#data-url-struct + return { mimeType: mimeTypeRecord, body } +} - // 14. If request’s body is non-null, then set request’s body to the first return - // value of safely extracting request’s body’s source. - if (request.body != null) { - assert(request.body.source != null) - request.body = safelyExtractBody(request.body.source)[0] +// https://url.spec.whatwg.org/#concept-url-serializer +/** + * @param {URL} url + * @param {boolean} excludeFragment + */ +function URLSerializer (url, excludeFragment = false) { + if (!excludeFragment) { + return url.href } - // 15. Let timingInfo be fetchParams’s timing info. - const timingInfo = fetchParams.timingInfo + const href = url.href + const hashLength = url.hash.length - // 16. Set timingInfo’s redirect end time and post-redirect start time to the - // coarsened shared current time given fetchParams’s cross-origin isolated - // capability. - timingInfo.redirectEndTime = timingInfo.postRedirectStartTime = - coarsenedSharedCurrentTime(fetchParams.crossOriginIsolatedCapability) + const serialized = hashLength === 0 ? href : href.substring(0, href.length - hashLength) - // 17. If timingInfo’s redirect start time is 0, then set timingInfo’s - // redirect start time to timingInfo’s start time. - if (timingInfo.redirectStartTime === 0) { - timingInfo.redirectStartTime = timingInfo.startTime + if (!hashLength && href.endsWith('#')) { + return serialized.slice(0, -1) } - // 18. Append locationURL to request’s URL list. - request.urlList.push(locationURL) + return serialized +} - // 19. Invoke set request’s referrer policy on redirect on request and - // actualResponse. - setRequestReferrerPolicyOnRedirect(request, actualResponse) +// https://url.spec.whatwg.org/#string-percent-decode +/** @param {string} input */ +function stringPercentDecode (input) { + // 1. Let bytes be the UTF-8 encoding of input. + const bytes = encoder.encode(input) - // 20. Return the result of running main fetch given fetchParams and true. - return mainFetch(fetchParams, true) + // 2. Return the percent-decoding of bytes. + return percentDecode(bytes) } -// https://fetch.spec.whatwg.org/#http-network-or-cache-fetch -async function httpNetworkOrCacheFetch ( - fetchParams, - isAuthenticationFetch = false, - isNewConnectionFetch = false -) { - // 1. Let request be fetchParams’s request. - const request = fetchParams.request +/** + * @param {number} byte + */ +function isHexCharByte (byte) { + // 0-9 A-F a-f + return (byte >= 0x30 && byte <= 0x39) || (byte >= 0x41 && byte <= 0x46) || (byte >= 0x61 && byte <= 0x66) +} - // 2. Let httpFetchParams be null. - let httpFetchParams = null +/** + * @param {number} byte + */ +function hexByteToNumber (byte) { + return ( + // 0-9 + byte >= 0x30 && byte <= 0x39 + ? (byte - 48) + // Convert to uppercase + // ((byte & 0xDF) - 65) + 10 + : ((byte & 0xDF) - 55) + ) +} - // 3. Let httpRequest be null. - let httpRequest = null +// https://url.spec.whatwg.org/#percent-decode +/** @param {Uint8Array} input */ +function percentDecode (input) { + const length = input.length + // 1. Let output be an empty byte sequence. + /** @type {Uint8Array} */ + const output = new Uint8Array(length) + let j = 0 + let i = 0 + // 2. For each byte byte in input: + while (i < length) { + const byte = input[i] - // 4. Let response be null. - let response = null + // 1. If byte is not 0x25 (%), then append byte to output. + if (byte !== 0x25) { + output[j++] = byte - // 5. Let storedResponse be null. - // TODO: cache + // 2. Otherwise, if byte is 0x25 (%) and the next two bytes + // after byte in input are not in the ranges + // 0x30 (0) to 0x39 (9), 0x41 (A) to 0x46 (F), + // and 0x61 (a) to 0x66 (f), all inclusive, append byte + // to output. + } else if ( + byte === 0x25 && + !(isHexCharByte(input[i + 1]) && isHexCharByte(input[i + 2])) + ) { + output[j++] = 0x25 - // 6. Let httpCache be null. - const httpCache = null + // 3. Otherwise: + } else { + // 1. Let bytePoint be the two bytes after byte in input, + // decoded, and then interpreted as hexadecimal number. + // 2. Append a byte whose value is bytePoint to output. + output[j++] = (hexByteToNumber(input[i + 1]) << 4) | hexByteToNumber(input[i + 2]) - // 7. Let the revalidatingFlag be unset. - const revalidatingFlag = false + // 3. Skip the next two bytes in input. + i += 2 + } + ++i + } - // 8. Run these steps, but abort when the ongoing fetch is terminated: + // 3. Return output. + return length === j ? output : output.subarray(0, j) +} - // 1. If request’s window is "no-window" and request’s redirect mode is - // "error", then set httpFetchParams to fetchParams and httpRequest to - // request. - if (request.window === 'no-window' && request.redirect === 'error') { - httpFetchParams = fetchParams - httpRequest = request - } else { - // Otherwise: +// https://mimesniff.spec.whatwg.org/#parse-a-mime-type +/** @param {string} input */ +function parseMIMEType (input) { + // 1. Remove any leading and trailing HTTP whitespace + // from input. + input = removeHTTPWhitespace(input, true, true) - // 1. Set httpRequest to a clone of request. - httpRequest = cloneRequest(request) + // 2. Let position be a position variable for input, + // initially pointing at the start of input. + const position = { position: 0 } - // 2. Set httpFetchParams to a copy of fetchParams. - httpFetchParams = { ...fetchParams } + // 3. Let type be the result of collecting a sequence + // of code points that are not U+002F (/) from + // input, given position. + const type = collectASequenceOfCodePointsFast( + '/', + input, + position + ) - // 3. Set httpFetchParams’s request to httpRequest. - httpFetchParams.request = httpRequest + // 4. If type is the empty string or does not solely + // contain HTTP token code points, then return failure. + // https://mimesniff.spec.whatwg.org/#http-token-code-point + if (type.length === 0 || !HTTP_TOKEN_CODEPOINTS.test(type)) { + return 'failure' } - // 3. Let includeCredentials be true if one of - const includeCredentials = - request.credentials === 'include' || - (request.credentials === 'same-origin' && - request.responseTainting === 'basic') - - // 4. Let contentLength be httpRequest’s body’s length, if httpRequest’s - // body is non-null; otherwise null. - const contentLength = httpRequest.body ? httpRequest.body.length : null - - // 5. Let contentLengthHeaderValue be null. - let contentLengthHeaderValue = null - - // 6. If httpRequest’s body is null and httpRequest’s method is `POST` or - // `PUT`, then set contentLengthHeaderValue to `0`. - if ( - httpRequest.body == null && - ['POST', 'PUT'].includes(httpRequest.method) - ) { - contentLengthHeaderValue = '0' + // 5. If position is past the end of input, then return + // failure + if (position.position >= input.length) { + return 'failure' } - // 7. If contentLength is non-null, then set contentLengthHeaderValue to - // contentLength, serialized and isomorphic encoded. - if (contentLength != null) { - contentLengthHeaderValue = isomorphicEncode(`${contentLength}`) - } + // 6. Advance position by 1. (This skips past U+002F (/).) + position.position++ - // 8. If contentLengthHeaderValue is non-null, then append - // `Content-Length`/contentLengthHeaderValue to httpRequest’s header - // list. - if (contentLengthHeaderValue != null) { - httpRequest.headersList.append('content-length', contentLengthHeaderValue, true) - } + // 7. Let subtype be the result of collecting a sequence of + // code points that are not U+003B (;) from input, given + // position. + let subtype = collectASequenceOfCodePointsFast( + ';', + input, + position + ) - // 9. If contentLengthHeaderValue is non-null, then append (`Content-Length`, - // contentLengthHeaderValue) to httpRequest’s header list. + // 8. Remove any trailing HTTP whitespace from subtype. + subtype = removeHTTPWhitespace(subtype, false, true) - // 10. If contentLength is non-null and httpRequest’s keepalive is true, - // then: - if (contentLength != null && httpRequest.keepalive) { - // NOTE: keepalive is a noop outside of browser context. + // 9. If subtype is the empty string or does not solely + // contain HTTP token code points, then return failure. + if (subtype.length === 0 || !HTTP_TOKEN_CODEPOINTS.test(subtype)) { + return 'failure' } - // 11. If httpRequest’s referrer is a URL, then append - // `Referer`/httpRequest’s referrer, serialized and isomorphic encoded, - // to httpRequest’s header list. - if (webidl.is.URL(httpRequest.referrer)) { - httpRequest.headersList.append('referer', isomorphicEncode(httpRequest.referrer.href), true) + const typeLowercase = type.toLowerCase() + const subtypeLowercase = subtype.toLowerCase() + + // 10. Let mimeType be a new MIME type record whose type + // is type, in ASCII lowercase, and subtype is subtype, + // in ASCII lowercase. + // https://mimesniff.spec.whatwg.org/#mime-type + const mimeType = { + type: typeLowercase, + subtype: subtypeLowercase, + /** @type {Map} */ + parameters: new Map(), + // https://mimesniff.spec.whatwg.org/#mime-type-essence + essence: `${typeLowercase}/${subtypeLowercase}` } - // 12. Append a request `Origin` header for httpRequest. - appendRequestOriginHeader(httpRequest) + // 11. While position is not past the end of input: + while (position.position < input.length) { + // 1. Advance position by 1. (This skips past U+003B (;).) + position.position++ - // 13. Append the Fetch metadata headers for httpRequest. [FETCH-METADATA] - appendFetchMetadata(httpRequest) + // 2. Collect a sequence of code points that are HTTP + // whitespace from input given position. + collectASequenceOfCodePoints( + // https://fetch.spec.whatwg.org/#http-whitespace + char => HTTP_WHITESPACE_REGEX.test(char), + input, + position + ) - // 14. If httpRequest’s header list does not contain `User-Agent`, then - // user agents should append `User-Agent`/default `User-Agent` value to - // httpRequest’s header list. - if (!httpRequest.headersList.contains('user-agent', true)) { - httpRequest.headersList.append('user-agent', defaultUserAgent, true) - } + // 3. Let parameterName be the result of collecting a + // sequence of code points that are not U+003B (;) + // or U+003D (=) from input, given position. + let parameterName = collectASequenceOfCodePoints( + (char) => char !== ';' && char !== '=', + input, + position + ) - // 15. If httpRequest’s cache mode is "default" and httpRequest’s header - // list contains `If-Modified-Since`, `If-None-Match`, - // `If-Unmodified-Since`, `If-Match`, or `If-Range`, then set - // httpRequest’s cache mode to "no-store". - if ( - httpRequest.cache === 'default' && - (httpRequest.headersList.contains('if-modified-since', true) || - httpRequest.headersList.contains('if-none-match', true) || - httpRequest.headersList.contains('if-unmodified-since', true) || - httpRequest.headersList.contains('if-match', true) || - httpRequest.headersList.contains('if-range', true)) - ) { - httpRequest.cache = 'no-store' - } + // 4. Set parameterName to parameterName, in ASCII + // lowercase. + parameterName = parameterName.toLowerCase() - // 16. If httpRequest’s cache mode is "no-cache", httpRequest’s prevent - // no-cache cache-control header modification flag is unset, and - // httpRequest’s header list does not contain `Cache-Control`, then append - // `Cache-Control`/`max-age=0` to httpRequest’s header list. - if ( - httpRequest.cache === 'no-cache' && - !httpRequest.preventNoCacheCacheControlHeaderModification && - !httpRequest.headersList.contains('cache-control', true) - ) { - httpRequest.headersList.append('cache-control', 'max-age=0', true) - } + // 5. If position is not past the end of input, then: + if (position.position < input.length) { + // 1. If the code point at position within input is + // U+003B (;), then continue. + if (input[position.position] === ';') { + continue + } - // 17. If httpRequest’s cache mode is "no-store" or "reload", then: - if (httpRequest.cache === 'no-store' || httpRequest.cache === 'reload') { - // 1. If httpRequest’s header list does not contain `Pragma`, then append - // `Pragma`/`no-cache` to httpRequest’s header list. - if (!httpRequest.headersList.contains('pragma', true)) { - httpRequest.headersList.append('pragma', 'no-cache', true) + // 2. Advance position by 1. (This skips past U+003D (=).) + position.position++ } - // 2. If httpRequest’s header list does not contain `Cache-Control`, - // then append `Cache-Control`/`no-cache` to httpRequest’s header list. - if (!httpRequest.headersList.contains('cache-control', true)) { - httpRequest.headersList.append('cache-control', 'no-cache', true) + // 6. If position is past the end of input, then break. + if (position.position >= input.length) { + break } - } - // 18. If httpRequest’s header list contains `Range`, then append - // `Accept-Encoding`/`identity` to httpRequest’s header list. - if (httpRequest.headersList.contains('range', true)) { - httpRequest.headersList.append('accept-encoding', 'identity', true) - } + // 7. Let parameterValue be null. + let parameterValue = null - // 19. Modify httpRequest’s header list per HTTP. Do not append a given - // header if httpRequest’s header list contains that header’s name. - // TODO: https://github.com/whatwg/fetch/issues/1285#issuecomment-896560129 - if (!httpRequest.headersList.contains('accept-encoding', true)) { - if (urlHasHttpsScheme(requestCurrentURL(httpRequest))) { - httpRequest.headersList.append('accept-encoding', 'br, gzip, deflate', true) - } else { - httpRequest.headersList.append('accept-encoding', 'gzip, deflate', true) - } - } + // 8. If the code point at position within input is + // U+0022 ("), then: + if (input[position.position] === '"') { + // 1. Set parameterValue to the result of collecting + // an HTTP quoted string from input, given position + // and the extract-value flag. + parameterValue = collectAnHTTPQuotedString(input, position, true) - httpRequest.headersList.delete('host', true) + // 2. Collect a sequence of code points that are not + // U+003B (;) from input, given position. + collectASequenceOfCodePointsFast( + ';', + input, + position + ) - // 21. If includeCredentials is true, then: - if (includeCredentials) { - // 1. If the user agent is not configured to block cookies for httpRequest - // (see section 7 of [COOKIES]), then: - // TODO: credentials + // 9. Otherwise: + } else { + // 1. Set parameterValue to the result of collecting + // a sequence of code points that are not U+003B (;) + // from input, given position. + parameterValue = collectASequenceOfCodePointsFast( + ';', + input, + position + ) - // 2. If httpRequest’s header list does not contain `Authorization`, then: - if (!httpRequest.headersList.contains('authorization', true)) { - // 1. Let authorizationValue be null. - let authorizationValue = null + // 2. Remove any trailing HTTP whitespace from parameterValue. + parameterValue = removeHTTPWhitespace(parameterValue, false, true) - // 2. If there’s an authentication entry for httpRequest and either - // httpRequest’s use-URL-credentials flag is unset or httpRequest’s - // current URL does not include credentials, then set - // authorizationValue to authentication entry. - if (hasAuthenticationEntry(httpRequest) && ( - httpRequest.useURLCredentials === undefined || !includesCredentials(requestCurrentURL(httpRequest)) - )) { - // TODO - } else if (includesCredentials(requestCurrentURL(httpRequest)) && isAuthenticationFetch) { - // 3. Otherwise, if httpRequest’s current URL does include credentials - // and isAuthenticationFetch is true, set authorizationValue to - // httpRequest’s current URL, converted to an `Authorization` value - const { username, password } = requestCurrentURL(httpRequest) - authorizationValue = `Basic ${Buffer.from(`${username}:${password}`).toString('base64')}` + // 3. If parameterValue is the empty string, then continue. + if (parameterValue.length === 0) { + continue } + } - // 4. If authorizationValue is non-null, then append (`Authorization`, - // authorizationValue) to httpRequest’s header list. - if (authorizationValue !== null) { - httpRequest.headersList.append('Authorization', authorizationValue, false) - } + // 10. If all of the following are true + // - parameterName is not the empty string + // - parameterName solely contains HTTP token code points + // - parameterValue solely contains HTTP quoted-string token code points + // - mimeType’s parameters[parameterName] does not exist + // then set mimeType’s parameters[parameterName] to parameterValue. + if ( + parameterName.length !== 0 && + HTTP_TOKEN_CODEPOINTS.test(parameterName) && + (parameterValue.length === 0 || HTTP_QUOTED_STRING_TOKENS.test(parameterValue)) && + !mimeType.parameters.has(parameterName) + ) { + mimeType.parameters.set(parameterName, parameterValue) } } - // 21. If there’s a proxy-authentication entry, use it as appropriate. - // TODO: proxy-authentication - - // 22. Set httpCache to the result of determining the HTTP cache - // partition, given httpRequest. - // TODO: cache + // 12. Return mimeType. + return mimeType +} - // 23. If httpCache is null, then set httpRequest’s cache mode to - // "no-store". - if (httpCache == null) { - httpRequest.cache = 'no-store' - } +// https://fetch.spec.whatwg.org/#collect-an-http-quoted-string +// tests: https://fetch.spec.whatwg.org/#example-http-quoted-string +/** + * @param {string} input + * @param {{ position: number }} position + * @param {boolean} [extractValue=false] + */ +function collectAnHTTPQuotedString (input, position, extractValue = false) { + // 1. Let positionStart be position. + const positionStart = position.position - // 24. If httpRequest’s cache mode is neither "no-store" nor "reload", - // then: - if (httpRequest.cache !== 'no-store' && httpRequest.cache !== 'reload') { - // TODO: cache - } + // 2. Let value be the empty string. + let value = '' - // 9. If aborted, then return the appropriate network error for fetchParams. - // TODO + // 3. Assert: the code point at position within input + // is U+0022 ("). + assert(input[position.position] === '"') - // 10. If response is null, then: - if (response == null) { - // 1. If httpRequest’s cache mode is "only-if-cached", then return a - // network error. - if (httpRequest.cache === 'only-if-cached') { - return makeNetworkError('only if cached') - } + // 4. Advance position by 1. + position.position++ - // 2. Let forwardResponse be the result of running HTTP-network fetch - // given httpFetchParams, includeCredentials, and isNewConnectionFetch. - const forwardResponse = await httpNetworkFetch( - httpFetchParams, - includeCredentials, - isNewConnectionFetch + // 5. While true: + while (true) { + // 1. Append the result of collecting a sequence of code points + // that are not U+0022 (") or U+005C (\) from input, given + // position, to value. + value += collectASequenceOfCodePoints( + (char) => char !== '"' && char !== '\\', + input, + position ) - // 3. If httpRequest’s method is unsafe and forwardResponse’s status is - // in the range 200 to 399, inclusive, invalidate appropriate stored - // responses in httpCache, as per the "Invalidation" chapter of HTTP - // Caching, and set storedResponse to null. [HTTP-CACHING] - if ( - !safeMethodsSet.has(httpRequest.method) && - forwardResponse.status >= 200 && - forwardResponse.status <= 399 - ) { - // TODO: cache - } - - // 4. If the revalidatingFlag is set and forwardResponse’s status is 304, - // then: - if (revalidatingFlag && forwardResponse.status === 304) { - // TODO: cache + // 2. If position is past the end of input, then break. + if (position.position >= input.length) { + break } - // 5. If response is null, then: - if (response == null) { - // 1. Set response to forwardResponse. - response = forwardResponse + // 3. Let quoteOrBackslash be the code point at position within + // input. + const quoteOrBackslash = input[position.position] - // 2. Store httpRequest and forwardResponse in httpCache, as per the - // "Storing Responses in Caches" chapter of HTTP Caching. [HTTP-CACHING] - // TODO: cache - } - } + // 4. Advance position by 1. + position.position++ - // 11. Set response’s URL list to a clone of httpRequest’s URL list. - response.urlList = [...httpRequest.urlList] + // 5. If quoteOrBackslash is U+005C (\), then: + if (quoteOrBackslash === '\\') { + // 1. If position is past the end of input, then append + // U+005C (\) to value and break. + if (position.position >= input.length) { + value += '\\' + break + } - // 12. If httpRequest’s header list contains `Range`, then set response’s - // range-requested flag. - if (httpRequest.headersList.contains('range', true)) { - response.rangeRequested = true - } + // 2. Append the code point at position within input to value. + value += input[position.position] - // 13. Set response’s request-includes-credentials to includeCredentials. - response.requestIncludesCredentials = includeCredentials + // 3. Advance position by 1. + position.position++ - // 14. If response’s status is 401, httpRequest’s response tainting is not "cors", - // includeCredentials is true, and request’s traversable for user prompts is - // a traversable navigable: - if (response.status === 401 && httpRequest.responseTainting !== 'cors' && includeCredentials && isTraversableNavigable(request.traversableForUserPrompts)) { - // 2. If request’s body is non-null, then: - if (request.body != null) { - // 1. If request’s body’s source is null, then return a network error. - if (request.body.source == null) { - return makeNetworkError('expected non-null body source') - } + // 6. Otherwise: + } else { + // 1. Assert: quoteOrBackslash is U+0022 ("). + assert(quoteOrBackslash === '"') - // 2. Set request’s body to the body of the result of safely extracting - // request’s body’s source. - request.body = safelyExtractBody(request.body.source)[0] + // 2. Break. + break } + } - // 3. If request’s use-URL-credentials flag is unset or isAuthenticationFetch is - // true, then: - if (request.useURLCredentials === undefined || isAuthenticationFetch) { - // 1. If fetchParams is canceled, then return the appropriate network error - // for fetchParams. - if (isCancelled(fetchParams)) { - return makeAppropriateNetworkError(fetchParams) - } + // 6. If the extract-value flag is set, then return value. + if (extractValue) { + return value + } - // 2. Let username and password be the result of prompting the end user for a - // username and password, respectively, in request’s traversable for user prompts. - // TODO + // 7. Return the code points from positionStart to position, + // inclusive, within input. + return input.slice(positionStart, position.position) +} - // 3. Set the username given request’s current URL and username. - // requestCurrentURL(request).username = TODO +/** + * @see https://mimesniff.spec.whatwg.org/#serialize-a-mime-type + */ +function serializeAMimeType (mimeType) { + assert(mimeType !== 'failure') + const { parameters, essence } = mimeType - // 4. Set the password given request’s current URL and password. - // requestCurrentURL(request).password = TODO - } + // 1. Let serialization be the concatenation of mimeType’s + // type, U+002F (/), and mimeType’s subtype. + let serialization = essence - // 4. Set response to the result of running HTTP-network-or-cache fetch given - // fetchParams and true. - fetchParams.controller.connection.destroy() + // 2. For each name → value of mimeType’s parameters: + for (let [name, value] of parameters.entries()) { + // 1. Append U+003B (;) to serialization. + serialization += ';' - response = await httpNetworkOrCacheFetch(fetchParams, true) - } + // 2. Append name to serialization. + serialization += name - // 15. If response’s status is 407, then: - if (response.status === 407) { - // 1. If request’s window is "no-window", then return a network error. - if (request.window === 'no-window') { - return makeNetworkError() - } + // 3. Append U+003D (=) to serialization. + serialization += '=' - // 2. ??? + // 4. If value does not solely contain HTTP token code + // points or value is the empty string, then: + if (!HTTP_TOKEN_CODEPOINTS.test(value)) { + // 1. Precede each occurrence of U+0022 (") or + // U+005C (\) in value with U+005C (\). + value = value.replace(/[\\"]/ug, '\\$&') - // 3. If fetchParams is canceled, then return the appropriate network error for fetchParams. - if (isCancelled(fetchParams)) { - return makeAppropriateNetworkError(fetchParams) - } + // 2. Prepend U+0022 (") to value. + value = '"' + value - // 4. Prompt the end user as appropriate in request’s window and store - // the result as a proxy-authentication entry. [HTTP-AUTH] - // TODO: Invoke some kind of callback? + // 3. Append U+0022 (") to value. + value += '"' + } - // 5. Set response to the result of running HTTP-network-or-cache fetch given - // fetchParams. - // TODO - return makeNetworkError('proxy authentication required') + // 5. Append value to serialization. + serialization += value } - // 16. If all of the following are true - if ( - // response’s status is 421 - response.status === 421 && - // isNewConnectionFetch is false - !isNewConnectionFetch && - // request’s body is null, or request’s body is non-null and request’s body’s source is non-null - (request.body == null || request.body.source != null) - ) { - // then: + // 3. Return serialization. + return serialization +} - // 1. If fetchParams is canceled, then return the appropriate network error for fetchParams. - if (isCancelled(fetchParams)) { - return makeAppropriateNetworkError(fetchParams) - } +/** + * @see https://fetch.spec.whatwg.org/#http-whitespace + * @param {number} char + */ +function isHTTPWhiteSpace (char) { + // "\r\n\t " + return char === 0x00d || char === 0x00a || char === 0x009 || char === 0x020 +} - // 2. Set response to the result of running HTTP-network-or-cache - // fetch given fetchParams, isAuthenticationFetch, and true. +/** + * @see https://fetch.spec.whatwg.org/#http-whitespace + * @param {string} str + * @param {boolean} [leading=true] + * @param {boolean} [trailing=true] + */ +function removeHTTPWhitespace (str, leading = true, trailing = true) { + return removeChars(str, leading, trailing, isHTTPWhiteSpace) +} - // TODO (spec): The spec doesn't specify this but we need to cancel - // the active response before we can start a new one. - // https://github.com/whatwg/fetch/issues/1293 - fetchParams.controller.connection.destroy() +/** + * @see https://mimesniff.spec.whatwg.org/#minimize-a-supported-mime-type + * @param {Exclude, 'failure'>} mimeType + */ +function minimizeSupportedMimeType (mimeType) { + switch (mimeType.essence) { + case 'application/ecmascript': + case 'application/javascript': + case 'application/x-ecmascript': + case 'application/x-javascript': + case 'text/ecmascript': + case 'text/javascript': + case 'text/javascript1.0': + case 'text/javascript1.1': + case 'text/javascript1.2': + case 'text/javascript1.3': + case 'text/javascript1.4': + case 'text/javascript1.5': + case 'text/jscript': + case 'text/livescript': + case 'text/x-ecmascript': + case 'text/x-javascript': + // 1. If mimeType is a JavaScript MIME type, then return "text/javascript". + return 'text/javascript' + case 'application/json': + case 'text/json': + // 2. If mimeType is a JSON MIME type, then return "application/json". + return 'application/json' + case 'image/svg+xml': + // 3. If mimeType’s essence is "image/svg+xml", then return "image/svg+xml". + return 'image/svg+xml' + case 'text/xml': + case 'application/xml': + // 4. If mimeType is an XML MIME type, then return "application/xml". + return 'application/xml' + } - response = await httpNetworkOrCacheFetch( - fetchParams, - isAuthenticationFetch, - true - ) + // 2. If mimeType is a JSON MIME type, then return "application/json". + if (mimeType.subtype.endsWith('+json')) { + return 'application/json' } - // 17. If isAuthenticationFetch is true, then create an authentication entry - if (isAuthenticationFetch) { - // TODO + // 4. If mimeType is an XML MIME type, then return "application/xml". + if (mimeType.subtype.endsWith('+xml')) { + return 'application/xml' } - // 18. Return response. - return response -} + // 5. If mimeType is supported by the user agent, then return mimeType’s essence. + // Technically, node doesn't support any mimetypes. -// https://fetch.spec.whatwg.org/#http-network-fetch -async function httpNetworkFetch ( - fetchParams, - includeCredentials = false, - forceNewConnection = false -) { - assert(!fetchParams.controller.connection || fetchParams.controller.connection.destroyed) + // 6. Return the empty string. + return '' +} - fetchParams.controller.connection = { - abort: null, - destroyed: false, - destroy (err, abort = true) { - if (!this.destroyed) { - this.destroyed = true - if (abort) { - this.abort?.(err ?? new DOMException('The operation was aborted.', 'AbortError')) - } - } - } - } +module.exports = { + dataURLProcessor, + URLSerializer, + stringPercentDecode, + parseMIMEType, + collectAnHTTPQuotedString, + serializeAMimeType, + removeHTTPWhitespace, + minimizeSupportedMimeType, + HTTP_TOKEN_CODEPOINTS +} - // 1. Let request be fetchParams’s request. - const request = fetchParams.request - // 2. Let response be null. - let response = null +/***/ }), - // 3. Let timingInfo be fetchParams’s timing info. - const timingInfo = fetchParams.timingInfo +/***/ 1682: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - // 4. Let httpCache be the result of determining the HTTP cache partition, - // given request. - // TODO: cache - const httpCache = null - // 5. If httpCache is null, then set request’s cache mode to "no-store". - if (httpCache == null) { - request.cache = 'no-store' - } - // 6. Let networkPartitionKey be the result of determining the network - // partition key given request. - // TODO +const { bufferToLowerCasedHeaderName } = __nccwpck_require__(2550) +const { HTTP_TOKEN_CODEPOINTS } = __nccwpck_require__(1410) +const { makeEntry } = __nccwpck_require__(3756) +const { webidl } = __nccwpck_require__(909) +const assert = __nccwpck_require__(4589) +const { isomorphicDecode } = __nccwpck_require__(5074) +const { utf8DecodeBytes } = __nccwpck_require__(6546) - // 7. Let newConnection be "yes" if forceNewConnection is true; otherwise - // "no". - const newConnection = forceNewConnection ? 'yes' : 'no' // eslint-disable-line no-unused-vars +const dd = Buffer.from('--') +const decoder = new TextDecoder() - // 8. Switch on request’s mode: - if (request.mode === 'websocket') { - // Let connection be the result of obtaining a WebSocket connection, - // given request’s current URL. - // TODO - } else { - // Let connection be the result of obtaining a connection, given - // networkPartitionKey, request’s current URL’s origin, - // includeCredentials, and forceNewConnection. - // TODO +/** + * @param {string} chars + */ +function isAsciiString (chars) { + for (let i = 0; i < chars.length; ++i) { + if ((chars.charCodeAt(i) & ~0x7F) !== 0) { + return false + } } + return true +} - // 9. Run these steps, but abort when the ongoing fetch is terminated: +/** + * @see https://andreubotella.github.io/multipart-form-data/#multipart-form-data-boundary + * @param {string} boundary + */ +function validateBoundary (boundary) { + const length = boundary.length - // 1. If connection is failure, then return a network error. + // - its length is greater or equal to 27 and lesser or equal to 70, and + if (length < 27 || length > 70) { + return false + } - // 2. Set timingInfo’s final connection timing info to the result of - // calling clamp and coarsen connection timing info with connection’s - // timing info, timingInfo’s post-redirect start time, and fetchParams’s - // cross-origin isolated capability. + // - it is composed by bytes in the ranges 0x30 to 0x39, 0x41 to 0x5A, or + // 0x61 to 0x7A, inclusive (ASCII alphanumeric), or which are 0x27 ('), + // 0x2D (-) or 0x5F (_). + for (let i = 0; i < length; ++i) { + const cp = boundary.charCodeAt(i) - // 3. If connection is not an HTTP/2 connection, request’s body is non-null, - // and request’s body’s source is null, then append (`Transfer-Encoding`, - // `chunked`) to request’s header list. + if (!( + (cp >= 0x30 && cp <= 0x39) || + (cp >= 0x41 && cp <= 0x5a) || + (cp >= 0x61 && cp <= 0x7a) || + cp === 0x27 || + cp === 0x2d || + cp === 0x5f + )) { + return false + } + } - // 4. Set timingInfo’s final network-request start time to the coarsened - // shared current time given fetchParams’s cross-origin isolated - // capability. + return true +} - // 5. Set response to the result of making an HTTP request over connection - // using request with the following caveats: +/** + * @see https://andreubotella.github.io/multipart-form-data/#multipart-form-data-parser + * @param {Buffer} input + * @param {ReturnType} mimeType + */ +function multipartFormDataParser (input, mimeType) { + // 1. Assert: mimeType’s essence is "multipart/form-data". + assert(mimeType !== 'failure' && mimeType.essence === 'multipart/form-data') - // - Follow the relevant requirements from HTTP. [HTTP] [HTTP-SEMANTICS] - // [HTTP-COND] [HTTP-CACHING] [HTTP-AUTH] + const boundaryString = mimeType.parameters.get('boundary') - // - If request’s body is non-null, and request’s body’s source is null, - // then the user agent may have a buffer of up to 64 kibibytes and store - // a part of request’s body in that buffer. If the user agent reads from - // request’s body beyond that buffer’s size and the user agent needs to - // resend request, then instead return a network error. + // 2. If mimeType’s parameters["boundary"] does not exist, return failure. + // Otherwise, let boundary be the result of UTF-8 decoding mimeType’s + // parameters["boundary"]. + if (boundaryString === undefined) { + throw parsingError('missing boundary in content-type header') + } - // - Set timingInfo’s final network-response start time to the coarsened - // shared current time given fetchParams’s cross-origin isolated capability, - // immediately after the user agent’s HTTP parser receives the first byte - // of the response (e.g., frame header bytes for HTTP/2 or response status - // line for HTTP/1.x). + const boundary = Buffer.from(`--${boundaryString}`, 'utf8') - // - Wait until all the headers are transmitted. + // 3. Let entry list be an empty entry list. + const entryList = [] - // - Any responses whose status is in the range 100 to 199, inclusive, - // and is not 101, are to be ignored, except for the purposes of setting - // timingInfo’s final network-response start time above. + // 4. Let position be a pointer to a byte in input, initially pointing at + // the first byte. + const position = { position: 0 } - // - If request’s header list contains `Transfer-Encoding`/`chunked` and - // response is transferred via HTTP/1.0 or older, then return a network - // error. + // Note: Per RFC 2046 Section 5.1.1, we must ignore anything before the + // first boundary delimiter line (preamble). Search for the first boundary. + const firstBoundaryIndex = input.indexOf(boundary) - // - If the HTTP request results in a TLS client certificate dialog, then: + if (firstBoundaryIndex === -1) { + throw parsingError('no boundary found in multipart body') + } - // 1. If request’s window is an environment settings object, make the - // dialog available in request’s window. + // Start parsing from the first boundary, ignoring any preamble + position.position = firstBoundaryIndex - // 2. Otherwise, return a network error. + // 5. While true: + while (true) { + // 5.1. If position points to a sequence of bytes starting with 0x2D 0x2D + // (`--`) followed by boundary, advance position by 2 + the length of + // boundary. Otherwise, return failure. + // Note: boundary is padded with 2 dashes already, no need to add 2. + if (input.subarray(position.position, position.position + boundary.length).equals(boundary)) { + position.position += boundary.length + } else { + throw parsingError('expected a value starting with -- and the boundary') + } - // To transmit request’s body body, run these steps: - let requestBody = null - // 1. If body is null and fetchParams’s process request end-of-body is - // non-null, then queue a fetch task given fetchParams’s process request - // end-of-body and fetchParams’s task destination. - if (request.body == null && fetchParams.processRequestEndOfBody) { - queueMicrotask(() => fetchParams.processRequestEndOfBody()) - } else if (request.body != null) { - // 2. Otherwise, if body is non-null: + // 5.2. If position points to the sequence of bytes 0x2D 0x2D 0x0D 0x0A + // (`--` followed by CR LF) followed by the end of input, return entry list. + // Note: Per RFC 2046 Section 5.1.1, we must ignore anything after the + // final boundary delimiter (epilogue). Check for -- or --CRLF and return + // regardless of what follows. + if (bufferStartsWith(input, dd, position)) { + // Found closing boundary delimiter (--), ignore any epilogue + return entryList + } - // 1. Let processBodyChunk given bytes be these steps: - const processBodyChunk = async function * (bytes) { - // 1. If the ongoing fetch is terminated, then abort these steps. - if (isCancelled(fetchParams)) { - return - } + // 5.3. If position does not point to a sequence of bytes starting with 0x0D + // 0x0A (CR LF), return failure. + if (input[position.position] !== 0x0d || input[position.position + 1] !== 0x0a) { + throw parsingError('expected CRLF') + } - // 2. Run this step in parallel: transmit bytes. - yield bytes + // 5.4. Advance position by 2. (This skips past the newline.) + position.position += 2 - // 3. If fetchParams’s process request body is non-null, then run - // fetchParams’s process request body given bytes’s length. - fetchParams.processRequestBodyChunkLength?.(bytes.byteLength) - } + // 5.5. Let name, filename and contentType be the result of parsing + // multipart/form-data headers on input and position, if the result + // is not failure. Otherwise, return failure. + const result = parseMultipartFormDataHeaders(input, position) - // 2. Let processEndOfBody be these steps: - const processEndOfBody = () => { - // 1. If fetchParams is canceled, then abort these steps. - if (isCancelled(fetchParams)) { - return - } + let { name, filename, contentType, encoding } = result - // 2. If fetchParams’s process request end-of-body is non-null, - // then run fetchParams’s process request end-of-body. - if (fetchParams.processRequestEndOfBody) { - fetchParams.processRequestEndOfBody() - } - } + // 5.6. Advance position by 2. (This skips past the empty line that marks + // the end of the headers.) + position.position += 2 - // 3. Let processBodyError given e be these steps: - const processBodyError = (e) => { - // 1. If fetchParams is canceled, then abort these steps. - if (isCancelled(fetchParams)) { - return - } + // 5.7. Let body be the empty byte sequence. + let body - // 2. If e is an "AbortError" DOMException, then abort fetchParams’s controller. - if (e.name === 'AbortError') { - fetchParams.controller.abort() - } else { - fetchParams.controller.terminate(e) - } - } + // 5.8. Body loop: While position is not past the end of input: + // TODO: the steps here are completely wrong + { + const boundaryIndex = input.indexOf(boundary.subarray(2), position.position) - // 4. Incrementally read request’s body given processBodyChunk, processEndOfBody, - // processBodyError, and fetchParams’s task destination. - requestBody = (async function * () { - try { - for await (const bytes of request.body.stream) { - yield * processBodyChunk(bytes) - } - processEndOfBody() - } catch (err) { - processBodyError(err) + if (boundaryIndex === -1) { + throw parsingError('expected boundary after body') } - })() - } - try { - // socket is only provided for websockets - const { body, status, statusText, headersList, socket } = await dispatch({ body: requestBody }) + body = input.subarray(position.position, boundaryIndex - 4) - if (socket) { - response = makeResponse({ status, statusText, headersList, socket }) - } else { - const iterator = body[Symbol.asyncIterator]() - fetchParams.controller.next = () => iterator.next() + position.position += body.length - response = makeResponse({ status, statusText, headersList }) + // Note: position must be advanced by the body's length before being + // decoded, otherwise the parsing will fail. + if (encoding === 'base64') { + body = Buffer.from(body.toString(), 'base64') + } } - } catch (err) { - // 10. If aborted, then: - if (err.name === 'AbortError') { - // 1. If connection uses HTTP/2, then transmit an RST_STREAM frame. - fetchParams.controller.connection.destroy() - // 2. Return the appropriate network error for fetchParams. - return makeAppropriateNetworkError(fetchParams, err) + // 5.9. If position does not point to a sequence of bytes starting with + // 0x0D 0x0A (CR LF), return failure. Otherwise, advance position by 2. + if (input[position.position] !== 0x0d || input[position.position + 1] !== 0x0a) { + throw parsingError('expected CRLF') + } else { + position.position += 2 } - return makeNetworkError(err) - } + // 5.10. If filename is not null: + let value - // 11. Let pullAlgorithm be an action that resumes the ongoing fetch - // if it is suspended. - const pullAlgorithm = () => { - return fetchParams.controller.resume() - } + if (filename !== null) { + // 5.10.1. If contentType is null, set contentType to "text/plain". + contentType ??= 'text/plain' - // 12. Let cancelAlgorithm be an algorithm that aborts fetchParams’s - // controller with reason, given reason. - const cancelAlgorithm = (reason) => { - // If the aborted fetch was already terminated, then we do not - // need to do anything. - if (!isCancelled(fetchParams)) { - fetchParams.controller.abort(reason) - } - } + // 5.10.2. If contentType is not an ASCII string, set contentType to the empty string. - // 13. Let highWaterMark be a non-negative, non-NaN number, chosen by - // the user agent. - // TODO + // Note: `buffer.isAscii` can be used at zero-cost, but converting a string to a buffer is a high overhead. + // Content-Type is a relatively small string, so it is faster to use `String#charCodeAt`. + if (!isAsciiString(contentType)) { + contentType = '' + } - // 14. Let sizeAlgorithm be an algorithm that accepts a chunk object - // and returns a non-negative, non-NaN, non-infinite number, chosen by the user agent. - // TODO + // 5.10.3. Let value be a new File object with name filename, type contentType, and body body. + value = new File([body], filename, { type: contentType }) + } else { + // 5.11. Otherwise: - // 15. Let stream be a new ReadableStream. - // 16. Set up stream with byte reading support with pullAlgorithm set to pullAlgorithm, - // cancelAlgorithm set to cancelAlgorithm. - const stream = new ReadableStream( - { - start (controller) { - fetchParams.controller.controller = controller - }, - pull: pullAlgorithm, - cancel: cancelAlgorithm, - type: 'bytes' + // 5.11.1. Let value be the UTF-8 decoding without BOM of body. + value = utf8DecodeBytes(Buffer.from(body)) } - ) - - // 17. Run these steps, but abort when the ongoing fetch is terminated: - // 1. Set response’s body to a new body whose stream is stream. - response.body = { stream, source: null, length: null } + // 5.12. Assert: name is a scalar value string and value is either a scalar value string or a File object. + assert(webidl.is.USVString(name)) + assert((typeof value === 'string' && webidl.is.USVString(value)) || webidl.is.File(value)) - // 2. If response is not a network error and request’s cache mode is - // not "no-store", then update response in httpCache for request. - // TODO + // 5.13. Create an entry with name and value, and append it to entry list. + entryList.push(makeEntry(name, value, filename)) + } +} - // 3. If includeCredentials is true and the user agent is not configured - // to block cookies for request (see section 7 of [COOKIES]), then run the - // "set-cookie-string" parsing algorithm (see section 5.2 of [COOKIES]) on - // the value of each header whose name is a byte-case-insensitive match for - // `Set-Cookie` in response’s header list, if any, and request’s current URL. - // TODO +/** + * Parses content-disposition attributes (e.g., name="value" or filename*=utf-8''encoded) + * @param {Buffer} input + * @param {{ position: number }} position + * @returns {{ name: string, value: string }} + */ +function parseContentDispositionAttribute (input, position) { + // Skip leading semicolon and whitespace + if (input[position.position] === 0x3b /* ; */) { + position.position++ + } - // 18. If aborted, then: - // TODO + // Skip whitespace + collectASequenceOfBytes( + (char) => char === 0x20 || char === 0x09, + input, + position + ) - // 19. Run these steps in parallel: + // Collect attribute name (token characters) + const attributeName = collectASequenceOfBytes( + (char) => isToken(char) && char !== 0x3d && char !== 0x2a, // not = or * + input, + position + ) - // 1. Run these steps, but abort when fetchParams is canceled: - if (!fetchParams.controller.resume) { - fetchParams.controller.on('terminated', onAborted) + if (attributeName.length === 0) { + return null } - fetchParams.controller.resume = async () => { - // 1. While true - while (true) { - // 1-3. See onData... - - // 4. Set bytes to the result of handling content codings given - // codings and bytes. - let bytes - let isFailure - try { - const { done, value } = await fetchParams.controller.next() + const attrNameStr = attributeName.toString('ascii').toLowerCase() - if (isAborted(fetchParams)) { - break - } + // Check for extended notation (attribute*) + const isExtended = input[position.position] === 0x2a /* * */ + if (isExtended) { + position.position++ // skip * + } - bytes = done ? undefined : value - } catch (err) { - if (fetchParams.controller.ended && !timingInfo.encodedBodySize) { - // zlib doesn't like empty streams. - bytes = undefined - } else { - bytes = err + // Expect = sign + if (input[position.position] !== 0x3d /* = */) { + return null + } + position.position++ // skip = - // err may be propagated from the result of calling readablestream.cancel, - // which might not be an error. https://github.com/nodejs/undici/issues/2009 - isFailure = true - } - } + // Skip whitespace + collectASequenceOfBytes( + (char) => char === 0x20 || char === 0x09, + input, + position + ) - if (bytes === undefined) { - // 2. Otherwise, if the bytes transmission for response’s message - // body is done normally and stream is readable, then close - // stream, finalize response for fetchParams and response, and - // abort these in-parallel steps. - readableStreamClose(fetchParams.controller.controller) + let value - finalizeResponse(fetchParams, response) + if (isExtended) { + // Extended attribute format: charset'language'encoded-value + const headerValue = collectASequenceOfBytes( + (char) => char !== 0x20 && char !== 0x0d && char !== 0x0a && char !== 0x3b, // not space, CRLF, or ; + input, + position + ) - return - } + // Check for utf-8'' prefix (case insensitive) + if ( + (headerValue[0] !== 0x75 && headerValue[0] !== 0x55) || // u or U + (headerValue[1] !== 0x74 && headerValue[1] !== 0x54) || // t or T + (headerValue[2] !== 0x66 && headerValue[2] !== 0x46) || // f or F + headerValue[3] !== 0x2d || // - + headerValue[4] !== 0x38 // 8 + ) { + throw parsingError('unknown encoding, expected utf-8\'\'') + } - // 5. Increase timingInfo’s decoded body size by bytes’s length. - timingInfo.decodedBodySize += bytes?.byteLength ?? 0 + // Skip utf-8'' and decode the rest + value = decodeURIComponent(decoder.decode(headerValue.subarray(7))) + } else if (input[position.position] === 0x22 /* " */) { + // Quoted string + position.position++ // skip opening quote - // 6. If bytes is failure, then terminate fetchParams’s controller. - if (isFailure) { - fetchParams.controller.terminate(bytes) - return - } + const quotedValue = collectASequenceOfBytes( + (char) => char !== 0x0a && char !== 0x0d && char !== 0x22, // not LF, CR, or " + input, + position + ) - // 7. Enqueue a Uint8Array wrapping an ArrayBuffer containing bytes - // into stream. - const buffer = new Uint8Array(bytes) - if (buffer.byteLength) { - fetchParams.controller.controller.enqueue(buffer) - } + if (input[position.position] !== 0x22) { + throw parsingError('Closing quote not found') + } + position.position++ // skip closing quote - // 8. If stream is errored, then terminate the ongoing fetch. - if (isErrored(stream)) { - fetchParams.controller.terminate() - return - } + value = decoder.decode(quotedValue) + .replace(/%0A/ig, '\n') + .replace(/%0D/ig, '\r') + .replace(/%22/g, '"') + } else { + // Token value (no quotes) + const tokenValue = collectASequenceOfBytes( + (char) => isToken(char) && char !== 0x3b, // not ; + input, + position + ) - // 9. If stream doesn’t need more data ask the user agent to suspend - // the ongoing fetch. - if (fetchParams.controller.controller.desiredSize <= 0) { - return - } - } + value = decoder.decode(tokenValue) } - // 2. If aborted, then: - function onAborted (reason) { - // 2. If fetchParams is aborted, then: - if (isAborted(fetchParams)) { - // 1. Set response’s aborted flag. - response.aborted = true + return { name: attrNameStr, value } +} - // 2. If stream is readable, then error stream with the result of - // deserialize a serialized abort reason given fetchParams’s - // controller’s serialized abort reason and an - // implementation-defined realm. - if (isReadable(stream)) { - fetchParams.controller.controller.error( - fetchParams.controller.serializedAbortReason - ) - } - } else { - // 3. Otherwise, if stream is readable, error stream with a TypeError. - if (isReadable(stream)) { - fetchParams.controller.controller.error(new TypeError('terminated', { - cause: isErrorLike(reason) ? reason : undefined - })) +/** + * @see https://andreubotella.github.io/multipart-form-data/#parse-multipart-form-data-headers + * @param {Buffer} input + * @param {{ position: number }} position + */ +function parseMultipartFormDataHeaders (input, position) { + // 1. Let name, filename and contentType be null. + let name = null + let filename = null + let contentType = null + let encoding = null + + // 2. While true: + while (true) { + // 2.1. If position points to a sequence of bytes starting with 0x0D 0x0A (CR LF): + if (input[position.position] === 0x0d && input[position.position + 1] === 0x0a) { + // 2.1.1. If name is null, return failure. + if (name === null) { + throw parsingError('header name is null') } + + // 2.1.2. Return name, filename and contentType. + return { name, filename, contentType, encoding } } - // 4. If connection uses HTTP/2, then transmit an RST_STREAM frame. - // 5. Otherwise, the user agent should close connection unless it would be bad for performance to do so. - fetchParams.controller.connection.destroy() - } + // 2.2. Let header name be the result of collecting a sequence of bytes that are + // not 0x0A (LF), 0x0D (CR) or 0x3A (:), given position. + let headerName = collectASequenceOfBytes( + (char) => char !== 0x0a && char !== 0x0d && char !== 0x3a, + input, + position + ) - // 20. Return response. - return response + // 2.3. Remove any HTTP tab or space bytes from the start or end of header name. + headerName = removeChars(headerName, true, true, (char) => char === 0x9 || char === 0x20) - function dispatch ({ body }) { - const url = requestCurrentURL(request) - /** @type {import('../../..').Agent} */ - const agent = fetchParams.controller.dispatcher + // 2.4. If header name does not match the field-name token production, return failure. + if (!HTTP_TOKEN_CODEPOINTS.test(headerName.toString())) { + throw parsingError('header name does not match the field-name token production') + } - return new Promise((resolve, reject) => agent.dispatch( - { - path: url.pathname + url.search, - origin: url.origin, - method: request.method, - body: agent.isMockActive ? request.body && (request.body.source || request.body.stream) : body, - headers: request.headersList.entries, - maxRedirections: 0, - upgrade: request.mode === 'websocket' ? 'websocket' : undefined - }, - { - body: null, - abort: null, + // 2.5. If the byte at position is not 0x3A (:), return failure. + if (input[position.position] !== 0x3a) { + throw parsingError('expected :') + } - onConnect (abort) { - // TODO (fix): Do we need connection here? - const { connection } = fetchParams.controller + // 2.6. Advance position by 1. + position.position++ - // Set timingInfo’s final connection timing info to the result of calling clamp and coarsen - // connection timing info with connection’s timing info, timingInfo’s post-redirect start - // time, and fetchParams’s cross-origin isolated capability. - // TODO: implement connection timing - timingInfo.finalConnectionTimingInfo = clampAndCoarsenConnectionTimingInfo(undefined, timingInfo.postRedirectStartTime, fetchParams.crossOriginIsolatedCapability) + // 2.7. Collect a sequence of bytes that are HTTP tab or space bytes given position. + // (Do nothing with those bytes.) + collectASequenceOfBytes( + (char) => char === 0x20 || char === 0x09, + input, + position + ) - if (connection.destroyed) { - abort(new DOMException('The operation was aborted.', 'AbortError')) - } else { - fetchParams.controller.on('terminated', abort) - this.abort = connection.abort = abort - } + // 2.8. Byte-lowercase header name and switch on the result: + switch (bufferToLowerCasedHeaderName(headerName)) { + case 'content-disposition': { + name = filename = null - // Set timingInfo’s final network-request start time to the coarsened shared current time given - // fetchParams’s cross-origin isolated capability. - timingInfo.finalNetworkRequestStartTime = coarsenedSharedCurrentTime(fetchParams.crossOriginIsolatedCapability) - }, + // Collect the disposition type (should be "form-data") + const dispositionType = collectASequenceOfBytes( + (char) => isToken(char), + input, + position + ) - onResponseStarted () { - // Set timingInfo’s final network-response start time to the coarsened shared current - // time given fetchParams’s cross-origin isolated capability, immediately after the - // user agent’s HTTP parser receives the first byte of the response (e.g., frame header - // bytes for HTTP/2 or response status line for HTTP/1.x). - timingInfo.finalNetworkResponseStartTime = coarsenedSharedCurrentTime(fetchParams.crossOriginIsolatedCapability) - }, + if (dispositionType.toString('ascii').toLowerCase() !== 'form-data') { + throw parsingError('expected form-data for content-disposition header') + } - onHeaders (status, rawHeaders, resume, statusText) { - if (status < 200) { - return false - } + // Parse attributes recursively until CRLF + while ( + position.position < input.length && + input[position.position] !== 0x0d && + input[position.position + 1] !== 0x0a + ) { + const attribute = parseContentDispositionAttribute(input, position) - const headersList = new HeadersList() + if (!attribute) { + break + } - for (let i = 0; i < rawHeaders.length; i += 2) { - headersList.append(bufferToLowerCasedHeaderName(rawHeaders[i]), rawHeaders[i + 1].toString('latin1'), true) + if (attribute.name === 'name') { + name = attribute.value + } else if (attribute.name === 'filename') { + filename = attribute.value } - const location = headersList.get('location', true) + } - this.body = new Readable({ read: resume }) + if (name === null) { + throw parsingError('name attribute is required in content-disposition header') + } - const willFollow = location && request.redirect === 'follow' && - redirectStatusSet.has(status) + break + } + case 'content-type': { + // 1. Let header value be the result of collecting a sequence of bytes that are + // not 0x0A (LF) or 0x0D (CR), given position. + let headerValue = collectASequenceOfBytes( + (char) => char !== 0x0a && char !== 0x0d, + input, + position + ) - const decoders = [] + // 2. Remove any HTTP tab or space bytes from the end of header value. + headerValue = removeChars(headerValue, false, true, (char) => char === 0x9 || char === 0x20) - // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding - if (request.method !== 'HEAD' && request.method !== 'CONNECT' && !nullBodyStatus.includes(status) && !willFollow) { - // https://www.rfc-editor.org/rfc/rfc7231#section-3.1.2.1 - const contentEncoding = headersList.get('content-encoding', true) - // "All content-coding values are case-insensitive..." - /** @type {string[]} */ - const codings = contentEncoding ? contentEncoding.toLowerCase().split(',') : [] - - // Limit the number of content-encodings to prevent resource exhaustion. - // CVE fix similar to urllib3 (GHSA-gm62-xv2j-4w53) and curl (CVE-2022-32206). - const maxContentEncodings = 5 - if (codings.length > maxContentEncodings) { - reject(new Error(`too many content-encodings in response: ${codings.length}, maximum allowed is ${maxContentEncodings}`)) - return true - } - - for (let i = codings.length - 1; i >= 0; --i) { - const coding = codings[i].trim() - // https://www.rfc-editor.org/rfc/rfc9112.html#section-7.2 - if (coding === 'x-gzip' || coding === 'gzip') { - decoders.push(zlib.createGunzip({ - // Be less strict when decoding compressed responses, since sometimes - // servers send slightly invalid responses that are still accepted - // by common browsers. - // Always using Z_SYNC_FLUSH is what cURL does. - flush: zlib.constants.Z_SYNC_FLUSH, - finishFlush: zlib.constants.Z_SYNC_FLUSH - })) - } else if (coding === 'deflate') { - decoders.push(createInflate({ - flush: zlib.constants.Z_SYNC_FLUSH, - finishFlush: zlib.constants.Z_SYNC_FLUSH - })) - } else if (coding === 'br') { - decoders.push(zlib.createBrotliDecompress({ - flush: zlib.constants.BROTLI_OPERATION_FLUSH, - finishFlush: zlib.constants.BROTLI_OPERATION_FLUSH - })) - } else if (coding === 'zstd' && hasZstd) { - decoders.push(zlib.createZstdDecompress({ - flush: zlib.constants.ZSTD_e_continue, - finishFlush: zlib.constants.ZSTD_e_end - })) - } else { - decoders.length = 0 - break - } - } - } - - const onError = this.onError.bind(this) - - resolve({ - status, - statusText, - headersList, - body: decoders.length - ? pipeline(this.body, ...decoders, (err) => { - if (err) { - this.onError(err) - } - }).on('error', onError) - : this.body.on('error', onError) - }) - - return true - }, + // 3. Set contentType to the isomorphic decoding of header value. + contentType = isomorphicDecode(headerValue) - onData (chunk) { - if (fetchParams.controller.dump) { - return - } + break + } + case 'content-transfer-encoding': { + let headerValue = collectASequenceOfBytes( + (char) => char !== 0x0a && char !== 0x0d, + input, + position + ) - // 1. If one or more bytes have been transmitted from response’s - // message body, then: + headerValue = removeChars(headerValue, false, true, (char) => char === 0x9 || char === 0x20) - // 1. Let bytes be the transmitted bytes. - const bytes = chunk + encoding = isomorphicDecode(headerValue) - // 2. Let codings be the result of extracting header list values - // given `Content-Encoding` and response’s header list. - // See pullAlgorithm. + break + } + default: { + // Collect a sequence of bytes that are not 0x0A (LF) or 0x0D (CR), given position. + // (Do nothing with those bytes.) + collectASequenceOfBytes( + (char) => char !== 0x0a && char !== 0x0d, + input, + position + ) + } + } - // 3. Increase timingInfo’s encoded body size by bytes’s length. - timingInfo.encodedBodySize += bytes.byteLength + // 2.9. If position does not point to a sequence of bytes starting with 0x0D 0x0A + // (CR LF), return failure. Otherwise, advance position by 2 (past the newline). + if (input[position.position] !== 0x0d && input[position.position + 1] !== 0x0a) { + throw parsingError('expected CRLF') + } else { + position.position += 2 + } + } +} - // 4. See pullAlgorithm... +/** + * @param {(char: number) => boolean} condition + * @param {Buffer} input + * @param {{ position: number }} position + */ +function collectASequenceOfBytes (condition, input, position) { + let start = position.position - return this.body.push(bytes) - }, + while (start < input.length && condition(input[start])) { + ++start + } - onComplete () { - if (this.abort) { - fetchParams.controller.off('terminated', this.abort) - } + return input.subarray(position.position, (position.position = start)) +} - fetchParams.controller.ended = true +/** + * @param {Buffer} buf + * @param {boolean} leading + * @param {boolean} trailing + * @param {(charCode: number) => boolean} predicate + * @returns {Buffer} + */ +function removeChars (buf, leading, trailing, predicate) { + let lead = 0 + let trail = buf.length - 1 - this.body.push(null) - }, + if (leading) { + while (lead < buf.length && predicate(buf[lead])) lead++ + } - onError (error) { - if (this.abort) { - fetchParams.controller.off('terminated', this.abort) - } + if (trailing) { + while (trail > 0 && predicate(buf[trail])) trail-- + } - this.body?.destroy(error) + return lead === 0 && trail === buf.length - 1 ? buf : buf.subarray(lead, trail + 1) +} - fetchParams.controller.terminate(error) +/** + * Checks if {@param buffer} starts with {@param start} + * @param {Buffer} buffer + * @param {Buffer} start + * @param {{ position: number }} position + */ +function bufferStartsWith (buffer, start, position) { + if (buffer.length < start.length) { + return false + } - reject(error) - }, + for (let i = 0; i < start.length; i++) { + if (start[i] !== buffer[position.position + i]) { + return false + } + } - onUpgrade (status, rawHeaders, socket) { - // We need to support 200 for websocket over h2 as per RFC-8441 - // Absence of session means H1 - if ((socket.session != null && status !== 200) || (socket.session == null && status !== 101)) { - return false - } + return true +} - const headersList = new HeadersList() +function parsingError (cause) { + return new TypeError('Failed to parse body as FormData.', { cause: new TypeError(cause) }) +} - for (let i = 0; i < rawHeaders.length; i += 2) { - headersList.append(bufferToLowerCasedHeaderName(rawHeaders[i]), rawHeaders[i + 1].toString('latin1'), true) - } +/** + * CTL = + * @param {number} char + */ +function isCTL (char) { + return char <= 0x1f || char === 0x7f +} - resolve({ - status, - statusText: STATUS_CODES[status], - headersList, - socket - }) +/** + * tspecials := "(" / ")" / "<" / ">" / "@" / + * "," / ";" / ":" / "\" / <"> + * "/" / "[" / "]" / "?" / "=" + * ; Must be in quoted-string, + * ; to use within parameter values + * @param {number} char + */ +function isTSpecial (char) { + return ( + char === 0x28 || // ( + char === 0x29 || // ) + char === 0x3c || // < + char === 0x3e || // > + char === 0x40 || // @ + char === 0x2c || // , + char === 0x3b || // ; + char === 0x3a || // : + char === 0x5c || // \ + char === 0x22 || // " + char === 0x2f || // / + char === 0x5b || // [ + char === 0x5d || // ] + char === 0x3f || // ? + char === 0x3d // + + ) +} - return true - } - } - )) - } +/** + * token := 1* + * @param {number} char + */ +function isToken (char) { + return ( + char <= 0x7f && // ascii + char !== 0x20 && // space + char !== 0x09 && + !isCTL(char) && + !isTSpecial(char) + ) } module.exports = { - fetch, - Fetch, - fetching, - finalizeAndReportTiming + multipartFormDataParser, + validateBoundary } /***/ }), -/***/ 8140: +/***/ 3756: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -/* globals AbortController */ - -const { extractBody, mixinBody, cloneBody, bodyUnusable } = __nccwpck_require__(2921) -const { Headers, fill: fillHeaders, HeadersList, setHeadersGuard, getHeadersGuard, setHeadersList, getHeadersList } = __nccwpck_require__(8447) -const util = __nccwpck_require__(983) +const { iteratorMixin } = __nccwpck_require__(3106) +const { kEnumerableProperty } = __nccwpck_require__(2550) +const { webidl } = __nccwpck_require__(909) const nodeUtil = __nccwpck_require__(7975) -const { - isValidHTTPToken, - sameOrigin, - environmentSettingsObject -} = __nccwpck_require__(8913) -const { - forbiddenMethodsSet, - corsSafeListedMethodsSet, - referrerPolicy, - requestRedirect, - requestMode, - requestCredentials, - requestCache, - requestDuplex -} = __nccwpck_require__(112) -const { kEnumerableProperty, normalizedMethodRecordsBase, normalizedMethodRecords } = util -const { webidl } = __nccwpck_require__(2318) -const { URLSerializer } = __nccwpck_require__(9425) -const { kConstruct } = __nccwpck_require__(9562) -const assert = __nccwpck_require__(4589) -const { getMaxListeners, setMaxListeners, defaultMaxListeners } = __nccwpck_require__(8474) -const kAbortController = Symbol('abortController') +// https://xhr.spec.whatwg.org/#formdata +class FormData { + #state = [] -const requestFinalizer = new FinalizationRegistry(({ signal, abort }) => { - signal.removeEventListener('abort', abort) -}) + constructor (form = undefined) { + webidl.util.markAsUncloneable(this) -const dependentControllerMap = new WeakMap() + if (form !== undefined) { + throw webidl.errors.conversionFailed({ + prefix: 'FormData constructor', + argument: 'Argument 1', + types: ['undefined'] + }) + } + } -let abortSignalHasEventHandlerLeakWarning + append (name, value, filename = undefined) { + webidl.brandCheck(this, FormData) -try { - abortSignalHasEventHandlerLeakWarning = getMaxListeners(new AbortController().signal) > 0 -} catch { - abortSignalHasEventHandlerLeakWarning = false -} + const prefix = 'FormData.append' + webidl.argumentLengthCheck(arguments, 2, prefix) -function buildAbort (acRef) { - return abort + name = webidl.converters.USVString(name) - function abort () { - const ac = acRef.deref() - if (ac !== undefined) { - // Currently, there is a problem with FinalizationRegistry. - // https://github.com/nodejs/node/issues/49344 - // https://github.com/nodejs/node/issues/47748 - // In the case of abort, the first step is to unregister from it. - // If the controller can refer to it, it is still registered. - // It will be removed in the future. - requestFinalizer.unregister(abort) + if (arguments.length === 3 || webidl.is.Blob(value)) { + value = webidl.converters.Blob(value, prefix, 'value') - // Unsubscribe a listener. - // FinalizationRegistry will no longer be called, so this must be done. - this.removeEventListener('abort', abort) + if (filename !== undefined) { + filename = webidl.converters.USVString(filename) + } + } else { + value = webidl.converters.USVString(value) + } - ac.abort(this.reason) + // 1. Let value be value if given; otherwise blobValue. - const controllerList = dependentControllerMap.get(ac.signal) + // 2. Let entry be the result of creating an entry with + // name, value, and filename if given. + const entry = makeEntry(name, value, filename) - if (controllerList !== undefined) { - if (controllerList.size !== 0) { - for (const ref of controllerList) { - const ctrl = ref.deref() - if (ctrl !== undefined) { - ctrl.abort(this.reason) - } - } - controllerList.clear() - } - dependentControllerMap.delete(ac.signal) - } - } + // 3. Append entry to this’s entry list. + this.#state.push(entry) } -} -let patchMethodWarning = false + delete (name) { + webidl.brandCheck(this, FormData) -// https://fetch.spec.whatwg.org/#request-class -class Request { - /** @type {AbortSignal} */ - #signal + const prefix = 'FormData.delete' + webidl.argumentLengthCheck(arguments, 1, prefix) - /** @type {import('../../dispatcher/dispatcher')} */ - #dispatcher + name = webidl.converters.USVString(name) - /** @type {Headers} */ - #headers + // The delete(name) method steps are to remove all entries whose name + // is name from this’s entry list. + this.#state = this.#state.filter(entry => entry.name !== name) + } - #state + get (name) { + webidl.brandCheck(this, FormData) - // https://fetch.spec.whatwg.org/#dom-request - constructor (input, init = undefined) { - webidl.util.markAsUncloneable(this) + const prefix = 'FormData.get' + webidl.argumentLengthCheck(arguments, 1, prefix) - if (input === kConstruct) { - return + name = webidl.converters.USVString(name) + + // 1. If there is no entry whose name is name in this’s entry list, + // then return null. + const idx = this.#state.findIndex((entry) => entry.name === name) + if (idx === -1) { + return null } - const prefix = 'Request constructor' + // 2. Return the value of the first entry whose name is name from + // this’s entry list. + return this.#state[idx].value + } + + getAll (name) { + webidl.brandCheck(this, FormData) + + const prefix = 'FormData.getAll' webidl.argumentLengthCheck(arguments, 1, prefix) - input = webidl.converters.RequestInfo(input) - init = webidl.converters.RequestInit(init) + name = webidl.converters.USVString(name) - // 1. Let request be null. - let request = null + // 1. If there is no entry whose name is name in this’s entry list, + // then return the empty list. + // 2. Return the values of all entries whose name is name, in order, + // from this’s entry list. + return this.#state + .filter((entry) => entry.name === name) + .map((entry) => entry.value) + } - // 2. Let fallbackMode be null. - let fallbackMode = null + has (name) { + webidl.brandCheck(this, FormData) - // 3. Let baseURL be this’s relevant settings object’s API base URL. - const baseUrl = environmentSettingsObject.settingsObject.baseUrl + const prefix = 'FormData.has' + webidl.argumentLengthCheck(arguments, 1, prefix) - // 4. Let signal be null. - let signal = null + name = webidl.converters.USVString(name) - // 5. If input is a string, then: - if (typeof input === 'string') { - this.#dispatcher = init.dispatcher + // The has(name) method steps are to return true if there is an entry + // whose name is name in this’s entry list; otherwise false. + return this.#state.findIndex((entry) => entry.name === name) !== -1 + } - // 1. Let parsedURL be the result of parsing input with baseURL. - // 2. If parsedURL is failure, then throw a TypeError. - let parsedURL - try { - parsedURL = new URL(input, baseUrl) - } catch (err) { - throw new TypeError('Failed to parse URL from ' + input, { cause: err }) - } + set (name, value, filename = undefined) { + webidl.brandCheck(this, FormData) - // 3. If parsedURL includes credentials, then throw a TypeError. - if (parsedURL.username || parsedURL.password) { - throw new TypeError( - 'Request cannot be constructed from a URL that includes credentials: ' + - input - ) - } + const prefix = 'FormData.set' + webidl.argumentLengthCheck(arguments, 2, prefix) - // 4. Set request to a new request whose URL is parsedURL. - request = makeRequest({ urlList: [parsedURL] }) + name = webidl.converters.USVString(name) - // 5. Set fallbackMode to "cors". - fallbackMode = 'cors' + if (arguments.length === 3 || webidl.is.Blob(value)) { + value = webidl.converters.Blob(value, prefix, 'value') + + if (filename !== undefined) { + filename = webidl.converters.USVString(filename) + } } else { - // 6. Otherwise: + value = webidl.converters.USVString(value) + } - // 7. Assert: input is a Request object. - assert(webidl.is.Request(input)) + // The set(name, value) and set(name, blobValue, filename) method steps + // are: - // 8. Set request to input’s request. - request = input.#state + // 1. Let value be value if given; otherwise blobValue. - // 9. Set signal to input’s signal. - signal = input.#signal + // 2. Let entry be the result of creating an entry with name, value, and + // filename if given. + const entry = makeEntry(name, value, filename) - this.#dispatcher = init.dispatcher || input.#dispatcher + // 3. If there are entries in this’s entry list whose name is name, then + // replace the first such entry with entry and remove the others. + const idx = this.#state.findIndex((entry) => entry.name === name) + if (idx !== -1) { + this.#state = [ + ...this.#state.slice(0, idx), + entry, + ...this.#state.slice(idx + 1).filter((entry) => entry.name !== name) + ] + } else { + // 4. Otherwise, append entry to this’s entry list. + this.#state.push(entry) } + } - // 7. Let origin be this’s relevant settings object’s origin. - const origin = environmentSettingsObject.settingsObject.origin + [nodeUtil.inspect.custom] (depth, options) { + const state = this.#state.reduce((a, b) => { + if (a[b.name]) { + if (Array.isArray(a[b.name])) { + a[b.name].push(b.value) + } else { + a[b.name] = [a[b.name], b.value] + } + } else { + a[b.name] = b.value + } - // 8. Let window be "client". - let window = 'client' + return a + }, { __proto__: null }) - // 9. If request’s window is an environment settings object and its origin - // is same origin with origin, then set window to request’s window. - if ( - request.window?.constructor?.name === 'EnvironmentSettingsObject' && - sameOrigin(request.window, origin) - ) { - window = request.window - } + options.depth ??= depth + options.colors ??= true - // 10. If init["window"] exists and is non-null, then throw a TypeError. - if (init.window != null) { - throw new TypeError(`'window' option '${window}' must be null`) - } + const output = nodeUtil.formatWithOptions(options, state) - // 11. If init["window"] exists, then set window to "no-window". - if ('window' in init) { - window = 'no-window' - } + // remove [Object null prototype] + return `FormData ${output.slice(output.indexOf(']') + 2)}` + } - // 12. Set request to a new request with the following properties: - request = makeRequest({ - // URL request’s URL. - // undici implementation note: this is set as the first item in request's urlList in makeRequest - // method request’s method. - method: request.method, - // header list A copy of request’s header list. - // undici implementation note: headersList is cloned in makeRequest - headersList: request.headersList, - // unsafe-request flag Set. - unsafeRequest: request.unsafeRequest, - // client This’s relevant settings object. - client: environmentSettingsObject.settingsObject, - // window window. - window, - // priority request’s priority. - priority: request.priority, - // origin request’s origin. The propagation of the origin is only significant for navigation requests - // being handled by a service worker. In this scenario a request can have an origin that is different - // from the current client. - origin: request.origin, - // referrer request’s referrer. - referrer: request.referrer, - // referrer policy request’s referrer policy. - referrerPolicy: request.referrerPolicy, - // mode request’s mode. - mode: request.mode, - // credentials mode request’s credentials mode. - credentials: request.credentials, - // cache mode request’s cache mode. - cache: request.cache, - // redirect mode request’s redirect mode. - redirect: request.redirect, - // integrity metadata request’s integrity metadata. - integrity: request.integrity, - // keepalive request’s keepalive. - keepalive: request.keepalive, - // reload-navigation flag request’s reload-navigation flag. - reloadNavigation: request.reloadNavigation, - // history-navigation flag request’s history-navigation flag. - historyNavigation: request.historyNavigation, - // URL list A clone of request’s URL list. - urlList: [...request.urlList] - }) + /** + * @param {FormData} formData + */ + static getFormDataState (formData) { + return formData.#state + } - const initHasKey = Object.keys(init).length !== 0 + /** + * @param {FormData} formData + * @param {any[]} newState + */ + static setFormDataState (formData, newState) { + formData.#state = newState + } +} - // 13. If init is not empty, then: - if (initHasKey) { - // 1. If request’s mode is "navigate", then set it to "same-origin". - if (request.mode === 'navigate') { - request.mode = 'same-origin' - } +const { getFormDataState, setFormDataState } = FormData +Reflect.deleteProperty(FormData, 'getFormDataState') +Reflect.deleteProperty(FormData, 'setFormDataState') - // 2. Unset request’s reload-navigation flag. - request.reloadNavigation = false +iteratorMixin('FormData', FormData, getFormDataState, 'name', 'value') - // 3. Unset request’s history-navigation flag. - request.historyNavigation = false +Object.defineProperties(FormData.prototype, { + append: kEnumerableProperty, + delete: kEnumerableProperty, + get: kEnumerableProperty, + getAll: kEnumerableProperty, + has: kEnumerableProperty, + set: kEnumerableProperty, + [Symbol.toStringTag]: { + value: 'FormData', + configurable: true + } +}) - // 4. Set request’s origin to "client". - request.origin = 'client' +/** + * @see https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#create-an-entry + * @param {string} name + * @param {string|Blob} value + * @param {?string} filename + * @returns + */ +function makeEntry (name, value, filename) { + // 1. Set name to the result of converting name into a scalar value string. + // Note: This operation was done by the webidl converter USVString. - // 5. Set request’s referrer to "client" - request.referrer = 'client' + // 2. If value is a string, then set value to the result of converting + // value into a scalar value string. + if (typeof value === 'string') { + // Note: This operation was done by the webidl converter USVString. + } else { + // 3. Otherwise: - // 6. Set request’s referrer policy to the empty string. - request.referrerPolicy = '' + // 1. If value is not a File object, then set value to a new File object, + // representing the same bytes, whose name attribute value is "blob" + if (!webidl.is.File(value)) { + value = new File([value], 'blob', { type: value.type }) + } - // 7. Set request’s URL to request’s current URL. - request.url = request.urlList[request.urlList.length - 1] + // 2. If filename is given, then set value to a new File object, + // representing the same bytes, whose name attribute is filename. + if (filename !== undefined) { + /** @type {FilePropertyBag} */ + const options = { + type: value.type, + lastModified: value.lastModified + } - // 8. Set request’s URL list to « request’s URL ». - request.urlList = [request.url] + value = new File([value], filename, options) } + } - // 14. If init["referrer"] exists, then: - if (init.referrer !== undefined) { - // 1. Let referrer be init["referrer"]. - const referrer = init.referrer + // 4. Return an entry whose name is name and whose value is value. + return { name, value } +} - // 2. If referrer is the empty string, then set request’s referrer to "no-referrer". - if (referrer === '') { - request.referrer = 'no-referrer' - } else { - // 1. Let parsedReferrer be the result of parsing referrer with - // baseURL. - // 2. If parsedReferrer is failure, then throw a TypeError. - let parsedReferrer - try { - parsedReferrer = new URL(referrer, baseUrl) - } catch (err) { - throw new TypeError(`Referrer "${referrer}" is not a valid URL.`, { cause: err }) - } +webidl.is.FormData = webidl.util.MakeTypeAssertion(FormData) - // 3. If one of the following is true - // - parsedReferrer’s scheme is "about" and path is the string "client" - // - parsedReferrer’s origin is not same origin with origin - // then set request’s referrer to "client". - if ( - (parsedReferrer.protocol === 'about:' && parsedReferrer.hostname === 'client') || - (origin && !sameOrigin(parsedReferrer, environmentSettingsObject.settingsObject.baseUrl)) - ) { - request.referrer = 'client' - } else { - // 4. Otherwise, set request’s referrer to parsedReferrer. - request.referrer = parsedReferrer - } - } - } +module.exports = { FormData, makeEntry, setFormDataState } - // 15. If init["referrerPolicy"] exists, then set request’s referrer policy - // to it. - if (init.referrerPolicy !== undefined) { - request.referrerPolicy = init.referrerPolicy - } - // 16. Let mode be init["mode"] if it exists, and fallbackMode otherwise. - let mode - if (init.mode !== undefined) { - mode = init.mode - } else { - mode = fallbackMode - } +/***/ }), - // 17. If mode is "navigate", then throw a TypeError. - if (mode === 'navigate') { - throw webidl.errors.exception({ - header: 'Request constructor', - message: 'invalid request mode navigate.' - }) - } +/***/ 1393: +/***/ ((module) => { - // 18. If mode is non-null, set request’s mode to mode. - if (mode != null) { - request.mode = mode - } - // 19. If init["credentials"] exists, then set request’s credentials mode - // to it. - if (init.credentials !== undefined) { - request.credentials = init.credentials - } - // 18. If init["cache"] exists, then set request’s cache mode to it. - if (init.cache !== undefined) { - request.cache = init.cache - } +// In case of breaking changes, increase the version +// number to avoid conflicts. +const globalOrigin = Symbol.for('undici.globalOrigin.1') - // 21. If request’s cache mode is "only-if-cached" and request’s mode is - // not "same-origin", then throw a TypeError. - if (request.cache === 'only-if-cached' && request.mode !== 'same-origin') { - throw new TypeError( - "'only-if-cached' can be set only with 'same-origin' mode" - ) - } +function getGlobalOrigin () { + return globalThis[globalOrigin] +} - // 22. If init["redirect"] exists, then set request’s redirect mode to it. - if (init.redirect !== undefined) { - request.redirect = init.redirect - } +function setGlobalOrigin (newOrigin) { + if (newOrigin === undefined) { + Object.defineProperty(globalThis, globalOrigin, { + value: undefined, + writable: true, + enumerable: false, + configurable: false + }) - // 23. If init["integrity"] exists, then set request’s integrity metadata to it. - if (init.integrity != null) { - request.integrity = String(init.integrity) - } + return + } - // 24. If init["keepalive"] exists, then set request’s keepalive to it. - if (init.keepalive !== undefined) { - request.keepalive = Boolean(init.keepalive) - } + const parsedURL = new URL(newOrigin) - // 25. If init["method"] exists, then: - if (init.method !== undefined) { - // 1. Let method be init["method"]. - let method = init.method + if (parsedURL.protocol !== 'http:' && parsedURL.protocol !== 'https:') { + throw new TypeError(`Only http & https urls are allowed, received ${parsedURL.protocol}`) + } - const mayBeNormalized = normalizedMethodRecords[method] + Object.defineProperty(globalThis, globalOrigin, { + value: parsedURL, + writable: true, + enumerable: false, + configurable: false + }) +} - if (mayBeNormalized !== undefined) { - // Note: Bypass validation DELETE, GET, HEAD, OPTIONS, POST, PUT, PATCH and these lowercase ones - request.method = mayBeNormalized - } else { - // 2. If method is not a method or method is a forbidden method, then - // throw a TypeError. - if (!isValidHTTPToken(method)) { - throw new TypeError(`'${method}' is not a valid HTTP method.`) - } +module.exports = { + getGlobalOrigin, + setGlobalOrigin +} - const upperCase = method.toUpperCase() - if (forbiddenMethodsSet.has(upperCase)) { - throw new TypeError(`'${method}' HTTP method is unsupported.`) - } +/***/ }), - // 3. Normalize method. - // https://fetch.spec.whatwg.org/#concept-method-normalize - // Note: must be in uppercase - method = normalizedMethodRecordsBase[upperCase] ?? method +/***/ 7754: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - // 4. Set request’s method to method. - request.method = method - } +// https://github.com/Ethan-Arrowood/undici-fetch - if (!patchMethodWarning && request.method === 'patch') { - process.emitWarning('Using `patch` is highly likely to result in a `405 Method Not Allowed`. `PATCH` is much more likely to succeed.', { - code: 'UNDICI-FETCH-patch' - }) - patchMethodWarning = true - } - } - // 26. If init["signal"] exists, then set signal to it. - if (init.signal !== undefined) { - signal = init.signal - } +const { kConstruct } = __nccwpck_require__(8261) +const { kEnumerableProperty } = __nccwpck_require__(2550) +const { + iteratorMixin, + isValidHeaderName, + isValidHeaderValue +} = __nccwpck_require__(3106) +const { webidl } = __nccwpck_require__(909) +const assert = __nccwpck_require__(4589) +const util = __nccwpck_require__(7975) - // 27. Set this’s request to request. - this.#state = request +/** + * @param {number} code + * @returns {code is (0x0a | 0x0d | 0x09 | 0x20)} + */ +function isHTTPWhiteSpaceCharCode (code) { + return code === 0x0a || code === 0x0d || code === 0x09 || code === 0x20 +} - // 28. Set this’s signal to a new AbortSignal object with this’s relevant - // Realm. - // TODO: could this be simplified with AbortSignal.any - // (https://dom.spec.whatwg.org/#dom-abortsignal-any) - const ac = new AbortController() - this.#signal = ac.signal +/** + * @see https://fetch.spec.whatwg.org/#concept-header-value-normalize + * @param {string} potentialValue + * @returns {string} + */ +function headerValueNormalize (potentialValue) { + // To normalize a byte sequence potentialValue, remove + // any leading and trailing HTTP whitespace bytes from + // potentialValue. + let i = 0; let j = potentialValue.length - // 29. If signal is not null, then make this’s signal follow signal. - if (signal != null) { - if (signal.aborted) { - ac.abort(signal.reason) - } else { - // Keep a strong ref to ac while request object - // is alive. This is needed to prevent AbortController - // from being prematurely garbage collected. - // See, https://github.com/nodejs/undici/issues/1926. - this[kAbortController] = ac + while (j > i && isHTTPWhiteSpaceCharCode(potentialValue.charCodeAt(j - 1))) --j + while (j > i && isHTTPWhiteSpaceCharCode(potentialValue.charCodeAt(i))) ++i - const acRef = new WeakRef(ac) - const abort = buildAbort(acRef) + return i === 0 && j === potentialValue.length ? potentialValue : potentialValue.substring(i, j) +} - // If the max amount of listeners is equal to the default, increase it - if (abortSignalHasEventHandlerLeakWarning && getMaxListeners(signal) === defaultMaxListeners) { - setMaxListeners(1500, signal) - } +/** + * @param {Headers} headers + * @param {Array|Object} object + */ +function fill (headers, object) { + // To fill a Headers object headers with a given object object, run these steps: - util.addAbortListener(signal, abort) - // The third argument must be a registry key to be unregistered. - // Without it, you cannot unregister. - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/FinalizationRegistry - // abort is used as the unregister key. (because it is unique) - requestFinalizer.register(ac, { signal, abort }, abort) + // 1. If object is a sequence, then for each header in object: + // Note: webidl conversion to array has already been done. + if (Array.isArray(object)) { + for (let i = 0; i < object.length; ++i) { + const header = object[i] + // 1. If header does not contain exactly two items, then throw a TypeError. + if (header.length !== 2) { + throw webidl.errors.exception({ + header: 'Headers constructor', + message: `expected name/value pair to be length 2, found ${header.length}.` + }) } - } - - // 30. Set this’s headers to a new Headers object with this’s relevant - // Realm, whose header list is request’s header list and guard is - // "request". - this.#headers = new Headers(kConstruct) - setHeadersList(this.#headers, request.headersList) - setHeadersGuard(this.#headers, 'request') - // 31. If this’s request’s mode is "no-cors", then: - if (mode === 'no-cors') { - // 1. If this’s request’s method is not a CORS-safelisted method, - // then throw a TypeError. - if (!corsSafeListedMethodsSet.has(request.method)) { - throw new TypeError( - `'${request.method} is unsupported in no-cors mode.` - ) - } + // 2. Append (header’s first item, header’s second item) to headers. + appendHeader(headers, header[0], header[1]) + } + } else if (typeof object === 'object' && object !== null) { + // Note: null should throw - // 2. Set this’s headers’s guard to "request-no-cors". - setHeadersGuard(this.#headers, 'request-no-cors') + // 2. Otherwise, object is a record, then for each key → value in object, + // append (key, value) to headers + const keys = Object.keys(object) + for (let i = 0; i < keys.length; ++i) { + appendHeader(headers, keys[i], object[keys[i]]) } + } else { + throw webidl.errors.conversionFailed({ + prefix: 'Headers constructor', + argument: 'Argument 1', + types: ['sequence>', 'record'] + }) + } +} - // 32. If init is not empty, then: - if (initHasKey) { - /** @type {HeadersList} */ - const headersList = getHeadersList(this.#headers) - // 1. Let headers be a copy of this’s headers and its associated header - // list. - // 2. If init["headers"] exists, then set headers to init["headers"]. - const headers = init.headers !== undefined ? init.headers : new HeadersList(headersList) +/** + * @see https://fetch.spec.whatwg.org/#concept-headers-append + * @param {Headers} headers + * @param {string} name + * @param {string} value + */ +function appendHeader (headers, name, value) { + // 1. Normalize value. + value = headerValueNormalize(value) - // 3. Empty this’s headers’s header list. - headersList.clear() + // 2. If name is not a header name or value is not a + // header value, then throw a TypeError. + if (!isValidHeaderName(name)) { + throw webidl.errors.invalidArgument({ + prefix: 'Headers.append', + value: name, + type: 'header name' + }) + } else if (!isValidHeaderValue(value)) { + throw webidl.errors.invalidArgument({ + prefix: 'Headers.append', + value, + type: 'header value' + }) + } - // 4. If headers is a Headers object, then for each header in its header - // list, append header’s name/header’s value to this’s headers. - if (headers instanceof HeadersList) { - for (const { name, value } of headers.rawValues()) { - headersList.append(name, value, false) - } - // Note: Copy the `set-cookie` meta-data. - headersList.cookies = headers.cookies - } else { - // 5. Otherwise, fill this’s headers with headers. - fillHeaders(this.#headers, headers) - } - } + // 3. If headers’s guard is "immutable", then throw a TypeError. + // 4. Otherwise, if headers’s guard is "request" and name is a + // forbidden header name, return. + // 5. Otherwise, if headers’s guard is "request-no-cors": + // TODO + // Note: undici does not implement forbidden header names + if (getHeadersGuard(headers) === 'immutable') { + throw new TypeError('immutable') + } - // 33. Let inputBody be input’s request’s body if input is a Request - // object; otherwise null. - const inputBody = webidl.is.Request(input) ? input.#state.body : null + // 6. Otherwise, if headers’s guard is "response" and name is a + // forbidden response-header name, return. - // 34. If either init["body"] exists and is non-null or inputBody is - // non-null, and request’s method is `GET` or `HEAD`, then throw a - // TypeError. - if ( - (init.body != null || inputBody != null) && - (request.method === 'GET' || request.method === 'HEAD') - ) { - throw new TypeError('Request with GET/HEAD method cannot have body.') - } + // 7. Append (name, value) to headers’s header list. + return getHeadersList(headers).append(name, value, false) - // 35. Let initBody be null. - let initBody = null + // 8. If headers’s guard is "request-no-cors", then remove + // privileged no-CORS request headers from headers +} - // 36. If init["body"] exists and is non-null, then: - if (init.body != null) { - // 1. Let Content-Type be null. - // 2. Set initBody and Content-Type to the result of extracting - // init["body"], with keepalive set to request’s keepalive. - const [extractedBody, contentType] = extractBody( - init.body, - request.keepalive - ) - initBody = extractedBody +// https://fetch.spec.whatwg.org/#concept-header-list-sort-and-combine +/** + * @param {Headers} target + */ +function headersListSortAndCombine (target) { + const headersList = getHeadersList(target) - // 3, If Content-Type is non-null and this’s headers’s header list does - // not contain `Content-Type`, then append `Content-Type`/Content-Type to - // this’s headers. - if (contentType && !getHeadersList(this.#headers).contains('content-type', true)) { - this.#headers.append('content-type', contentType, true) - } - } + if (!headersList) { + return [] + } - // 37. Let inputOrInitBody be initBody if it is non-null; otherwise - // inputBody. - const inputOrInitBody = initBody ?? inputBody + if (headersList.sortedMap) { + return headersList.sortedMap + } - // 38. If inputOrInitBody is non-null and inputOrInitBody’s source is - // null, then: - if (inputOrInitBody != null && inputOrInitBody.source == null) { - // 1. If initBody is non-null and init["duplex"] does not exist, - // then throw a TypeError. - if (initBody != null && init.duplex == null) { - throw new TypeError('RequestInit: duplex option is required when sending a body.') - } + // 1. Let headers be an empty list of headers with the key being the name + // and value the value. + const headers = [] - // 2. If this’s request’s mode is neither "same-origin" nor "cors", - // then throw a TypeError. - if (request.mode !== 'same-origin' && request.mode !== 'cors') { - throw new TypeError( - 'If request is made from ReadableStream, mode should be "same-origin" or "cors"' - ) - } + // 2. Let names be the result of convert header names to a sorted-lowercase + // set with all the names of the headers in list. + const names = headersList.toSortedArray() - // 3. Set this’s request’s use-CORS-preflight flag. - request.useCORSPreflightFlag = true - } + const cookies = headersList.cookies - // 39. Let finalBody be inputOrInitBody. - let finalBody = inputOrInitBody + // fast-path + if (cookies === null || cookies.length === 1) { + // Note: The non-null assertion of value has already been done by `HeadersList#toSortedArray` + return (headersList.sortedMap = names) + } - // 40. If initBody is null and inputBody is non-null, then: - if (initBody == null && inputBody != null) { - // 1. If input is unusable, then throw a TypeError. - if (bodyUnusable(input.#state)) { - throw new TypeError( - 'Cannot construct a Request with a Request object that has already been used.' - ) - } + // 3. For each name of names: + for (let i = 0; i < names.length; ++i) { + const { 0: name, 1: value } = names[i] + // 1. If name is `set-cookie`, then: + if (name === 'set-cookie') { + // 1. Let values be a list of all values of headers in list whose name + // is a byte-case-insensitive match for name, in order. - // 2. Set finalBody to the result of creating a proxy for inputBody. - // https://streams.spec.whatwg.org/#readablestream-create-a-proxy - const identityTransform = new TransformStream() - inputBody.stream.pipeThrough(identityTransform) - finalBody = { - source: inputBody.source, - length: inputBody.length, - stream: identityTransform.readable + // 2. For each value of values: + // 1. Append (name, value) to headers. + for (let j = 0; j < cookies.length; ++j) { + headers.push([name, cookies[j]]) } - } + } else { + // 2. Otherwise: - // 41. Set this’s request’s body to finalBody. - this.#state.body = finalBody - } + // 1. Let value be the result of getting name from list. - // Returns request’s HTTP method, which is "GET" by default. - get method () { - webidl.brandCheck(this, Request) + // 2. Assert: value is non-null. + // Note: This operation was done by `HeadersList#toSortedArray`. - // The method getter steps are to return this’s request’s method. - return this.#state.method + // 3. Append (name, value) to headers. + headers.push([name, value]) + } } - // Returns the URL of request as a string. - get url () { - webidl.brandCheck(this, Request) + // 4. Return headers. + return (headersList.sortedMap = headers) +} - // The url getter steps are to return this’s request’s URL, serialized. - return URLSerializer(this.#state.url) - } +function compareHeaderName (a, b) { + return a[0] < b[0] ? -1 : 1 +} - // Returns a Headers object consisting of the headers associated with request. - // Note that headers added in the network layer by the user agent will not - // be accounted for in this object, e.g., the "Host" header. - get headers () { - webidl.brandCheck(this, Request) +class HeadersList { + /** @type {[string, string][]|null} */ + cookies = null - // The headers getter steps are to return this’s headers. - return this.#headers + sortedMap + headersMap + + constructor (init) { + if (init instanceof HeadersList) { + this.headersMap = new Map(init.headersMap) + this.sortedMap = init.sortedMap + this.cookies = init.cookies === null ? null : [...init.cookies] + } else { + this.headersMap = new Map(init) + this.sortedMap = null + } } - // Returns the kind of resource requested by request, e.g., "document" - // or "script". - get destination () { - webidl.brandCheck(this, Request) + /** + * @see https://fetch.spec.whatwg.org/#header-list-contains + * @param {string} name + * @param {boolean} isLowerCase + */ + contains (name, isLowerCase) { + // A header list list contains a header name name if list + // contains a header whose name is a byte-case-insensitive + // match for name. - // The destination getter are to return this’s request’s destination. - return this.#state.destination + return this.headersMap.has(isLowerCase ? name : name.toLowerCase()) } - // Returns the referrer of request. Its value can be a same-origin URL if - // explicitly set in init, the empty string to indicate no referrer, and - // "about:client" when defaulting to the global’s default. This is used - // during fetching to determine the value of the `Referer` header of the - // request being made. - get referrer () { - webidl.brandCheck(this, Request) + clear () { + this.headersMap.clear() + this.sortedMap = null + this.cookies = null + } - // 1. If this’s request’s referrer is "no-referrer", then return the - // empty string. - if (this.#state.referrer === 'no-referrer') { - return '' - } + /** + * @see https://fetch.spec.whatwg.org/#concept-header-list-append + * @param {string} name + * @param {string} value + * @param {boolean} isLowerCase + */ + append (name, value, isLowerCase) { + this.sortedMap = null - // 2. If this’s request’s referrer is "client", then return - // "about:client". - if (this.#state.referrer === 'client') { - return 'about:client' + // 1. If list contains name, then set name to the first such + // header’s name. + const lowercaseName = isLowerCase ? name : name.toLowerCase() + const exists = this.headersMap.get(lowercaseName) + + // 2. Append (name, value) to list. + if (exists) { + const delimiter = lowercaseName === 'cookie' ? '; ' : ', ' + this.headersMap.set(lowercaseName, { + name: exists.name, + value: `${exists.value}${delimiter}${value}` + }) + } else { + this.headersMap.set(lowercaseName, { name, value }) } - // Return this’s request’s referrer, serialized. - return this.#state.referrer.toString() + if (lowercaseName === 'set-cookie') { + (this.cookies ??= []).push(value) + } } - // Returns the referrer policy associated with request. - // This is used during fetching to compute the value of the request’s - // referrer. - get referrerPolicy () { - webidl.brandCheck(this, Request) + /** + * @see https://fetch.spec.whatwg.org/#concept-header-list-set + * @param {string} name + * @param {string} value + * @param {boolean} isLowerCase + */ + set (name, value, isLowerCase) { + this.sortedMap = null + const lowercaseName = isLowerCase ? name : name.toLowerCase() - // The referrerPolicy getter steps are to return this’s request’s referrer policy. - return this.#state.referrerPolicy + if (lowercaseName === 'set-cookie') { + this.cookies = [value] + } + + // 1. If list contains name, then set the value of + // the first such header to value and remove the + // others. + // 2. Otherwise, append header (name, value) to list. + this.headersMap.set(lowercaseName, { name, value }) } - // Returns the mode associated with request, which is a string indicating - // whether the request will use CORS, or will be restricted to same-origin - // URLs. - get mode () { - webidl.brandCheck(this, Request) + /** + * @see https://fetch.spec.whatwg.org/#concept-header-list-delete + * @param {string} name + * @param {boolean} isLowerCase + */ + delete (name, isLowerCase) { + this.sortedMap = null + if (!isLowerCase) name = name.toLowerCase() - // The mode getter steps are to return this’s request’s mode. - return this.#state.mode + if (name === 'set-cookie') { + this.cookies = null + } + + this.headersMap.delete(name) } - // Returns the credentials mode associated with request, - // which is a string indicating whether credentials will be sent with the - // request always, never, or only when sent to a same-origin URL. - get credentials () { - webidl.brandCheck(this, Request) + /** + * @see https://fetch.spec.whatwg.org/#concept-header-list-get + * @param {string} name + * @param {boolean} isLowerCase + * @returns {string | null} + */ + get (name, isLowerCase) { + // 1. If list does not contain name, then return null. + // 2. Return the values of all headers in list whose name + // is a byte-case-insensitive match for name, + // separated from each other by 0x2C 0x20, in order. + return this.headersMap.get(isLowerCase ? name : name.toLowerCase())?.value ?? null + } - // The credentials getter steps are to return this’s request’s credentials mode. - return this.#state.credentials + * [Symbol.iterator] () { + // use the lowercased name + for (const { 0: name, 1: { value } } of this.headersMap) { + yield [name, value] + } } - // Returns the cache mode associated with request, - // which is a string indicating how the request will - // interact with the browser’s cache when fetching. - get cache () { - webidl.brandCheck(this, Request) + get entries () { + const headers = {} - // The cache getter steps are to return this’s request’s cache mode. - return this.#state.cache - } + if (this.headersMap.size !== 0) { + for (const { name, value } of this.headersMap.values()) { + headers[name] = value + } + } - // Returns the redirect mode associated with request, - // which is a string indicating how redirects for the - // request will be handled during fetching. A request - // will follow redirects by default. - get redirect () { - webidl.brandCheck(this, Request) + return headers + } - // The redirect getter steps are to return this’s request’s redirect mode. - return this.#state.redirect + rawValues () { + return this.headersMap.values() } - // Returns request’s subresource integrity metadata, which is a - // cryptographic hash of the resource being fetched. Its value - // consists of multiple hashes separated by whitespace. [SRI] - get integrity () { - webidl.brandCheck(this, Request) + get entriesList () { + const headers = [] - // The integrity getter steps are to return this’s request’s integrity - // metadata. - return this.#state.integrity - } + if (this.headersMap.size !== 0) { + for (const { 0: lowerName, 1: { name, value } } of this.headersMap) { + if (lowerName === 'set-cookie') { + for (const cookie of this.cookies) { + headers.push([name, cookie]) + } + } else { + headers.push([name, value]) + } + } + } - // Returns a boolean indicating whether or not request can outlive the - // global in which it was created. - get keepalive () { - webidl.brandCheck(this, Request) + return headers + } - // The keepalive getter steps are to return this’s request’s keepalive. - return this.#state.keepalive + // https://fetch.spec.whatwg.org/#convert-header-names-to-a-sorted-lowercase-set + toSortedArray () { + const size = this.headersMap.size + const array = new Array(size) + // In most cases, you will use the fast-path. + // fast-path: Use binary insertion sort for small arrays. + if (size <= 32) { + if (size === 0) { + // If empty, it is an empty array. To avoid the first index assignment. + return array + } + // Improve performance by unrolling loop and avoiding double-loop. + // Double-loop-less version of the binary insertion sort. + const iterator = this.headersMap[Symbol.iterator]() + const firstValue = iterator.next().value + // set [name, value] to first index. + array[0] = [firstValue[0], firstValue[1].value] + // https://fetch.spec.whatwg.org/#concept-header-list-sort-and-combine + // 3.2.2. Assert: value is non-null. + assert(firstValue[1].value !== null) + for ( + let i = 1, j = 0, right = 0, left = 0, pivot = 0, x, value; + i < size; + ++i + ) { + // get next value + value = iterator.next().value + // set [name, value] to current index. + x = array[i] = [value[0], value[1].value] + // https://fetch.spec.whatwg.org/#concept-header-list-sort-and-combine + // 3.2.2. Assert: value is non-null. + assert(x[1] !== null) + left = 0 + right = i + // binary search + while (left < right) { + // middle index + pivot = left + ((right - left) >> 1) + // compare header name + if (array[pivot][0] <= x[0]) { + left = pivot + 1 + } else { + right = pivot + } + } + if (i !== pivot) { + j = i + while (j > left) { + array[j] = array[--j] + } + array[left] = x + } + } + /* c8 ignore next 4 */ + if (!iterator.next().done) { + // This is for debugging and will never be called. + throw new TypeError('Unreachable') + } + return array + } else { + // This case would be a rare occurrence. + // slow-path: fallback + let i = 0 + for (const { 0: name, 1: { value } } of this.headersMap) { + array[i++] = [name, value] + // https://fetch.spec.whatwg.org/#concept-header-list-sort-and-combine + // 3.2.2. Assert: value is non-null. + assert(value !== null) + } + return array.sort(compareHeaderName) + } } +} - // Returns a boolean indicating whether or not request is for a reload - // navigation. - get isReloadNavigation () { - webidl.brandCheck(this, Request) +// https://fetch.spec.whatwg.org/#headers-class +class Headers { + #guard + /** + * @type {HeadersList} + */ + #headersList - // The isReloadNavigation getter steps are to return true if this’s - // request’s reload-navigation flag is set; otherwise false. - return this.#state.reloadNavigation - } + /** + * @param {HeadersInit|Symbol} [init] + * @returns + */ + constructor (init = undefined) { + webidl.util.markAsUncloneable(this) - // Returns a boolean indicating whether or not request is for a history - // navigation (a.k.a. back-forward navigation). - get isHistoryNavigation () { - webidl.brandCheck(this, Request) + if (init === kConstruct) { + return + } - // The isHistoryNavigation getter steps are to return true if this’s request’s - // history-navigation flag is set; otherwise false. - return this.#state.historyNavigation - } + this.#headersList = new HeadersList() - // Returns the signal associated with request, which is an AbortSignal - // object indicating whether or not request has been aborted, and its - // abort event handler. - get signal () { - webidl.brandCheck(this, Request) + // The new Headers(init) constructor steps are: - // The signal getter steps are to return this’s signal. - return this.#signal + // 1. Set this’s guard to "none". + this.#guard = 'none' + + // 2. If init is given, then fill this with init. + if (init !== undefined) { + init = webidl.converters.HeadersInit(init, 'Headers constructor', 'init') + fill(this, init) + } } - get body () { - webidl.brandCheck(this, Request) + // https://fetch.spec.whatwg.org/#dom-headers-append + append (name, value) { + webidl.brandCheck(this, Headers) - return this.#state.body ? this.#state.body.stream : null - } + webidl.argumentLengthCheck(arguments, 2, 'Headers.append') - get bodyUsed () { - webidl.brandCheck(this, Request) + const prefix = 'Headers.append' + name = webidl.converters.ByteString(name, prefix, 'name') + value = webidl.converters.ByteString(value, prefix, 'value') - return !!this.#state.body && util.isDisturbed(this.#state.body.stream) + return appendHeader(this, name, value) } - get duplex () { - webidl.brandCheck(this, Request) + // https://fetch.spec.whatwg.org/#dom-headers-delete + delete (name) { + webidl.brandCheck(this, Headers) - return 'half' - } + webidl.argumentLengthCheck(arguments, 1, 'Headers.delete') - // Returns a clone of request. - clone () { - webidl.brandCheck(this, Request) + const prefix = 'Headers.delete' + name = webidl.converters.ByteString(name, prefix, 'name') - // 1. If this is unusable, then throw a TypeError. - if (bodyUnusable(this.#state)) { - throw new TypeError('unusable') + // 1. If name is not a header name, then throw a TypeError. + if (!isValidHeaderName(name)) { + throw webidl.errors.invalidArgument({ + prefix: 'Headers.delete', + value: name, + type: 'header name' + }) } - // 2. Let clonedRequest be the result of cloning this’s request. - const clonedRequest = cloneRequest(this.#state) + // 2. If this’s guard is "immutable", then throw a TypeError. + // 3. Otherwise, if this’s guard is "request" and name is a + // forbidden header name, return. + // 4. Otherwise, if this’s guard is "request-no-cors", name + // is not a no-CORS-safelisted request-header name, and + // name is not a privileged no-CORS request-header name, + // return. + // 5. Otherwise, if this’s guard is "response" and name is + // a forbidden response-header name, return. + // Note: undici does not implement forbidden header names + if (this.#guard === 'immutable') { + throw new TypeError('immutable') + } - // 3. Let clonedRequestObject be the result of creating a Request object, - // given clonedRequest, this’s headers’s guard, and this’s relevant Realm. - // 4. Make clonedRequestObject’s signal follow this’s signal. - const ac = new AbortController() - if (this.signal.aborted) { - ac.abort(this.signal.reason) - } else { - let list = dependentControllerMap.get(this.signal) - if (list === undefined) { - list = new Set() - dependentControllerMap.set(this.signal, list) - } - const acRef = new WeakRef(ac) - list.add(acRef) - util.addAbortListener( - ac.signal, - buildAbort(acRef) - ) + // 6. If this’s header list does not contain name, then + // return. + if (!this.#headersList.contains(name, false)) { + return } - // 4. Return clonedRequestObject. - return fromInnerRequest(clonedRequest, this.#dispatcher, ac.signal, getHeadersGuard(this.#headers)) + // 7. Delete name from this’s header list. + // 8. If this’s guard is "request-no-cors", then remove + // privileged no-CORS request headers from this. + this.#headersList.delete(name, false) } - [nodeUtil.inspect.custom] (depth, options) { - if (options.depth === null) { - options.depth = 2 - } + // https://fetch.spec.whatwg.org/#dom-headers-get + get (name) { + webidl.brandCheck(this, Headers) - options.colors ??= true + webidl.argumentLengthCheck(arguments, 1, 'Headers.get') - const properties = { - method: this.method, - url: this.url, - headers: this.headers, - destination: this.destination, - referrer: this.referrer, - referrerPolicy: this.referrerPolicy, - mode: this.mode, - credentials: this.credentials, - cache: this.cache, - redirect: this.redirect, - integrity: this.integrity, - keepalive: this.keepalive, - isReloadNavigation: this.isReloadNavigation, - isHistoryNavigation: this.isHistoryNavigation, - signal: this.signal + const prefix = 'Headers.get' + name = webidl.converters.ByteString(name, prefix, 'name') + + // 1. If name is not a header name, then throw a TypeError. + if (!isValidHeaderName(name)) { + throw webidl.errors.invalidArgument({ + prefix, + value: name, + type: 'header name' + }) } - return `Request ${nodeUtil.formatWithOptions(options, properties)}` + // 2. Return the result of getting name from this’s header + // list. + return this.#headersList.get(name, false) } - /** - * @param {Request} request - * @param {AbortSignal} newSignal - */ - static setRequestSignal (request, newSignal) { - request.#signal = newSignal - return request - } + // https://fetch.spec.whatwg.org/#dom-headers-has + has (name) { + webidl.brandCheck(this, Headers) - /** - * @param {Request} request - */ - static getRequestDispatcher (request) { - return request.#dispatcher - } + webidl.argumentLengthCheck(arguments, 1, 'Headers.has') - /** - * @param {Request} request - * @param {import('../../dispatcher/dispatcher')} newDispatcher - */ - static setRequestDispatcher (request, newDispatcher) { - request.#dispatcher = newDispatcher - } + const prefix = 'Headers.has' + name = webidl.converters.ByteString(name, prefix, 'name') - /** - * @param {Request} request - * @param {Headers} newHeaders - */ - static setRequestHeaders (request, newHeaders) { - request.#headers = newHeaders - } + // 1. If name is not a header name, then throw a TypeError. + if (!isValidHeaderName(name)) { + throw webidl.errors.invalidArgument({ + prefix, + value: name, + type: 'header name' + }) + } - /** - * @param {Request} request - */ - static getRequestState (request) { - return request.#state + // 2. Return true if this’s header list contains name; + // otherwise false. + return this.#headersList.contains(name, false) } - /** - * @param {Request} request - * @param {any} newState - */ - static setRequestState (request, newState) { - request.#state = newState + // https://fetch.spec.whatwg.org/#dom-headers-set + set (name, value) { + webidl.brandCheck(this, Headers) + + webidl.argumentLengthCheck(arguments, 2, 'Headers.set') + + const prefix = 'Headers.set' + name = webidl.converters.ByteString(name, prefix, 'name') + value = webidl.converters.ByteString(value, prefix, 'value') + + // 1. Normalize value. + value = headerValueNormalize(value) + + // 2. If name is not a header name or value is not a + // header value, then throw a TypeError. + if (!isValidHeaderName(name)) { + throw webidl.errors.invalidArgument({ + prefix, + value: name, + type: 'header name' + }) + } else if (!isValidHeaderValue(value)) { + throw webidl.errors.invalidArgument({ + prefix, + value, + type: 'header value' + }) + } + + // 3. If this’s guard is "immutable", then throw a TypeError. + // 4. Otherwise, if this’s guard is "request" and name is a + // forbidden header name, return. + // 5. Otherwise, if this’s guard is "request-no-cors" and + // name/value is not a no-CORS-safelisted request-header, + // return. + // 6. Otherwise, if this’s guard is "response" and name is a + // forbidden response-header name, return. + // Note: undici does not implement forbidden header names + if (this.#guard === 'immutable') { + throw new TypeError('immutable') + } + + // 7. Set (name, value) in this’s header list. + // 8. If this’s guard is "request-no-cors", then remove + // privileged no-CORS request headers from this + this.#headersList.set(name, value, false) } -} -const { setRequestSignal, getRequestDispatcher, setRequestDispatcher, setRequestHeaders, getRequestState, setRequestState } = Request -Reflect.deleteProperty(Request, 'setRequestSignal') -Reflect.deleteProperty(Request, 'getRequestDispatcher') -Reflect.deleteProperty(Request, 'setRequestDispatcher') -Reflect.deleteProperty(Request, 'setRequestHeaders') -Reflect.deleteProperty(Request, 'getRequestState') -Reflect.deleteProperty(Request, 'setRequestState') + // https://fetch.spec.whatwg.org/#dom-headers-getsetcookie + getSetCookie () { + webidl.brandCheck(this, Headers) -mixinBody(Request, getRequestState) + // 1. If this’s header list does not contain `Set-Cookie`, then return « ». + // 2. Return the values of all headers in this’s header list whose name is + // a byte-case-insensitive match for `Set-Cookie`, in order. -// https://fetch.spec.whatwg.org/#requests -function makeRequest (init) { - return { - method: init.method ?? 'GET', - localURLsOnly: init.localURLsOnly ?? false, - unsafeRequest: init.unsafeRequest ?? false, - body: init.body ?? null, - client: init.client ?? null, - reservedClient: init.reservedClient ?? null, - replacesClientId: init.replacesClientId ?? '', - window: init.window ?? 'client', - keepalive: init.keepalive ?? false, - serviceWorkers: init.serviceWorkers ?? 'all', - initiator: init.initiator ?? '', - destination: init.destination ?? '', - priority: init.priority ?? null, - origin: init.origin ?? 'client', - policyContainer: init.policyContainer ?? 'client', - referrer: init.referrer ?? 'client', - referrerPolicy: init.referrerPolicy ?? '', - mode: init.mode ?? 'no-cors', - useCORSPreflightFlag: init.useCORSPreflightFlag ?? false, - credentials: init.credentials ?? 'same-origin', - useCredentials: init.useCredentials ?? false, - cache: init.cache ?? 'default', - redirect: init.redirect ?? 'follow', - integrity: init.integrity ?? '', - cryptoGraphicsNonceMetadata: init.cryptoGraphicsNonceMetadata ?? '', - parserMetadata: init.parserMetadata ?? '', - reloadNavigation: init.reloadNavigation ?? false, - historyNavigation: init.historyNavigation ?? false, - userActivation: init.userActivation ?? false, - taintedOrigin: init.taintedOrigin ?? false, - redirectCount: init.redirectCount ?? 0, - responseTainting: init.responseTainting ?? 'basic', - preventNoCacheCacheControlHeaderModification: init.preventNoCacheCacheControlHeaderModification ?? false, - done: init.done ?? false, - timingAllowFailed: init.timingAllowFailed ?? false, - useURLCredentials: init.useURLCredentials ?? undefined, - traversableForUserPrompts: init.traversableForUserPrompts ?? 'client', - urlList: init.urlList, - url: init.urlList[0], - headersList: init.headersList - ? new HeadersList(init.headersList) - : new HeadersList() + const list = this.#headersList.cookies + + if (list) { + return [...list] + } + + return [] } -} -// https://fetch.spec.whatwg.org/#concept-request-clone -function cloneRequest (request) { - // To clone a request request, run these steps: + [util.inspect.custom] (depth, options) { + options.depth ??= depth - // 1. Let newRequest be a copy of request, except for its body. - const newRequest = makeRequest({ ...request, body: null }) + return `Headers ${util.formatWithOptions(options, this.#headersList.entries)}` + } - // 2. If request’s body is non-null, set newRequest’s body to the - // result of cloning request’s body. - if (request.body != null) { - newRequest.body = cloneBody(request.body) + static getHeadersGuard (o) { + return o.#guard } - // 3. Return newRequest. - return newRequest -} + static setHeadersGuard (o, guard) { + o.#guard = guard + } -/** - * @see https://fetch.spec.whatwg.org/#request-create - * @param {any} innerRequest - * @param {import('../../dispatcher/agent')} dispatcher - * @param {AbortSignal} signal - * @param {'request' | 'immutable' | 'request-no-cors' | 'response' | 'none'} guard - * @returns {Request} - */ -function fromInnerRequest (innerRequest, dispatcher, signal, guard) { - const request = new Request(kConstruct) - setRequestState(request, innerRequest) - setRequestDispatcher(request, dispatcher) - setRequestSignal(request, signal) - const headers = new Headers(kConstruct) - setRequestHeaders(request, headers) - setHeadersList(headers, innerRequest.headersList) - setHeadersGuard(headers, guard) - return request + /** + * @param {Headers} o + */ + static getHeadersList (o) { + return o.#headersList + } + + /** + * @param {Headers} target + * @param {HeadersList} list + */ + static setHeadersList (target, list) { + target.#headersList = list + } } -Object.defineProperties(Request.prototype, { - method: kEnumerableProperty, - url: kEnumerableProperty, - headers: kEnumerableProperty, - redirect: kEnumerableProperty, - clone: kEnumerableProperty, - signal: kEnumerableProperty, - duplex: kEnumerableProperty, - destination: kEnumerableProperty, - body: kEnumerableProperty, - bodyUsed: kEnumerableProperty, - isHistoryNavigation: kEnumerableProperty, - isReloadNavigation: kEnumerableProperty, - keepalive: kEnumerableProperty, - integrity: kEnumerableProperty, - cache: kEnumerableProperty, - credentials: kEnumerableProperty, - attribute: kEnumerableProperty, - referrerPolicy: kEnumerableProperty, - referrer: kEnumerableProperty, - mode: kEnumerableProperty, +const { getHeadersGuard, setHeadersGuard, getHeadersList, setHeadersList } = Headers +Reflect.deleteProperty(Headers, 'getHeadersGuard') +Reflect.deleteProperty(Headers, 'setHeadersGuard') +Reflect.deleteProperty(Headers, 'getHeadersList') +Reflect.deleteProperty(Headers, 'setHeadersList') + +iteratorMixin('Headers', Headers, headersListSortAndCombine, 0, 1) + +Object.defineProperties(Headers.prototype, { + append: kEnumerableProperty, + delete: kEnumerableProperty, + get: kEnumerableProperty, + has: kEnumerableProperty, + set: kEnumerableProperty, + getSetCookie: kEnumerableProperty, [Symbol.toStringTag]: { - value: 'Request', + value: 'Headers', configurable: true + }, + [util.inspect.custom]: { + enumerable: false } }) -webidl.is.Request = webidl.util.MakeTypeAssertion(Request) +webidl.converters.HeadersInit = function (V, prefix, argument) { + if (webidl.util.Type(V) === webidl.util.Types.OBJECT) { + const iterator = Reflect.get(V, Symbol.iterator) -/** - * @param {*} V - * @returns {import('../../../types/fetch').Request|string} - * - * @see https://fetch.spec.whatwg.org/#requestinfo - */ -webidl.converters.RequestInfo = function (V) { - if (typeof V === 'string') { - return webidl.converters.USVString(V) - } + // A work-around to ensure we send the properly-cased Headers when V is a Headers object. + // Read https://github.com/nodejs/undici/pull/3159#issuecomment-2075537226 before touching, please. + if (!util.types.isProxy(V) && iterator === Headers.prototype.entries) { // Headers object + try { + return getHeadersList(V).entriesList + } catch { + // fall-through + } + } - if (webidl.is.Request(V)) { - return V + if (typeof iterator === 'function') { + return webidl.converters['sequence>'](V, prefix, argument, iterator.bind(V)) + } + + return webidl.converters['record'](V, prefix, argument) } - return webidl.converters.USVString(V) + throw webidl.errors.conversionFailed({ + prefix: 'Headers constructor', + argument: 'Argument 1', + types: ['sequence>', 'record'] + }) } -/** - * @param {*} V - * @returns {import('../../../types/fetch').RequestInit} - * @see https://fetch.spec.whatwg.org/#requestinit - */ -webidl.converters.RequestInit = webidl.dictionaryConverter([ - { - key: 'method', - converter: webidl.converters.ByteString - }, - { - key: 'headers', - converter: webidl.converters.HeadersInit - }, - { - key: 'body', - converter: webidl.nullableConverter( - webidl.converters.BodyInit - ) - }, - { - key: 'referrer', - converter: webidl.converters.USVString - }, - { - key: 'referrerPolicy', - converter: webidl.converters.DOMString, - // https://w3c.github.io/webappsec-referrer-policy/#referrer-policy - allowedValues: referrerPolicy - }, - { - key: 'mode', - converter: webidl.converters.DOMString, - // https://fetch.spec.whatwg.org/#concept-request-mode - allowedValues: requestMode - }, - { - key: 'credentials', - converter: webidl.converters.DOMString, - // https://fetch.spec.whatwg.org/#requestcredentials - allowedValues: requestCredentials - }, - { - key: 'cache', - converter: webidl.converters.DOMString, - // https://fetch.spec.whatwg.org/#requestcache - allowedValues: requestCache - }, - { - key: 'redirect', - converter: webidl.converters.DOMString, - // https://fetch.spec.whatwg.org/#requestredirect - allowedValues: requestRedirect - }, - { - key: 'integrity', - converter: webidl.converters.DOMString - }, - { - key: 'keepalive', - converter: webidl.converters.boolean - }, - { - key: 'signal', - converter: webidl.nullableConverter( - (signal) => webidl.converters.AbortSignal( - signal, - 'RequestInit', - 'signal' - ) - ) - }, - { - key: 'window', - converter: webidl.converters.any - }, - { - key: 'duplex', - converter: webidl.converters.DOMString, - allowedValues: requestDuplex - }, - { - key: 'dispatcher', // undici specific option - converter: webidl.converters.any - }, - { - key: 'priority', - converter: webidl.converters.DOMString, - allowedValues: ['high', 'low', 'auto'], - defaultValue: () => 'auto' - } -]) - module.exports = { - Request, - makeRequest, - fromInnerRequest, - cloneRequest, - getRequestDispatcher, - getRequestState + fill, + // for test. + compareHeaderName, + Headers, + HeadersList, + getHeadersGuard, + setHeadersGuard, + setHeadersList, + getHeadersList } /***/ }), -/***/ 9294: +/***/ 5288: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; +// https://github.com/Ethan-Arrowood/undici-fetch + -const { Headers, HeadersList, fill, getHeadersGuard, setHeadersGuard, setHeadersList } = __nccwpck_require__(8447) -const { extractBody, cloneBody, mixinBody, streamRegistry, bodyUnusable } = __nccwpck_require__(2921) -const util = __nccwpck_require__(983) -const nodeUtil = __nccwpck_require__(7975) -const { kEnumerableProperty } = util const { - isValidReasonPhrase, + makeNetworkError, + makeAppropriateNetworkError, + filterResponse, + makeResponse, + fromInnerResponse, + getResponseState +} = __nccwpck_require__(4545) +const { HeadersList } = __nccwpck_require__(7754) +const { Request, cloneRequest, getRequestDispatcher, getRequestState } = __nccwpck_require__(4517) +const zlib = __nccwpck_require__(8522) +const { + makePolicyContainer, + clonePolicyContainer, + requestBadPort, + TAOCheck, + appendRequestOriginHeader, + responseLocationURL, + requestCurrentURL, + setRequestReferrerPolicyOnRedirect, + tryUpgradeRequestToAPotentiallyTrustworthyURL, + createOpaqueTimingInfo, + appendFetchMetadata, + corsCheck, + crossOriginResourcePolicyCheck, + determineRequestsReferrer, + coarsenedSharedCurrentTime, + sameOrigin, isCancelled, isAborted, isErrorLike, - environmentSettingsObject: relevantRealm -} = __nccwpck_require__(8913) + fullyReadBody, + readableStreamClose, + urlIsLocal, + urlIsHttpHttpsScheme, + urlHasHttpsScheme, + clampAndCoarsenConnectionTimingInfo, + simpleRangeHeaderValue, + buildContentRange, + createInflate, + extractMimeType, + hasAuthenticationEntry, + includesCredentials, + isTraversableNavigable +} = __nccwpck_require__(3106) +const assert = __nccwpck_require__(4589) +const { safelyExtractBody, extractBody } = __nccwpck_require__(9742) const { redirectStatusSet, - nullBodyStatus -} = __nccwpck_require__(112) -const { webidl } = __nccwpck_require__(2318) -const { URLSerializer } = __nccwpck_require__(9425) -const { kConstruct } = __nccwpck_require__(9562) -const assert = __nccwpck_require__(4589) -const { isomorphicEncode, serializeJavascriptValueToJSONString } = __nccwpck_require__(3883) + nullBodyStatus, + safeMethodsSet, + requestBodyHeader, + subresourceSet +} = __nccwpck_require__(8973) +const EE = __nccwpck_require__(8474) +const { Readable, pipeline, finished, isErrored, isReadable } = __nccwpck_require__(7075) +const { addAbortListener, bufferToLowerCasedHeaderName } = __nccwpck_require__(2550) +const { dataURLProcessor, serializeAMimeType, minimizeSupportedMimeType } = __nccwpck_require__(1410) +const { getGlobalDispatcher } = __nccwpck_require__(7483) +const { webidl } = __nccwpck_require__(909) +const { STATUS_CODES } = __nccwpck_require__(7067) +const { bytesMatch } = __nccwpck_require__(664) +const { createDeferredPromise } = __nccwpck_require__(3022) +const { isomorphicEncode } = __nccwpck_require__(5074) +const { runtimeFeatures } = __nccwpck_require__(3895) -const textEncoder = new TextEncoder('utf-8') +// Node.js v23.8.0+ and v22.15.0+ supports Zstandard +const hasZstd = runtimeFeatures.has('zstd') -// https://fetch.spec.whatwg.org/#response-class -class Response { - /** @type {Headers} */ - #headers +const GET_OR_HEAD = ['GET', 'HEAD'] - #state +const defaultUserAgent = typeof __UNDICI_IS_NODE__ !== 'undefined' || typeof esbuildDetection !== 'undefined' + ? 'node' + : 'undici' - // Creates network error Response. - static error () { - // The static error() method steps are to return the result of creating a - // Response object, given a new network error, "immutable", and this’s - // relevant Realm. - const responseObject = fromInnerResponse(makeNetworkError(), 'immutable') +/** @type {import('buffer').resolveObjectURL} */ +let resolveObjectURL - return responseObject - } +class Fetch extends EE { + constructor (dispatcher) { + super() - // https://fetch.spec.whatwg.org/#dom-response-json - static json (data, init = undefined) { - webidl.argumentLengthCheck(arguments, 1, 'Response.json') + this.dispatcher = dispatcher + this.connection = null + this.dump = false + this.state = 'ongoing' + } - if (init !== null) { - init = webidl.converters.ResponseInit(init) + terminate (reason) { + if (this.state !== 'ongoing') { + return } - // 1. Let bytes the result of running serialize a JavaScript value to JSON bytes on data. - const bytes = textEncoder.encode( - serializeJavascriptValueToJSONString(data) - ) + this.state = 'terminated' + this.connection?.destroy(reason) + this.emit('terminated', reason) + } - // 2. Let body be the result of extracting bytes. - const body = extractBody(bytes) + // https://fetch.spec.whatwg.org/#fetch-controller-abort + abort (error) { + if (this.state !== 'ongoing') { + return + } - // 3. Let responseObject be the result of creating a Response object, given a new response, - // "response", and this’s relevant Realm. - const responseObject = fromInnerResponse(makeResponse({}), 'response') + // 1. Set controller’s state to "aborted". + this.state = 'aborted' - // 4. Perform initialize a response given responseObject, init, and (body, "application/json"). - initializeResponse(responseObject, init, { body: body[0], type: 'application/json' }) + // 2. Let fallbackError be an "AbortError" DOMException. + // 3. Set error to fallbackError if it is not given. + if (!error) { + error = new DOMException('The operation was aborted.', 'AbortError') + } - // 5. Return responseObject. - return responseObject + // 4. Let serializedError be StructuredSerialize(error). + // If that threw an exception, catch it, and let + // serializedError be StructuredSerialize(fallbackError). + + // 5. Set controller’s serialized abort reason to serializedError. + this.serializedAbortReason = error + + this.connection?.destroy(error) + this.emit('terminated', error) } +} - // Creates a redirect Response that redirects to url with status status. - static redirect (url, status = 302) { - webidl.argumentLengthCheck(arguments, 1, 'Response.redirect') +function handleFetchDone (response) { + finalizeAndReportTiming(response, 'fetch') +} - url = webidl.converters.USVString(url) - status = webidl.converters['unsigned short'](status) +// https://fetch.spec.whatwg.org/#fetch-method +function fetch (input, init = undefined) { + webidl.argumentLengthCheck(arguments, 1, 'globalThis.fetch') - // 1. Let parsedURL be the result of parsing url with current settings - // object’s API base URL. - // 2. If parsedURL is failure, then throw a TypeError. - // TODO: base-URL? - let parsedURL - try { - parsedURL = new URL(url, relevantRealm.settingsObject.baseUrl) - } catch (err) { - throw new TypeError(`Failed to parse URL from ${url}`, { cause: err }) - } + // 1. Let p be a new promise. + let p = createDeferredPromise() - // 3. If status is not a redirect status, then throw a RangeError. - if (!redirectStatusSet.has(status)) { - throw new RangeError(`Invalid status code ${status}`) - } + // 2. Let requestObject be the result of invoking the initial value of + // Request as constructor with input and init as arguments. If this throws + // an exception, reject p with it and return p. + let requestObject - // 4. Let responseObject be the result of creating a Response object, - // given a new response, "immutable", and this’s relevant Realm. - const responseObject = fromInnerResponse(makeResponse({}), 'immutable') + try { + requestObject = new Request(input, init) + } catch (e) { + p.reject(e) + return p.promise + } - // 5. Set responseObject’s response’s status to status. - responseObject.#state.status = status + // 3. Let request be requestObject’s request. + const request = getRequestState(requestObject) - // 6. Let value be parsedURL, serialized and isomorphic encoded. - const value = isomorphicEncode(URLSerializer(parsedURL)) + // 4. If requestObject’s signal’s aborted flag is set, then: + if (requestObject.signal.aborted) { + // 1. Abort the fetch() call with p, request, null, and + // requestObject’s signal’s abort reason. + abortFetch(p, request, null, requestObject.signal.reason) - // 7. Append `Location`/value to responseObject’s response’s header list. - responseObject.#state.headersList.append('location', value, true) + // 2. Return p. + return p.promise + } - // 8. Return responseObject. - return responseObject + // 5. Let globalObject be request’s client’s global object. + const globalObject = request.client.globalObject + + // 6. If globalObject is a ServiceWorkerGlobalScope object, then set + // request’s service-workers mode to "none". + if (globalObject?.constructor?.name === 'ServiceWorkerGlobalScope') { + request.serviceWorkers = 'none' } - // https://fetch.spec.whatwg.org/#dom-response - constructor (body = null, init = undefined) { - webidl.util.markAsUncloneable(this) + // 7. Let responseObject be null. + let responseObject = null - if (body === kConstruct) { - return - } + // 8. Let relevantRealm be this’s relevant Realm. - if (body !== null) { - body = webidl.converters.BodyInit(body, 'Response', 'body') - } + // 9. Let locallyAborted be false. + let locallyAborted = false - init = webidl.converters.ResponseInit(init) + // 10. Let controller be null. + let controller = null - // 1. Set this’s response to a new response. - this.#state = makeResponse({}) + // 11. Add the following abort steps to requestObject’s signal: + addAbortListener( + requestObject.signal, + () => { + // 1. Set locallyAborted to true. + locallyAborted = true - // 2. Set this’s headers to a new Headers object with this’s relevant - // Realm, whose header list is this’s response’s header list and guard - // is "response". - this.#headers = new Headers(kConstruct) - setHeadersGuard(this.#headers, 'response') - setHeadersList(this.#headers, this.#state.headersList) + // 2. Assert: controller is non-null. + assert(controller != null) - // 3. Let bodyWithType be null. - let bodyWithType = null + // 3. Abort controller with requestObject’s signal’s abort reason. + controller.abort(requestObject.signal.reason) - // 4. If body is non-null, then set bodyWithType to the result of extracting body. - if (body != null) { - const [extractedBody, type] = extractBody(body) - bodyWithType = { body: extractedBody, type } - } + const realResponse = responseObject?.deref() - // 5. Perform initialize a response given this, init, and bodyWithType. - initializeResponse(this, init, bodyWithType) - } + // 4. Abort the fetch() call with p, request, responseObject, + // and requestObject’s signal’s abort reason. + abortFetch(p, request, realResponse, requestObject.signal.reason) + } + ) - // Returns response’s type, e.g., "cors". - get type () { - webidl.brandCheck(this, Response) + // 12. Let handleFetchDone given response response be to finalize and + // report timing with response, globalObject, and "fetch". + // see function handleFetchDone - // The type getter steps are to return this’s response’s type. - return this.#state.type - } + // 13. Set controller to the result of calling fetch given request, + // with processResponseEndOfBody set to handleFetchDone, and processResponse + // given response being these substeps: - // Returns response’s URL, if it has one; otherwise the empty string. - get url () { - webidl.brandCheck(this, Response) + const processResponse = (response) => { + // 1. If locallyAborted is true, terminate these substeps. + if (locallyAborted) { + return + } - const urlList = this.#state.urlList + // 2. If response’s aborted flag is set, then: + if (response.aborted) { + // 1. Let deserializedError be the result of deserialize a serialized + // abort reason given controller’s serialized abort reason and + // relevantRealm. - // The url getter steps are to return the empty string if this’s - // response’s URL is null; otherwise this’s response’s URL, - // serialized with exclude fragment set to true. - const url = urlList[urlList.length - 1] ?? null + // 2. Abort the fetch() call with p, request, responseObject, and + // deserializedError. - if (url === null) { - return '' + abortFetch(p, request, responseObject, controller.serializedAbortReason) + return } - return URLSerializer(url, true) - } + // 3. If response is a network error, then reject p with a TypeError + // and terminate these substeps. + if (response.type === 'error') { + p.reject(new TypeError('fetch failed', { cause: response.error })) + return + } - // Returns whether response was obtained through a redirect. - get redirected () { - webidl.brandCheck(this, Response) + // 4. Set responseObject to the result of creating a Response object, + // given response, "immutable", and relevantRealm. + responseObject = new WeakRef(fromInnerResponse(response, 'immutable')) - // The redirected getter steps are to return true if this’s response’s URL - // list has more than one item; otherwise false. - return this.#state.urlList.length > 1 + // 5. Resolve p with responseObject. + p.resolve(responseObject.deref()) + p = null } - // Returns response’s status. - get status () { - webidl.brandCheck(this, Response) - - // The status getter steps are to return this’s response’s status. - return this.#state.status - } + controller = fetching({ + request, + processResponseEndOfBody: handleFetchDone, + processResponse, + dispatcher: getRequestDispatcher(requestObject) // undici + }) - // Returns whether response’s status is an ok status. - get ok () { - webidl.brandCheck(this, Response) + // 14. Return p. + return p.promise +} - // The ok getter steps are to return true if this’s response’s status is an - // ok status; otherwise false. - return this.#state.status >= 200 && this.#state.status <= 299 +// https://fetch.spec.whatwg.org/#finalize-and-report-timing +function finalizeAndReportTiming (response, initiatorType = 'other') { + // 1. If response is an aborted network error, then return. + if (response.type === 'error' && response.aborted) { + return } - // Returns response’s status message. - get statusText () { - webidl.brandCheck(this, Response) - - // The statusText getter steps are to return this’s response’s status - // message. - return this.#state.statusText + // 2. If response’s URL list is null or empty, then return. + if (!response.urlList?.length) { + return } - // Returns response’s headers as Headers. - get headers () { - webidl.brandCheck(this, Response) + // 3. Let originalURL be response’s URL list[0]. + const originalURL = response.urlList[0] - // The headers getter steps are to return this’s headers. - return this.#headers - } + // 4. Let timingInfo be response’s timing info. + let timingInfo = response.timingInfo - get body () { - webidl.brandCheck(this, Response) + // 5. Let cacheState be response’s cache state. + let cacheState = response.cacheState - return this.#state.body ? this.#state.body.stream : null + // 6. If originalURL’s scheme is not an HTTP(S) scheme, then return. + if (!urlIsHttpHttpsScheme(originalURL)) { + return } - get bodyUsed () { - webidl.brandCheck(this, Response) - - return !!this.#state.body && util.isDisturbed(this.#state.body.stream) + // 7. If timingInfo is null, then return. + if (timingInfo === null) { + return } - // Returns a clone of response. - clone () { - webidl.brandCheck(this, Response) - - // 1. If this is unusable, then throw a TypeError. - if (bodyUnusable(this.#state)) { - throw webidl.errors.exception({ - header: 'Response.clone', - message: 'Body has already been consumed.' - }) - } - - // 2. Let clonedResponse be the result of cloning this’s response. - const clonedResponse = cloneResponse(this.#state) - - // Note: To re-register because of a new stream. - if (this.#state.body?.stream) { - streamRegistry.register(this, new WeakRef(this.#state.body.stream)) - } + // 8. If response’s timing allow passed flag is not set, then: + if (!response.timingAllowPassed) { + // 1. Set timingInfo to a the result of creating an opaque timing info for timingInfo. + timingInfo = createOpaqueTimingInfo({ + startTime: timingInfo.startTime + }) - // 3. Return the result of creating a Response object, given - // clonedResponse, this’s headers’s guard, and this’s relevant Realm. - return fromInnerResponse(clonedResponse, getHeadersGuard(this.#headers)) + // 2. Set cacheState to the empty string. + cacheState = '' } - [nodeUtil.inspect.custom] (depth, options) { - if (options.depth === null) { - options.depth = 2 - } + // 9. Set timingInfo’s end time to the coarsened shared current time + // given global’s relevant settings object’s cross-origin isolated + // capability. + // TODO: given global’s relevant settings object’s cross-origin isolated + // capability? + timingInfo.endTime = coarsenedSharedCurrentTime() - options.colors ??= true + // 10. Set response’s timing info to timingInfo. + response.timingInfo = timingInfo - const properties = { - status: this.status, - statusText: this.statusText, - headers: this.headers, - body: this.body, - bodyUsed: this.bodyUsed, - ok: this.ok, - redirected: this.redirected, - type: this.type, - url: this.url - } + // 11. Mark resource timing for timingInfo, originalURL, initiatorType, + // global, and cacheState. + markResourceTiming( + timingInfo, + originalURL.href, + initiatorType, + globalThis, + cacheState, + '', // bodyType + response.status + ) +} - return `Response ${nodeUtil.formatWithOptions(options, properties)}` - } +// https://w3c.github.io/resource-timing/#dfn-mark-resource-timing +const markResourceTiming = performance.markResourceTiming - /** - * @param {Response} response - */ - static getResponseHeaders (response) { - return response.#headers +// https://fetch.spec.whatwg.org/#abort-fetch +function abortFetch (p, request, responseObject, error) { + // 1. Reject promise with error. + if (p) { + // We might have already resolved the promise at this stage + p.reject(error) } - /** - * @param {Response} response - * @param {Headers} newHeaders - */ - static setResponseHeaders (response, newHeaders) { - response.#headers = newHeaders + // 2. If request’s body is not null and is readable, then cancel request’s + // body with error. + if (request.body?.stream != null && isReadable(request.body.stream)) { + request.body.stream.cancel(error).catch((err) => { + if (err.code === 'ERR_INVALID_STATE') { + // Node bug? + return + } + throw err + }) } - /** - * @param {Response} response - */ - static getResponseState (response) { - return response.#state + // 3. If responseObject is null, then return. + if (responseObject == null) { + return } - /** - * @param {Response} response - * @param {any} newState - */ - static setResponseState (response, newState) { - response.#state = newState + // 4. Let response be responseObject’s response. + const response = getResponseState(responseObject) + + // 5. If response’s body is not null and is readable, then error response’s + // body with error. + if (response.body?.stream != null && isReadable(response.body.stream)) { + response.body.stream.cancel(error).catch((err) => { + if (err.code === 'ERR_INVALID_STATE') { + // Node bug? + return + } + throw err + }) } } -const { getResponseHeaders, setResponseHeaders, getResponseState, setResponseState } = Response -Reflect.deleteProperty(Response, 'getResponseHeaders') -Reflect.deleteProperty(Response, 'setResponseHeaders') -Reflect.deleteProperty(Response, 'getResponseState') -Reflect.deleteProperty(Response, 'setResponseState') - -mixinBody(Response, getResponseState) +// https://fetch.spec.whatwg.org/#fetching +function fetching ({ + request, + processRequestBodyChunkLength, + processRequestEndOfBody, + processResponse, + processResponseEndOfBody, + processResponseConsumeBody, + useParallelQueue = false, + dispatcher = getGlobalDispatcher() // undici +}) { + // Ensure that the dispatcher is set accordingly + assert(dispatcher) -Object.defineProperties(Response.prototype, { - type: kEnumerableProperty, - url: kEnumerableProperty, - status: kEnumerableProperty, - ok: kEnumerableProperty, - redirected: kEnumerableProperty, - statusText: kEnumerableProperty, - headers: kEnumerableProperty, - clone: kEnumerableProperty, - body: kEnumerableProperty, - bodyUsed: kEnumerableProperty, - [Symbol.toStringTag]: { - value: 'Response', - configurable: true - } -}) + // 1. Let taskDestination be null. + let taskDestination = null -Object.defineProperties(Response, { - json: kEnumerableProperty, - redirect: kEnumerableProperty, - error: kEnumerableProperty -}) + // 2. Let crossOriginIsolatedCapability be false. + let crossOriginIsolatedCapability = false -// https://fetch.spec.whatwg.org/#concept-response-clone -function cloneResponse (response) { - // To clone a response response, run these steps: + // 3. If request’s client is non-null, then: + if (request.client != null) { + // 1. Set taskDestination to request’s client’s global object. + taskDestination = request.client.globalObject - // 1. If response is a filtered response, then return a new identical - // filtered response whose internal response is a clone of response’s - // internal response. - if (response.internalResponse) { - return filterResponse( - cloneResponse(response.internalResponse), - response.type - ) + // 2. Set crossOriginIsolatedCapability to request’s client’s cross-origin + // isolated capability. + crossOriginIsolatedCapability = + request.client.crossOriginIsolatedCapability } - // 2. Let newResponse be a copy of response, except for its body. - const newResponse = makeResponse({ ...response, body: null }) - - // 3. If response’s body is non-null, then set newResponse’s body to the - // result of cloning response’s body. - if (response.body != null) { - newResponse.body = cloneBody(response.body) - } + // 4. If useParallelQueue is true, then set taskDestination to the result of + // starting a new parallel queue. + // TODO - // 4. Return newResponse. - return newResponse -} + // 5. Let timingInfo be a new fetch timing info whose start time and + // post-redirect start time are the coarsened shared current time given + // crossOriginIsolatedCapability. + const currentTime = coarsenedSharedCurrentTime(crossOriginIsolatedCapability) + const timingInfo = createOpaqueTimingInfo({ + startTime: currentTime + }) -function makeResponse (init) { - return { - aborted: false, - rangeRequested: false, - timingAllowPassed: false, - requestIncludesCredentials: false, - type: 'default', - status: 200, - timingInfo: null, - cacheState: '', - statusText: '', - ...init, - headersList: init?.headersList - ? new HeadersList(init?.headersList) - : new HeadersList(), - urlList: init?.urlList ? [...init.urlList] : [] + // 6. Let fetchParams be a new fetch params whose + // request is request, + // timing info is timingInfo, + // process request body chunk length is processRequestBodyChunkLength, + // process request end-of-body is processRequestEndOfBody, + // process response is processResponse, + // process response consume body is processResponseConsumeBody, + // process response end-of-body is processResponseEndOfBody, + // task destination is taskDestination, + // and cross-origin isolated capability is crossOriginIsolatedCapability. + const fetchParams = { + controller: new Fetch(dispatcher), + request, + timingInfo, + processRequestBodyChunkLength, + processRequestEndOfBody, + processResponse, + processResponseConsumeBody, + processResponseEndOfBody, + taskDestination, + crossOriginIsolatedCapability } -} - -function makeNetworkError (reason) { - const isError = isErrorLike(reason) - return makeResponse({ - type: 'error', - status: 0, - error: isError - ? reason - : new Error(reason ? String(reason) : reason), - aborted: reason && reason.name === 'AbortError' - }) -} -// @see https://fetch.spec.whatwg.org/#concept-network-error -function isNetworkError (response) { - return ( - // A network error is a response whose type is "error", - response.type === 'error' && - // status is 0 - response.status === 0 - ) -} + // 7. If request’s body is a byte sequence, then set request’s body to + // request’s body as a body. + // NOTE: Since fetching is only called from fetch, body should already be + // extracted. + assert(!request.body || request.body.stream) -function makeFilteredResponse (response, state) { - state = { - internalResponse: response, - ...state + // 8. If request’s window is "client", then set request’s window to request’s + // client, if request’s client’s global object is a Window object; otherwise + // "no-window". + if (request.window === 'client') { + // TODO: What if request.client is null? + request.window = + request.client?.globalObject?.constructor?.name === 'Window' + ? request.client + : 'no-window' } - return new Proxy(response, { - get (target, p) { - return p in state ? state[p] : target[p] - }, - set (target, p, value) { - assert(!(p in state)) - target[p] = value - return true - } - }) -} - -// https://fetch.spec.whatwg.org/#concept-filtered-response -function filterResponse (response, type) { - // Set response to the following filtered response with response as its - // internal response, depending on request’s response tainting: - if (type === 'basic') { - // A basic filtered response is a filtered response whose type is "basic" - // and header list excludes any headers in internal response’s header list - // whose name is a forbidden response-header name. - - // Note: undici does not implement forbidden response-header names - return makeFilteredResponse(response, { - type: 'basic', - headersList: response.headersList - }) - } else if (type === 'cors') { - // A CORS filtered response is a filtered response whose type is "cors" - // and header list excludes any headers in internal response’s header - // list whose name is not a CORS-safelisted response-header name, given - // internal response’s CORS-exposed header-name list. - - // Note: undici does not implement CORS-safelisted response-header names - return makeFilteredResponse(response, { - type: 'cors', - headersList: response.headersList - }) - } else if (type === 'opaque') { - // An opaque filtered response is a filtered response whose type is - // "opaque", URL list is the empty list, status is 0, status message - // is the empty byte sequence, header list is empty, and body is null. + // 9. If request’s origin is "client", then set request’s origin to request’s + // client’s origin. + if (request.origin === 'client') { + request.origin = request.client.origin + } - return makeFilteredResponse(response, { - type: 'opaque', - urlList: [], - status: 0, - statusText: '', - body: null - }) - } else if (type === 'opaqueredirect') { - // An opaque-redirect filtered response is a filtered response whose type - // is "opaqueredirect", status is 0, status message is the empty byte - // sequence, header list is empty, and body is null. + // 10. If all of the following conditions are true: + // TODO - return makeFilteredResponse(response, { - type: 'opaqueredirect', - status: 0, - statusText: '', - headersList: [], - body: null - }) - } else { - assert(false) + // 11. If request’s policy container is "client", then: + if (request.policyContainer === 'client') { + // 1. If request’s client is non-null, then set request’s policy + // container to a clone of request’s client’s policy container. [HTML] + if (request.client != null) { + request.policyContainer = clonePolicyContainer( + request.client.policyContainer + ) + } else { + // 2. Otherwise, set request’s policy container to a new policy + // container. + request.policyContainer = makePolicyContainer() + } } -} - -// https://fetch.spec.whatwg.org/#appropriate-network-error -function makeAppropriateNetworkError (fetchParams, err = null) { - // 1. Assert: fetchParams is canceled. - assert(isCancelled(fetchParams)) - // 2. Return an aborted network error if fetchParams is aborted; - // otherwise return a network error. - return isAborted(fetchParams) - ? makeNetworkError(Object.assign(new DOMException('The operation was aborted.', 'AbortError'), { cause: err })) - : makeNetworkError(Object.assign(new DOMException('Request was cancelled.'), { cause: err })) -} + // 12. If request’s header list does not contain `Accept`, then: + if (!request.headersList.contains('accept', true)) { + // 1. Let value be `*/*`. + const value = '*/*' -// https://whatpr.org/fetch/1392.html#initialize-a-response -function initializeResponse (response, init, body) { - // 1. If init["status"] is not in the range 200 to 599, inclusive, then - // throw a RangeError. - if (init.status !== null && (init.status < 200 || init.status > 599)) { - throw new RangeError('init["status"] must be in the range of 200 to 599, inclusive.') - } + // 2. A user agent should set value to the first matching statement, if + // any, switching on request’s destination: + // "document" + // "frame" + // "iframe" + // `text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8` + // "image" + // `image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5` + // "style" + // `text/css,*/*;q=0.1` + // TODO - // 2. If init["statusText"] does not match the reason-phrase token production, - // then throw a TypeError. - if ('statusText' in init && init.statusText != null) { - // See, https://datatracker.ietf.org/doc/html/rfc7230#section-3.1.2: - // reason-phrase = *( HTAB / SP / VCHAR / obs-text ) - if (!isValidReasonPhrase(String(init.statusText))) { - throw new TypeError('Invalid statusText') - } + // 3. Append `Accept`/value to request’s header list. + request.headersList.append('accept', value, true) } - // 3. Set response’s response’s status to init["status"]. - if ('status' in init && init.status != null) { - getResponseState(response).status = init.status + // 13. If request’s header list does not contain `Accept-Language`, then + // user agents should append `Accept-Language`/an appropriate value to + // request’s header list. + if (!request.headersList.contains('accept-language', true)) { + request.headersList.append('accept-language', '*', true) } - // 4. Set response’s response’s status message to init["statusText"]. - if ('statusText' in init && init.statusText != null) { - getResponseState(response).statusText = init.statusText + // 14. If request’s priority is null, then use request’s initiator and + // destination appropriately in setting request’s priority to a + // user-agent-defined object. + if (request.priority === null) { + // TODO } - // 5. If init["headers"] exists, then fill response’s headers with init["headers"]. - if ('headers' in init && init.headers != null) { - fill(getResponseHeaders(response), init.headers) + // 15. If request is a subresource request, then: + if (subresourceSet.has(request.destination)) { + // TODO } - // 6. If body was given, then: - if (body) { - // 1. If response's status is a null body status, then throw a TypeError. - if (nullBodyStatus.includes(response.status)) { - throw webidl.errors.exception({ - header: 'Response constructor', - message: `Invalid response status code ${response.status}` - }) - } - - // 2. Set response's body to body's body. - getResponseState(response).body = body.body + // 16. Run main fetch given fetchParams. + mainFetch(fetchParams, false) - // 3. If body's type is non-null and response's header list does not contain - // `Content-Type`, then append (`Content-Type`, body's type) to response's header list. - if (body.type != null && !getResponseState(response).headersList.contains('content-type', true)) { - getResponseState(response).headersList.append('content-type', body.type, true) - } - } + // 17. Return fetchParam's controller + return fetchParams.controller } -/** - * @see https://fetch.spec.whatwg.org/#response-create - * @param {any} innerResponse - * @param {'request' | 'immutable' | 'request-no-cors' | 'response' | 'none'} guard - * @returns {Response} - */ -function fromInnerResponse (innerResponse, guard) { - const response = new Response(kConstruct) - setResponseState(response, innerResponse) - const headers = new Headers(kConstruct) - setResponseHeaders(response, headers) - setHeadersList(headers, innerResponse.headersList) - setHeadersGuard(headers, guard) - - // Note: If innerResponse's urlList contains a URL, it is a fetch response. - if (innerResponse.urlList.length !== 0 && innerResponse.body?.stream) { - // If the target (response) is reclaimed, the cleanup callback may be called at some point with - // the held value provided for it (innerResponse.body.stream). The held value can be any value: - // a primitive or an object, even undefined. If the held value is an object, the registry keeps - // a strong reference to it (so it can pass it to the cleanup callback later). Reworded from - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/FinalizationRegistry - streamRegistry.register(response, new WeakRef(innerResponse.body.stream)) - } +// https://fetch.spec.whatwg.org/#concept-main-fetch +async function mainFetch (fetchParams, recursive) { + try { + // 1. Let request be fetchParams’s request. + const request = fetchParams.request - return response -} + // 2. Let response be null. + let response = null -// https://fetch.spec.whatwg.org/#typedefdef-xmlhttprequestbodyinit -webidl.converters.XMLHttpRequestBodyInit = function (V, prefix, name) { - if (typeof V === 'string') { - return webidl.converters.USVString(V, prefix, name) - } + // 3. If request’s local-URLs-only flag is set and request’s current URL is + // not local, then set response to a network error. + if (request.localURLsOnly && !urlIsLocal(requestCurrentURL(request))) { + response = makeNetworkError('local URLs only') + } - if (webidl.is.Blob(V)) { - return V - } + // 4. Run report Content Security Policy violations for request. + // TODO - if (webidl.is.BufferSource(V)) { - return V - } + // 5. Upgrade request to a potentially trustworthy URL, if appropriate. + tryUpgradeRequestToAPotentiallyTrustworthyURL(request) - if (webidl.is.FormData(V)) { - return V - } + // 6. If should request be blocked due to a bad port, should fetching request + // be blocked as mixed content, or should request be blocked by Content + // Security Policy returns blocked, then set response to a network error. + if (requestBadPort(request) === 'blocked') { + response = makeNetworkError('bad port') + } + // TODO: should fetching request be blocked as mixed content? + // TODO: should request be blocked by Content Security Policy? - if (webidl.is.URLSearchParams(V)) { - return V - } + // 7. If request’s referrer policy is the empty string, then set request’s + // referrer policy to request’s policy container’s referrer policy. + if (request.referrerPolicy === '') { + request.referrerPolicy = request.policyContainer.referrerPolicy + } - return webidl.converters.DOMString(V, prefix, name) -} + // 8. If request’s referrer is not "no-referrer", then set request’s + // referrer to the result of invoking determine request’s referrer. + if (request.referrer !== 'no-referrer') { + request.referrer = determineRequestsReferrer(request) + } -// https://fetch.spec.whatwg.org/#bodyinit -webidl.converters.BodyInit = function (V, prefix, argument) { - if (webidl.is.ReadableStream(V)) { - return V - } + // 9. Set request’s current URL’s scheme to "https" if all of the following + // conditions are true: + // - request’s current URL’s scheme is "http" + // - request’s current URL’s host is a domain + // - Matching request’s current URL’s host per Known HSTS Host Domain Name + // Matching results in either a superdomain match with an asserted + // includeSubDomains directive or a congruent match (with or without an + // asserted includeSubDomains directive). [HSTS] + // TODO - // Note: the spec doesn't include async iterables, - // this is an undici extension. - if (V?.[Symbol.asyncIterator]) { - return V - } + // 10. If recursive is false, then run the remaining steps in parallel. + // TODO - return webidl.converters.XMLHttpRequestBodyInit(V, prefix, argument) -} + // 11. If response is null, then set response to the result of running + // the steps corresponding to the first matching statement: + if (response === null) { + const currentURL = requestCurrentURL(request) + if ( + // - request’s current URL’s origin is same origin with request’s origin, + // and request’s response tainting is "basic" + (sameOrigin(currentURL, request.url) && request.responseTainting === 'basic') || + // request’s current URL’s scheme is "data" + (currentURL.protocol === 'data:') || + // - request’s mode is "navigate" or "websocket" + (request.mode === 'navigate' || request.mode === 'websocket') + ) { + // 1. Set request’s response tainting to "basic". + request.responseTainting = 'basic' -webidl.converters.ResponseInit = webidl.dictionaryConverter([ - { - key: 'status', - converter: webidl.converters['unsigned short'], - defaultValue: () => 200 - }, - { - key: 'statusText', - converter: webidl.converters.ByteString, - defaultValue: () => '' - }, - { - key: 'headers', - converter: webidl.converters.HeadersInit - } -]) + // 2. Return the result of running scheme fetch given fetchParams. + response = await schemeFetch(fetchParams) -webidl.is.Response = webidl.util.MakeTypeAssertion(Response) + // request’s mode is "same-origin" + } else if (request.mode === 'same-origin') { + // 1. Return a network error. + response = makeNetworkError('request mode cannot be "same-origin"') -module.exports = { - isNetworkError, - makeNetworkError, - makeResponse, - makeAppropriateNetworkError, - filterResponse, - Response, - cloneResponse, - fromInnerResponse, - getResponseState -} + // request’s mode is "no-cors" + } else if (request.mode === 'no-cors') { + // 1. If request’s redirect mode is not "follow", then return a network + // error. + if (request.redirect !== 'follow') { + response = makeNetworkError( + 'redirect mode cannot be "follow" for "no-cors" request' + ) + } else { + // 2. Set request’s response tainting to "opaque". + request.responseTainting = 'opaque' + // 3. Return the result of running scheme fetch given fetchParams. + response = await schemeFetch(fetchParams) + } + // request’s current URL’s scheme is not an HTTP(S) scheme + } else if (!urlIsHttpHttpsScheme(requestCurrentURL(request))) { + // Return a network error. + response = makeNetworkError('URL scheme must be a HTTP(S) scheme') -/***/ }), + // - request’s use-CORS-preflight flag is set + // - request’s unsafe-request flag is set and either request’s method is + // not a CORS-safelisted method or CORS-unsafe request-header names with + // request’s header list is not empty + // 1. Set request’s response tainting to "cors". + // 2. Let corsWithPreflightResponse be the result of running HTTP fetch + // given fetchParams and true. + // 3. If corsWithPreflightResponse is a network error, then clear cache + // entries using request. + // 4. Return corsWithPreflightResponse. + // TODO -/***/ 8913: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // Otherwise + } else { + // 1. Set request’s response tainting to "cors". + request.responseTainting = 'cors' -"use strict"; + // 2. Return the result of running HTTP fetch given fetchParams. + response = await httpFetch(fetchParams) + } + } + // 12. If recursive is true, then return response. + if (recursive) { + return response + } -const { Transform } = __nccwpck_require__(7075) -const zlib = __nccwpck_require__(8522) -const { redirectStatusSet, referrerPolicyTokens, badPortsSet } = __nccwpck_require__(112) -const { getGlobalOrigin } = __nccwpck_require__(3862) -const { collectAnHTTPQuotedString, parseMIMEType } = __nccwpck_require__(9425) -const { performance } = __nccwpck_require__(643) -const { ReadableStreamFrom, isValidHTTPToken, normalizedMethodRecordsBase } = __nccwpck_require__(983) -const assert = __nccwpck_require__(4589) -const { isUint8Array } = __nccwpck_require__(3429) -const { webidl } = __nccwpck_require__(2318) -const { isomorphicEncode, collectASequenceOfCodePoints, removeChars } = __nccwpck_require__(3883) + // 13. If response is not a network error and response is not a filtered + // response, then: + if (response.status !== 0 && !response.internalResponse) { + // If request’s response tainting is "cors", then: + if (request.responseTainting === 'cors') { + // 1. Let headerNames be the result of extracting header list values + // given `Access-Control-Expose-Headers` and response’s header list. + // TODO + // 2. If request’s credentials mode is not "include" and headerNames + // contains `*`, then set response’s CORS-exposed header-name list to + // all unique header names in response’s header list. + // TODO + // 3. Otherwise, if headerNames is not null or failure, then set + // response’s CORS-exposed header-name list to headerNames. + // TODO + } -function responseURL (response) { - // https://fetch.spec.whatwg.org/#responses - // A response has an associated URL. It is a pointer to the last URL - // in response’s URL list and null if response’s URL list is empty. - const urlList = response.urlList - const length = urlList.length - return length === 0 ? null : urlList[length - 1].toString() -} + // Set response to the following filtered response with response as its + // internal response, depending on request’s response tainting: + if (request.responseTainting === 'basic') { + response = filterResponse(response, 'basic') + } else if (request.responseTainting === 'cors') { + response = filterResponse(response, 'cors') + } else if (request.responseTainting === 'opaque') { + response = filterResponse(response, 'opaque') + } else { + assert(false) + } + } -// https://fetch.spec.whatwg.org/#concept-response-location-url -function responseLocationURL (response, requestFragment) { - // 1. If response’s status is not a redirect status, then return null. - if (!redirectStatusSet.has(response.status)) { - return null - } + // 14. Let internalResponse be response, if response is a network error, + // and response’s internal response otherwise. + let internalResponse = + response.status === 0 ? response : response.internalResponse - // 2. Let location be the result of extracting header list values given - // `Location` and response’s header list. - let location = response.headersList.get('location', true) + // 15. If internalResponse’s URL list is empty, then set it to a clone of + // request’s URL list. + if (internalResponse.urlList.length === 0) { + internalResponse.urlList.push(...request.urlList) + } - // 3. If location is a header value, then set location to the result of - // parsing location with response’s URL. - if (location !== null && isValidHeaderValue(location)) { - if (!isValidEncodedURL(location)) { - // Some websites respond location header in UTF-8 form without encoding them as ASCII - // and major browsers redirect them to correctly UTF-8 encoded addresses. - // Here, we handle that behavior in the same way. - location = normalizeBinaryStringToUtf8(location) + // 16. If request’s timing allow failed flag is unset, then set + // internalResponse’s timing allow passed flag. + if (!request.timingAllowFailed) { + response.timingAllowPassed = true } - location = new URL(location, responseURL(response)) - } - // 4. If location is a URL whose fragment is null, then set location’s - // fragment to requestFragment. - if (location && !location.hash) { - location.hash = requestFragment - } - - // 5. Return location. - return location -} - -/** - * @see https://www.rfc-editor.org/rfc/rfc1738#section-2.2 - * @param {string} url - * @returns {boolean} - */ -function isValidEncodedURL (url) { - for (let i = 0; i < url.length; ++i) { - const code = url.charCodeAt(i) + // 17. If response is not a network error and any of the following returns + // blocked + // - should internalResponse to request be blocked as mixed content + // - should internalResponse to request be blocked by Content Security Policy + // - should internalResponse to request be blocked due to its MIME type + // - should internalResponse to request be blocked due to nosniff + // TODO + // 18. If response’s type is "opaque", internalResponse’s status is 206, + // internalResponse’s range-requested flag is set, and request’s header + // list does not contain `Range`, then set response and internalResponse + // to a network error. if ( - code > 0x7E || // Non-US-ASCII + DEL - code < 0x20 // Control characters NUL - US + response.type === 'opaque' && + internalResponse.status === 206 && + internalResponse.rangeRequested && + !request.headers.contains('range', true) ) { - return false + response = internalResponse = makeNetworkError() } - } - return true -} -/** - * If string contains non-ASCII characters, assumes it's UTF-8 encoded and decodes it. - * Since UTF-8 is a superset of ASCII, this will work for ASCII strings as well. - * @param {string} value - * @returns {string} - */ -function normalizeBinaryStringToUtf8 (value) { - return Buffer.from(value, 'binary').toString('utf8') -} + // 19. If response is not a network error and either request’s method is + // `HEAD` or `CONNECT`, or internalResponse’s status is a null body status, + // set internalResponse’s body to null and disregard any enqueuing toward + // it (if any). + if ( + response.status !== 0 && + (request.method === 'HEAD' || + request.method === 'CONNECT' || + nullBodyStatus.includes(internalResponse.status)) + ) { + internalResponse.body = null + fetchParams.controller.dump = true + } -/** @returns {URL} */ -function requestCurrentURL (request) { - return request.urlList[request.urlList.length - 1] -} + // 20. If request’s integrity metadata is not the empty string, then: + if (request.integrity) { + // 1. Let processBodyError be this step: run fetch finale given fetchParams + // and a network error. + const processBodyError = (reason) => + fetchFinale(fetchParams, makeNetworkError(reason)) -function requestBadPort (request) { - // 1. Let url be request’s current URL. - const url = requestCurrentURL(request) + // 2. If request’s response tainting is "opaque", or response’s body is null, + // then run processBodyError and abort these steps. + if (request.responseTainting === 'opaque' || response.body == null) { + processBodyError(response.error) + return + } - // 2. If url’s scheme is an HTTP(S) scheme and url’s port is a bad port, - // then return blocked. - if (urlIsHttpHttpsScheme(url) && badPortsSet.has(url.port)) { - return 'blocked' - } + // 3. Let processBody given bytes be these steps: + const processBody = (bytes) => { + // 1. If bytes do not match request’s integrity metadata, + // then run processBodyError and abort these steps. [SRI] + if (!bytesMatch(bytes, request.integrity)) { + processBodyError('integrity mismatch') + return + } - // 3. Return allowed. - return 'allowed' -} + // 2. Set response’s body to bytes as a body. + response.body = safelyExtractBody(bytes)[0] -function isErrorLike (object) { - return object instanceof Error || ( - object?.constructor?.name === 'Error' || - object?.constructor?.name === 'DOMException' - ) -} + // 3. Run fetch finale given fetchParams and response. + fetchFinale(fetchParams, response) + } -// Check whether |statusText| is a ByteString and -// matches the Reason-Phrase token production. -// RFC 2616: https://tools.ietf.org/html/rfc2616 -// RFC 7230: https://tools.ietf.org/html/rfc7230 -// "reason-phrase = *( HTAB / SP / VCHAR / obs-text )" -// https://github.com/chromium/chromium/blob/94.0.4604.1/third_party/blink/renderer/core/fetch/response.cc#L116 -function isValidReasonPhrase (statusText) { - for (let i = 0; i < statusText.length; ++i) { - const c = statusText.charCodeAt(i) - if ( - !( - ( - c === 0x09 || // HTAB - (c >= 0x20 && c <= 0x7e) || // SP / VCHAR - (c >= 0x80 && c <= 0xff) - ) // obs-text - ) - ) { - return false + // 4. Fully read response’s body given processBody and processBodyError. + fullyReadBody(response.body, processBody, processBodyError) + } else { + // 21. Otherwise, run fetch finale given fetchParams and response. + fetchFinale(fetchParams, response) } + } catch (err) { + fetchParams.controller.terminate(err) } - return true } -/** - * @see https://fetch.spec.whatwg.org/#header-name - * @param {string} potentialValue - */ -const isValidHeaderName = isValidHTTPToken - -/** - * @see https://fetch.spec.whatwg.org/#header-value - * @param {string} potentialValue - */ -function isValidHeaderValue (potentialValue) { - // - Has no leading or trailing HTTP tab or space bytes. - // - Contains no 0x00 (NUL) or HTTP newline bytes. - return ( - potentialValue[0] === '\t' || - potentialValue[0] === ' ' || - potentialValue[potentialValue.length - 1] === '\t' || - potentialValue[potentialValue.length - 1] === ' ' || - potentialValue.includes('\n') || - potentialValue.includes('\r') || - potentialValue.includes('\0') - ) === false -} +// https://fetch.spec.whatwg.org/#concept-scheme-fetch +// given a fetch params fetchParams +function schemeFetch (fetchParams) { + // Note: since the connection is destroyed on redirect, which sets fetchParams to a + // cancelled state, we do not want this condition to trigger *unless* there have been + // no redirects. See https://github.com/nodejs/undici/issues/1776 + // 1. If fetchParams is canceled, then return the appropriate network error for fetchParams. + if (isCancelled(fetchParams) && fetchParams.request.redirectCount === 0) { + return Promise.resolve(makeAppropriateNetworkError(fetchParams)) + } -/** - * Parse a referrer policy from a Referrer-Policy header - * @see https://w3c.github.io/webappsec-referrer-policy/#parse-referrer-policy-from-header - */ -function parseReferrerPolicy (actualResponse) { - // 1. Let policy-tokens be the result of extracting header list values given `Referrer-Policy` and response’s header list. - const policyHeader = (actualResponse.headersList.get('referrer-policy', true) ?? '').split(',') + // 2. Let request be fetchParams’s request. + const { request } = fetchParams - // 2. Let policy be the empty string. - let policy = '' + const { protocol: scheme } = requestCurrentURL(request) - // 3. For each token in policy-tokens, if token is a referrer policy and token is not the empty string, then set policy to token. + // 3. Switch on request’s current URL’s scheme and run the associated steps: + switch (scheme) { + case 'about:': { + // If request’s current URL’s path is the string "blank", then return a new response + // whose status message is `OK`, header list is « (`Content-Type`, `text/html;charset=utf-8`) », + // and body is the empty byte sequence as a body. - // Note: As the referrer-policy can contain multiple policies - // separated by comma, we need to loop through all of them - // and pick the first valid one. - // Ref: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy#specify_a_fallback_policy - if (policyHeader.length) { - // The right-most policy takes precedence. - // The left-most policy is the fallback. - for (let i = policyHeader.length; i !== 0; i--) { - const token = policyHeader[i - 1].trim() - if (referrerPolicyTokens.has(token)) { - policy = token - break - } + // Otherwise, return a network error. + return Promise.resolve(makeNetworkError('about scheme is not supported')) } - } - - // 4. Return policy. - return policy -} + case 'blob:': { + if (!resolveObjectURL) { + resolveObjectURL = (__nccwpck_require__(4573).resolveObjectURL) + } -/** - * Given a request request and a response actualResponse, this algorithm - * updates request’s referrer policy according to the Referrer-Policy - * header (if any) in actualResponse. - * @see https://w3c.github.io/webappsec-referrer-policy/#set-requests-referrer-policy-on-redirect - * @param {import('./request').Request} request - * @param {import('./response').Response} actualResponse - */ -function setRequestReferrerPolicyOnRedirect (request, actualResponse) { - // 1. Let policy be the result of executing § 8.1 Parse a referrer policy - // from a Referrer-Policy header on actualResponse. - const policy = parseReferrerPolicy(actualResponse) + // 1. Let blobURLEntry be request’s current URL’s blob URL entry. + const blobURLEntry = requestCurrentURL(request) - // 2. If policy is not the empty string, then set request’s referrer policy to policy. - if (policy !== '') { - request.referrerPolicy = policy - } -} + // https://github.com/web-platform-tests/wpt/blob/7b0ebaccc62b566a1965396e5be7bb2bc06f841f/FileAPI/url/resources/fetch-tests.js#L52-L56 + // Buffer.resolveObjectURL does not ignore URL queries. + if (blobURLEntry.search.length !== 0) { + return Promise.resolve(makeNetworkError('NetworkError when attempting to fetch resource.')) + } -// https://fetch.spec.whatwg.org/#cross-origin-resource-policy-check -function crossOriginResourcePolicyCheck () { - // TODO - return 'allowed' -} + const blob = resolveObjectURL(blobURLEntry.toString()) -// https://fetch.spec.whatwg.org/#concept-cors-check -function corsCheck () { - // TODO - return 'success' -} + // 2. If request’s method is not `GET`, blobURLEntry is null, or blobURLEntry’s + // object is not a Blob object, then return a network error. + if (request.method !== 'GET' || !webidl.is.Blob(blob)) { + return Promise.resolve(makeNetworkError('invalid method')) + } -// https://fetch.spec.whatwg.org/#concept-tao-check -function TAOCheck () { - // TODO - return 'success' -} + // 3. Let blob be blobURLEntry’s object. + // Note: done above -function appendFetchMetadata (httpRequest) { - // https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-dest-header - // TODO + // 4. Let response be a new response. + const response = makeResponse() - // https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-mode-header + // 5. Let fullLength be blob’s size. + const fullLength = blob.size - // 1. Assert: r’s url is a potentially trustworthy URL. - // TODO + // 6. Let serializedFullLength be fullLength, serialized and isomorphic encoded. + const serializedFullLength = isomorphicEncode(`${fullLength}`) - // 2. Let header be a Structured Header whose value is a token. - let header = null + // 7. Let type be blob’s type. + const type = blob.type - // 3. Set header’s value to r’s mode. - header = httpRequest.mode + // 8. If request’s header list does not contain `Range`: + // 9. Otherwise: + if (!request.headersList.contains('range', true)) { + // 1. Let bodyWithType be the result of safely extracting blob. + // Note: in the FileAPI a blob "object" is a Blob *or* a MediaSource. + // In node, this can only ever be a Blob. Therefore we can safely + // use extractBody directly. + const bodyWithType = extractBody(blob) - // 4. Set a structured field value `Sec-Fetch-Mode`/header in r’s header list. - httpRequest.headersList.set('sec-fetch-mode', header, true) + // 2. Set response’s status message to `OK`. + response.statusText = 'OK' - // https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-site-header - // TODO + // 3. Set response’s body to bodyWithType’s body. + response.body = bodyWithType[0] - // https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-user-header - // TODO -} + // 4. Set response’s header list to « (`Content-Length`, serializedFullLength), (`Content-Type`, type) ». + response.headersList.set('content-length', serializedFullLength, true) + response.headersList.set('content-type', type, true) + } else { + // 1. Set response’s range-requested flag. + response.rangeRequested = true -// https://fetch.spec.whatwg.org/#append-a-request-origin-header -function appendRequestOriginHeader (request) { - // 1. Let serializedOrigin be the result of byte-serializing a request origin - // with request. - // TODO: implement "byte-serializing a request origin" - let serializedOrigin = request.origin + // 2. Let rangeHeader be the result of getting `Range` from request’s header list. + const rangeHeader = request.headersList.get('range', true) - // - "'client' is changed to an origin during fetching." - // This doesn't happen in undici (in most cases) because undici, by default, - // has no concept of origin. - // - request.origin can also be set to request.client.origin (client being - // an environment settings object), which is undefined without using - // setGlobalOrigin. - if (serializedOrigin === 'client' || serializedOrigin === undefined) { - return - } + // 3. Let rangeValue be the result of parsing a single range header value given rangeHeader and true. + const rangeValue = simpleRangeHeaderValue(rangeHeader, true) - // 2. If request’s response tainting is "cors" or request’s mode is "websocket", - // then append (`Origin`, serializedOrigin) to request’s header list. - // 3. Otherwise, if request’s method is neither `GET` nor `HEAD`, then: - if (request.responseTainting === 'cors' || request.mode === 'websocket') { - request.headersList.append('origin', serializedOrigin, true) - } else if (request.method !== 'GET' && request.method !== 'HEAD') { - // 1. Switch on request’s referrer policy: - switch (request.referrerPolicy) { - case 'no-referrer': - // Set serializedOrigin to `null`. - serializedOrigin = null - break - case 'no-referrer-when-downgrade': - case 'strict-origin': - case 'strict-origin-when-cross-origin': - // If request’s origin is a tuple origin, its scheme is "https", and - // request’s current URL’s scheme is not "https", then set - // serializedOrigin to `null`. - if (request.origin && urlHasHttpsScheme(request.origin) && !urlHasHttpsScheme(requestCurrentURL(request))) { - serializedOrigin = null - } - break - case 'same-origin': - // If request’s origin is not same origin with request’s current URL’s - // origin, then set serializedOrigin to `null`. - if (!sameOrigin(request, requestCurrentURL(request))) { - serializedOrigin = null + // 4. If rangeValue is failure, then return a network error. + if (rangeValue === 'failure') { + return Promise.resolve(makeNetworkError('failed to fetch the data URL')) } - break - default: - // Do nothing. - } - // 2. Append (`Origin`, serializedOrigin) to request’s header list. - request.headersList.append('origin', serializedOrigin, true) - } -} + // 5. Let (rangeStart, rangeEnd) be rangeValue. + let { rangeStartValue: rangeStart, rangeEndValue: rangeEnd } = rangeValue -// https://w3c.github.io/hr-time/#dfn-coarsen-time -function coarsenTime (timestamp, crossOriginIsolatedCapability) { - // TODO - return timestamp -} + // 6. If rangeStart is null: + // 7. Otherwise: + if (rangeStart === null) { + // 1. Set rangeStart to fullLength − rangeEnd. + rangeStart = fullLength - rangeEnd -// https://fetch.spec.whatwg.org/#clamp-and-coarsen-connection-timing-info -function clampAndCoarsenConnectionTimingInfo (connectionTimingInfo, defaultStartTime, crossOriginIsolatedCapability) { - if (!connectionTimingInfo?.startTime || connectionTimingInfo.startTime < defaultStartTime) { - return { - domainLookupStartTime: defaultStartTime, - domainLookupEndTime: defaultStartTime, - connectionStartTime: defaultStartTime, - connectionEndTime: defaultStartTime, - secureConnectionStartTime: defaultStartTime, - ALPNNegotiatedProtocol: connectionTimingInfo?.ALPNNegotiatedProtocol - } - } + // 2. Set rangeEnd to rangeStart + rangeEnd − 1. + rangeEnd = rangeStart + rangeEnd - 1 + } else { + // 1. If rangeStart is greater than or equal to fullLength, then return a network error. + if (rangeStart >= fullLength) { + return Promise.resolve(makeNetworkError('Range start is greater than the blob\'s size.')) + } - return { - domainLookupStartTime: coarsenTime(connectionTimingInfo.domainLookupStartTime, crossOriginIsolatedCapability), - domainLookupEndTime: coarsenTime(connectionTimingInfo.domainLookupEndTime, crossOriginIsolatedCapability), - connectionStartTime: coarsenTime(connectionTimingInfo.connectionStartTime, crossOriginIsolatedCapability), - connectionEndTime: coarsenTime(connectionTimingInfo.connectionEndTime, crossOriginIsolatedCapability), - secureConnectionStartTime: coarsenTime(connectionTimingInfo.secureConnectionStartTime, crossOriginIsolatedCapability), - ALPNNegotiatedProtocol: connectionTimingInfo.ALPNNegotiatedProtocol - } -} + // 2. If rangeEnd is null or rangeEnd is greater than or equal to fullLength, then set + // rangeEnd to fullLength − 1. + if (rangeEnd === null || rangeEnd >= fullLength) { + rangeEnd = fullLength - 1 + } + } -// https://w3c.github.io/hr-time/#dfn-coarsened-shared-current-time -function coarsenedSharedCurrentTime (crossOriginIsolatedCapability) { - return coarsenTime(performance.now(), crossOriginIsolatedCapability) -} + // 8. Let slicedBlob be the result of invoking slice blob given blob, rangeStart, + // rangeEnd + 1, and type. + const slicedBlob = blob.slice(rangeStart, rangeEnd + 1, type) -// https://fetch.spec.whatwg.org/#create-an-opaque-timing-info -function createOpaqueTimingInfo (timingInfo) { - return { - startTime: timingInfo.startTime ?? 0, - redirectStartTime: 0, - redirectEndTime: 0, - postRedirectStartTime: timingInfo.startTime ?? 0, - finalServiceWorkerStartTime: 0, - finalNetworkResponseStartTime: 0, - finalNetworkRequestStartTime: 0, - endTime: 0, - encodedBodySize: 0, - decodedBodySize: 0, - finalConnectionTimingInfo: null - } -} + // 9. Let slicedBodyWithType be the result of safely extracting slicedBlob. + // Note: same reason as mentioned above as to why we use extractBody + const slicedBodyWithType = extractBody(slicedBlob) -// https://html.spec.whatwg.org/multipage/origin.html#policy-container -function makePolicyContainer () { - // Note: the fetch spec doesn't make use of embedder policy or CSP list - return { - referrerPolicy: 'strict-origin-when-cross-origin' - } -} + // 10. Set response’s body to slicedBodyWithType’s body. + response.body = slicedBodyWithType[0] -// https://html.spec.whatwg.org/multipage/origin.html#clone-a-policy-container -function clonePolicyContainer (policyContainer) { - return { - referrerPolicy: policyContainer.referrerPolicy - } -} + // 11. Let serializedSlicedLength be slicedBlob’s size, serialized and isomorphic encoded. + const serializedSlicedLength = isomorphicEncode(`${slicedBlob.size}`) -/** - * Determine request’s Referrer - * - * @see https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer - */ -function determineRequestsReferrer (request) { - // Given a request request, we can determine the correct referrer information - // to send by examining its referrer policy as detailed in the following - // steps, which return either no referrer or a URL: + // 12. Let contentRange be the result of invoking build a content range given rangeStart, + // rangeEnd, and fullLength. + const contentRange = buildContentRange(rangeStart, rangeEnd, fullLength) - // 1. Let policy be request's referrer policy. - const policy = request.referrerPolicy + // 13. Set response’s status to 206. + response.status = 206 - // Note: policy cannot (shouldn't) be null or an empty string. - assert(policy) + // 14. Set response’s status message to `Partial Content`. + response.statusText = 'Partial Content' - // 2. Let environment be request’s client. + // 15. Set response’s header list to « (`Content-Length`, serializedSlicedLength), + // (`Content-Type`, type), (`Content-Range`, contentRange) ». + response.headersList.set('content-length', serializedSlicedLength, true) + response.headersList.set('content-type', type, true) + response.headersList.set('content-range', contentRange, true) + } - let referrerSource = null + // 10. Return response. + return Promise.resolve(response) + } + case 'data:': { + // 1. Let dataURLStruct be the result of running the + // data: URL processor on request’s current URL. + const currentURL = requestCurrentURL(request) + const dataURLStruct = dataURLProcessor(currentURL) - // 3. Switch on request’s referrer: + // 2. If dataURLStruct is failure, then return a + // network error. + if (dataURLStruct === 'failure') { + return Promise.resolve(makeNetworkError('failed to fetch the data URL')) + } - // "client" - if (request.referrer === 'client') { - // Note: node isn't a browser and doesn't implement document/iframes, - // so we bypass this step and replace it with our own. + // 3. Let mimeType be dataURLStruct’s MIME type, serialized. + const mimeType = serializeAMimeType(dataURLStruct.mimeType) - const globalOrigin = getGlobalOrigin() + // 4. Return a response whose status message is `OK`, + // header list is « (`Content-Type`, mimeType) », + // and body is dataURLStruct’s body as a body. + return Promise.resolve(makeResponse({ + statusText: 'OK', + headersList: [ + ['content-type', { name: 'Content-Type', value: mimeType }] + ], + body: safelyExtractBody(dataURLStruct.body)[0] + })) + } + case 'file:': { + // For now, unfortunate as it is, file URLs are left as an exercise for the reader. + // When in doubt, return a network error. + return Promise.resolve(makeNetworkError('not implemented... yet...')) + } + case 'http:': + case 'https:': { + // Return the result of running HTTP fetch given fetchParams. - if (!globalOrigin || globalOrigin.origin === 'null') { - return 'no-referrer' + return httpFetch(fetchParams) + .catch((err) => makeNetworkError(err)) + } + default: { + return Promise.resolve(makeNetworkError('unknown scheme')) } + } +} - // Note: we need to clone it as it's mutated - referrerSource = new URL(globalOrigin) - // a URL - } else if (webidl.is.URL(request.referrer)) { - // Let referrerSource be request’s referrer. - referrerSource = request.referrer +// https://fetch.spec.whatwg.org/#finalize-response +function finalizeResponse (fetchParams, response) { + // 1. Set fetchParams’s request’s done flag. + fetchParams.request.done = true + + // 2, If fetchParams’s process response done is not null, then queue a fetch + // task to run fetchParams’s process response done given response, with + // fetchParams’s task destination. + if (fetchParams.processResponseDone != null) { + queueMicrotask(() => fetchParams.processResponseDone(response)) } +} - // 4. Let request’s referrerURL be the result of stripping referrerSource for - // use as a referrer. - let referrerURL = stripURLForReferrer(referrerSource) +// https://fetch.spec.whatwg.org/#fetch-finale +function fetchFinale (fetchParams, response) { + // 1. Let timingInfo be fetchParams’s timing info. + let timingInfo = fetchParams.timingInfo - // 5. Let referrerOrigin be the result of stripping referrerSource for use as - // a referrer, with the origin-only flag set to true. - const referrerOrigin = stripURLForReferrer(referrerSource, true) + // 2. If response is not a network error and fetchParams’s request’s client is a secure context, + // then set timingInfo’s server-timing headers to the result of getting, decoding, and splitting + // `Server-Timing` from response’s internal response’s header list. + // TODO - // 6. If the result of serializing referrerURL is a string whose length is - // greater than 4096, set referrerURL to referrerOrigin. - if (referrerURL.toString().length > 4096) { - referrerURL = referrerOrigin - } + // 3. Let processResponseEndOfBody be the following steps: + const processResponseEndOfBody = () => { + // 1. Let unsafeEndTime be the unsafe shared current time. + const unsafeEndTime = Date.now() // ? - // 7. The user agent MAY alter referrerURL or referrerOrigin at this point - // to enforce arbitrary policy considerations in the interests of minimizing - // data leakage. For example, the user agent could strip the URL down to an - // origin, modify its host, replace it with an empty string, etc. + // 2. If fetchParams’s request’s destination is "document", then set fetchParams’s controller’s + // full timing info to fetchParams’s timing info. + if (fetchParams.request.destination === 'document') { + fetchParams.controller.fullTimingInfo = timingInfo + } - // 8. Execute the switch statements corresponding to the value of policy: - switch (policy) { - case 'no-referrer': - // Return no referrer - return 'no-referrer' - case 'origin': - // Return referrerOrigin - if (referrerOrigin != null) { - return referrerOrigin + // 3. Set fetchParams’s controller’s report timing steps to the following steps given a global object global: + fetchParams.controller.reportTimingSteps = () => { + // 1. If fetchParams’s request’s URL’s scheme is not an HTTP(S) scheme, then return. + if (!urlIsHttpHttpsScheme(fetchParams.request.url)) { + return } - return stripURLForReferrer(referrerSource, true) - case 'unsafe-url': - // Return referrerURL. - return referrerURL - case 'strict-origin': { - const currentURL = requestCurrentURL(request) - // 1. If referrerURL is a potentially trustworthy URL and request’s - // current URL is not a potentially trustworthy URL, then return no - // referrer. - if (isURLPotentiallyTrustworthy(referrerURL) && !isURLPotentiallyTrustworthy(currentURL)) { - return 'no-referrer' - } - // 2. Return referrerOrigin - return referrerOrigin - } - case 'strict-origin-when-cross-origin': { - const currentURL = requestCurrentURL(request) + // 2. Set timingInfo’s end time to the relative high resolution time given unsafeEndTime and global. + timingInfo.endTime = unsafeEndTime - // 1. If the origin of referrerURL and the origin of request’s current - // URL are the same, then return referrerURL. - if (sameOrigin(referrerURL, currentURL)) { - return referrerURL - } + // 3. Let cacheState be response’s cache state. + let cacheState = response.cacheState - // 2. If referrerURL is a potentially trustworthy URL and request’s - // current URL is not a potentially trustworthy URL, then return no - // referrer. - if (isURLPotentiallyTrustworthy(referrerURL) && !isURLPotentiallyTrustworthy(currentURL)) { - return 'no-referrer' - } + // 4. Let bodyInfo be response’s body info. + const bodyInfo = response.bodyInfo - // 3. Return referrerOrigin. - return referrerOrigin - } - case 'same-origin': - // 1. If the origin of referrerURL and the origin of request’s current - // URL are the same, then return referrerURL. - if (sameOrigin(request, referrerURL)) { - return referrerURL + // 5. If response’s timing allow passed flag is not set, then set timingInfo to the result of creating an + // opaque timing info for timingInfo and set cacheState to the empty string. + if (!response.timingAllowPassed) { + timingInfo = createOpaqueTimingInfo(timingInfo) + + cacheState = '' } - // 2. Return no referrer. - return 'no-referrer' - case 'origin-when-cross-origin': - // 1. If the origin of referrerURL and the origin of request’s current - // URL are the same, then return referrerURL. - if (sameOrigin(request, referrerURL)) { - return referrerURL + + // 6. Let responseStatus be 0. + let responseStatus = 0 + + // 7. If fetchParams’s request’s mode is not "navigate" or response’s has-cross-origin-redirects is false: + if (fetchParams.request.mode !== 'navigator' || !response.hasCrossOriginRedirects) { + // 1. Set responseStatus to response’s status. + responseStatus = response.status + + // 2. Let mimeType be the result of extracting a MIME type from response’s header list. + const mimeType = extractMimeType(response.headersList) + + // 3. If mimeType is not failure, then set bodyInfo’s content type to the result of minimizing a supported MIME type given mimeType. + if (mimeType !== 'failure') { + bodyInfo.contentType = minimizeSupportedMimeType(mimeType) + } } - // 2. Return referrerOrigin. - return referrerOrigin - case 'no-referrer-when-downgrade': { - const currentURL = requestCurrentURL(request) - // 1. If referrerURL is a potentially trustworthy URL and request’s - // current URL is not a potentially trustworthy URL, then return no - // referrer. - if (isURLPotentiallyTrustworthy(referrerURL) && !isURLPotentiallyTrustworthy(currentURL)) { - return 'no-referrer' + // 8. If fetchParams’s request’s initiator type is non-null, then mark resource timing given timingInfo, + // fetchParams’s request’s URL, fetchParams’s request’s initiator type, global, cacheState, bodyInfo, + // and responseStatus. + if (fetchParams.request.initiatorType != null) { + markResourceTiming(timingInfo, fetchParams.request.url.href, fetchParams.request.initiatorType, globalThis, cacheState, bodyInfo, responseStatus) } - // 2. Return referrerURL. - return referrerURL } - } -} -/** - * Certain portions of URLs must not be included when sending a URL as the - * value of a `Referer` header: a URLs fragment, username, and password - * components must be stripped from the URL before it’s sent out. This - * algorithm accepts a origin-only flag, which defaults to false. If set to - * true, the algorithm will additionally remove the URL’s path and query - * components, leaving only the scheme, host, and port. - * - * @see https://w3c.github.io/webappsec-referrer-policy/#strip-url - * @param {URL} url - * @param {boolean} [originOnly=false] - */ -function stripURLForReferrer (url, originOnly = false) { - // 1. Assert: url is a URL. - assert(webidl.is.URL(url)) + // 4. Let processResponseEndOfBodyTask be the following steps: + const processResponseEndOfBodyTask = () => { + // 1. Set fetchParams’s request’s done flag. + fetchParams.request.done = true - // Note: Create a new URL instance to avoid mutating the original URL. - url = new URL(url) + // 2. If fetchParams’s process response end-of-body is non-null, then run fetchParams’s process + // response end-of-body given response. + if (fetchParams.processResponseEndOfBody != null) { + queueMicrotask(() => fetchParams.processResponseEndOfBody(response)) + } - // 2. If url’s scheme is a local scheme, then return no referrer. - if (urlIsLocal(url)) { - return 'no-referrer' + // 3. If fetchParams’s request’s initiator type is non-null and fetchParams’s request’s client’s + // global object is fetchParams’s task destination, then run fetchParams’s controller’s report + // timing steps given fetchParams’s request’s client’s global object. + if (fetchParams.request.initiatorType != null) { + fetchParams.controller.reportTimingSteps() + } + } + + // 5. Queue a fetch task to run processResponseEndOfBodyTask with fetchParams’s task destination + queueMicrotask(() => processResponseEndOfBodyTask()) } - // 3. Set url’s username to the empty string. - url.username = '' + // 4. If fetchParams’s process response is non-null, then queue a fetch task to run fetchParams’s + // process response given response, with fetchParams’s task destination. + if (fetchParams.processResponse != null) { + queueMicrotask(() => { + fetchParams.processResponse(response) + fetchParams.processResponse = null + }) + } - // 4. Set url’s password to the empty string. - url.password = '' + // 5. Let internalResponse be response, if response is a network error; otherwise response’s internal response. + const internalResponse = response.type === 'error' ? response : (response.internalResponse ?? response) - // 5. Set url’s fragment to null. - url.hash = '' + // 6. If internalResponse’s body is null, then run processResponseEndOfBody. + // 7. Otherwise: + if (internalResponse.body == null) { + processResponseEndOfBody() + } else { + // mcollina: all the following steps of the specs are skipped. + // The internal transform stream is not needed. + // See https://github.com/nodejs/undici/pull/3093#issuecomment-2050198541 - // 6. If the origin-only flag is true, then: - if (originOnly === true) { - // 1. Set url’s path to « the empty string ». - url.pathname = '' + // 1. Let transformStream be a new TransformStream. + // 2. Let identityTransformAlgorithm be an algorithm which, given chunk, enqueues chunk in transformStream. + // 3. Set up transformStream with transformAlgorithm set to identityTransformAlgorithm and flushAlgorithm + // set to processResponseEndOfBody. + // 4. Set internalResponse’s body’s stream to the result of internalResponse’s body’s stream piped through transformStream. - // 2. Set url’s query to null. - url.search = '' + finished(internalResponse.body.stream, () => { + processResponseEndOfBody() + }) } - - // 7. Return url. - return url } -const isPotentialleTrustworthyIPv4 = RegExp.prototype.test - .bind(/^127\.(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)\.){2}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)$/) +// https://fetch.spec.whatwg.org/#http-fetch +async function httpFetch (fetchParams) { + // 1. Let request be fetchParams’s request. + const request = fetchParams.request -const isPotentiallyTrustworthyIPv6 = RegExp.prototype.test - .bind(/^(?:(?:0{1,4}:){7}|(?:0{1,4}:){1,6}:|::)0{0,3}1$/) + // 2. Let response be null. + let response = null -/** - * Check if host matches one of the CIDR notations 127.0.0.0/8 or ::1/128. - * - * @param {string} origin - * @returns {boolean} - */ -function isOriginIPPotentiallyTrustworthy (origin) { - // IPv6 - if (origin.includes(':')) { - // Remove brackets from IPv6 addresses - if (origin[0] === '[' && origin[origin.length - 1] === ']') { - origin = origin.slice(1, -1) - } - return isPotentiallyTrustworthyIPv6(origin) - } + // 3. Let actualResponse be null. + let actualResponse = null - // IPv4 - return isPotentialleTrustworthyIPv4(origin) -} + // 4. Let timingInfo be fetchParams’s timing info. + const timingInfo = fetchParams.timingInfo -/** - * A potentially trustworthy origin is one which a user agent can generally - * trust as delivering data securely. - * - * Return value `true` means `Potentially Trustworthy`. - * Return value `false` means `Not Trustworthy`. - * - * @see https://w3c.github.io/webappsec-secure-contexts/#is-origin-trustworthy - * @param {string} origin - * @returns {boolean} - */ -function isOriginPotentiallyTrustworthy (origin) { - // 1. If origin is an opaque origin, return "Not Trustworthy". - if (origin == null || origin === 'null') { - return false + // 5. If request’s service-workers mode is "all", then: + if (request.serviceWorkers === 'all') { + // TODO } - // 2. Assert: origin is a tuple origin. - origin = new URL(origin) + // 6. If response is null, then: + if (response === null) { + // 1. If makeCORSPreflight is true and one of these conditions is true: + // TODO - // 3. If origin’s scheme is either "https" or "wss", - // return "Potentially Trustworthy". - if (origin.protocol === 'https:' || origin.protocol === 'wss:') { - return true - } + // 2. If request’s redirect mode is "follow", then set request’s + // service-workers mode to "none". + if (request.redirect === 'follow') { + request.serviceWorkers = 'none' + } - // 4. If origin’s host matches one of the CIDR notations 127.0.0.0/8 or - // ::1/128 [RFC4632], return "Potentially Trustworthy". - if (isOriginIPPotentiallyTrustworthy(origin.hostname)) { - return true - } + // 3. Set response and actualResponse to the result of running + // HTTP-network-or-cache fetch given fetchParams. + actualResponse = response = await httpNetworkOrCacheFetch(fetchParams) - // 5. If the user agent conforms to the name resolution rules in - // [let-localhost-be-localhost] and one of the following is true: + // 4. If request’s response tainting is "cors" and a CORS check + // for request and response returns failure, then return a network error. + if ( + request.responseTainting === 'cors' && + corsCheck(request, response) === 'failure' + ) { + return makeNetworkError('cors failure') + } - // origin’s host is "localhost" or "localhost." - if (origin.hostname === 'localhost' || origin.hostname === 'localhost.') { - return true + // 5. If the TAO check for request and response returns failure, then set + // request’s timing allow failed flag. + if (TAOCheck(request, response) === 'failure') { + request.timingAllowFailed = true + } } - // origin’s host ends with ".localhost" or ".localhost." - if (origin.hostname.endsWith('.localhost') || origin.hostname.endsWith('.localhost.')) { - return true + // 7. If either request’s response tainting or response’s type + // is "opaque", and the cross-origin resource policy check with + // request’s origin, request’s client, request’s destination, + // and actualResponse returns blocked, then return a network error. + if ( + (request.responseTainting === 'opaque' || response.type === 'opaque') && + crossOriginResourcePolicyCheck( + request.origin, + request.client, + request.destination, + actualResponse + ) === 'blocked' + ) { + return makeNetworkError('blocked') } - // 6. If origin’s scheme is "file", return "Potentially Trustworthy". - if (origin.protocol === 'file:') { - return true - } + // 8. If actualResponse’s status is a redirect status, then: + if (redirectStatusSet.has(actualResponse.status)) { + // 1. If actualResponse’s status is not 303, request’s body is not null, + // and the connection uses HTTP/2, then user agents may, and are even + // encouraged to, transmit an RST_STREAM frame. + // See, https://github.com/whatwg/fetch/issues/1288 + if (request.redirect !== 'manual') { + fetchParams.controller.connection.destroy(undefined, false) + } - // 7. If origin’s scheme component is one which the user agent considers to - // be authenticated, return "Potentially Trustworthy". + // 2. Switch on request’s redirect mode: + if (request.redirect === 'error') { + // Set response to a network error. + response = makeNetworkError('unexpected redirect') + } else if (request.redirect === 'manual') { + // Set response to an opaque-redirect filtered response whose internal + // response is actualResponse. + // NOTE(spec): On the web this would return an `opaqueredirect` response, + // but that doesn't make sense server side. + // See https://github.com/nodejs/undici/issues/1193. + response = actualResponse + } else if (request.redirect === 'follow') { + // Set response to the result of running HTTP-redirect fetch given + // fetchParams and response. + response = await httpRedirectFetch(fetchParams, response) + } else { + assert(false) + } + } - // 8. If origin has been configured as a trustworthy origin, return - // "Potentially Trustworthy". + // 9. Set response’s timing info to timingInfo. + response.timingInfo = timingInfo - // 9. Return "Not Trustworthy". - return false + // 10. Return response. + return response } -/** - * A potentially trustworthy URL is one which either inherits context from its - * creator (about:blank, about:srcdoc, data) or one whose origin is a - * potentially trustworthy origin. - * - * Return value `true` means `Potentially Trustworthy`. - * Return value `false` means `Not Trustworthy`. - * - * @see https://www.w3.org/TR/secure-contexts/#is-url-trustworthy - * @param {URL} url - * @returns {boolean} - */ -function isURLPotentiallyTrustworthy (url) { - // Given a URL record (url), the following algorithm returns "Potentially - // Trustworthy" or "Not Trustworthy" as appropriate: - if (!webidl.is.URL(url)) { - return false - } - - // 1. If url is "about:blank" or "about:srcdoc", - // return "Potentially Trustworthy". - if (url.href === 'about:blank' || url.href === 'about:srcdoc') { - return true - } +// https://fetch.spec.whatwg.org/#http-redirect-fetch +function httpRedirectFetch (fetchParams, response) { + // 1. Let request be fetchParams’s request. + const request = fetchParams.request - // 2. If url’s scheme is "data", return "Potentially Trustworthy". - if (url.protocol === 'data:') return true + // 2. Let actualResponse be response, if response is not a filtered response, + // and response’s internal response otherwise. + const actualResponse = response.internalResponse + ? response.internalResponse + : response - // Note: The origin of blob: URLs is the origin of the context in which they - // were created. Therefore, blobs created in a trustworthy origin will - // themselves be potentially trustworthy. - if (url.protocol === 'blob:') return true + // 3. Let locationURL be actualResponse’s location URL given request’s current + // URL’s fragment. + let locationURL - // 3. Return the result of executing § 3.1 Is origin potentially trustworthy? - // on url’s origin. - return isOriginPotentiallyTrustworthy(url.origin) -} + try { + locationURL = responseLocationURL( + actualResponse, + requestCurrentURL(request).hash + ) -// https://w3c.github.io/webappsec-upgrade-insecure-requests/#upgrade-request -function tryUpgradeRequestToAPotentiallyTrustworthyURL (request) { - // TODO -} + // 4. If locationURL is null, then return response. + if (locationURL == null) { + return response + } + } catch (err) { + // 5. If locationURL is failure, then return a network error. + return Promise.resolve(makeNetworkError(err)) + } -/** - * @link {https://html.spec.whatwg.org/multipage/origin.html#same-origin} - * @param {URL} A - * @param {URL} B - */ -function sameOrigin (A, B) { - // 1. If A and B are the same opaque origin, then return true. - if (A.origin === B.origin && A.origin === 'null') { - return true + // 6. If locationURL’s scheme is not an HTTP(S) scheme, then return a network + // error. + if (!urlIsHttpHttpsScheme(locationURL)) { + return Promise.resolve(makeNetworkError('URL scheme must be a HTTP(S) scheme')) } - // 2. If A and B are both tuple origins and their schemes, - // hosts, and port are identical, then return true. - if (A.protocol === B.protocol && A.hostname === B.hostname && A.port === B.port) { - return true + // 7. If request’s redirect count is 20, then return a network error. + if (request.redirectCount === 20) { + return Promise.resolve(makeNetworkError('redirect count exceeded')) } - // 3. Return false. - return false -} + // 8. Increase request’s redirect count by 1. + request.redirectCount += 1 -function isAborted (fetchParams) { - return fetchParams.controller.state === 'aborted' -} + // 9. If request’s mode is "cors", locationURL includes credentials, and + // request’s origin is not same origin with locationURL’s origin, then return + // a network error. + if ( + request.mode === 'cors' && + (locationURL.username || locationURL.password) && + !sameOrigin(request, locationURL) + ) { + return Promise.resolve(makeNetworkError('cross origin not allowed for request mode "cors"')) + } -function isCancelled (fetchParams) { - return fetchParams.controller.state === 'aborted' || - fetchParams.controller.state === 'terminated' -} + // 10. If request’s response tainting is "cors" and locationURL includes + // credentials, then return a network error. + if ( + request.responseTainting === 'cors' && + (locationURL.username || locationURL.password) + ) { + return Promise.resolve(makeNetworkError( + 'URL cannot contain credentials for request mode "cors"' + )) + } -/** - * @see https://fetch.spec.whatwg.org/#concept-method-normalize - * @param {string} method - */ -function normalizeMethod (method) { - return normalizedMethodRecordsBase[method.toLowerCase()] ?? method -} + // 11. If actualResponse’s status is not 303, request’s body is non-null, + // and request’s body’s source is null, then return a network error. + if ( + actualResponse.status !== 303 && + request.body != null && + request.body.source == null + ) { + return Promise.resolve(makeNetworkError()) + } -// https://tc39.es/ecma262/#sec-%25iteratorprototype%25-object -const esIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]())) - -/** - * @see https://webidl.spec.whatwg.org/#dfn-iterator-prototype-object - * @param {string} name name of the instance - * @param {((target: any) => any)} kInternalIterator - * @param {string | number} [keyIndex] - * @param {string | number} [valueIndex] - */ -function createIterator (name, kInternalIterator, keyIndex = 0, valueIndex = 1) { - class FastIterableIterator { - /** @type {any} */ - #target - /** @type {'key' | 'value' | 'key+value'} */ - #kind - /** @type {number} */ - #index - - /** - * @see https://webidl.spec.whatwg.org/#dfn-default-iterator-object - * @param {unknown} target - * @param {'key' | 'value' | 'key+value'} kind - */ - constructor (target, kind) { - this.#target = target - this.#kind = kind - this.#index = 0 - } - - next () { - // 1. Let interface be the interface for which the iterator prototype object exists. - // 2. Let thisValue be the this value. - // 3. Let object be ? ToObject(thisValue). - // 4. If object is a platform object, then perform a security - // check, passing: - // 5. If object is not a default iterator object for interface, - // then throw a TypeError. - if (typeof this !== 'object' || this === null || !(#target in this)) { - throw new TypeError( - `'next' called on an object that does not implement interface ${name} Iterator.` - ) - } - - // 6. Let index be object’s index. - // 7. Let kind be object’s kind. - // 8. Let values be object’s target's value pairs to iterate over. - const index = this.#index - const values = kInternalIterator(this.#target) - - // 9. Let len be the length of values. - const len = values.length - - // 10. If index is greater than or equal to len, then return - // CreateIterResultObject(undefined, true). - if (index >= len) { - return { - value: undefined, - done: true - } - } - - // 11. Let pair be the entry in values at index index. - const { [keyIndex]: key, [valueIndex]: value } = values[index] - - // 12. Set object’s index to index + 1. - this.#index = index + 1 - - // 13. Return the iterator result for pair and kind. - - // https://webidl.spec.whatwg.org/#iterator-result - - // 1. Let result be a value determined by the value of kind: - let result - switch (this.#kind) { - case 'key': - // 1. Let idlKey be pair’s key. - // 2. Let key be the result of converting idlKey to an - // ECMAScript value. - // 3. result is key. - result = key - break - case 'value': - // 1. Let idlValue be pair’s value. - // 2. Let value be the result of converting idlValue to - // an ECMAScript value. - // 3. result is value. - result = value - break - case 'key+value': - // 1. Let idlKey be pair’s key. - // 2. Let idlValue be pair’s value. - // 3. Let key be the result of converting idlKey to an - // ECMAScript value. - // 4. Let value be the result of converting idlValue to - // an ECMAScript value. - // 5. Let array be ! ArrayCreate(2). - // 6. Call ! CreateDataProperty(array, "0", key). - // 7. Call ! CreateDataProperty(array, "1", value). - // 8. result is array. - result = [key, value] - break - } + // 12. If one of the following is true + // - actualResponse’s status is 301 or 302 and request’s method is `POST` + // - actualResponse’s status is 303 and request’s method is not `GET` or `HEAD` + if ( + ([301, 302].includes(actualResponse.status) && request.method === 'POST') || + (actualResponse.status === 303 && + !GET_OR_HEAD.includes(request.method)) + ) { + // then: + // 1. Set request’s method to `GET` and request’s body to null. + request.method = 'GET' + request.body = null - // 2. Return CreateIterResultObject(result, false). - return { - value: result, - done: false - } + // 2. For each headerName of request-body-header name, delete headerName from + // request’s header list. + for (const headerName of requestBodyHeader) { + request.headersList.delete(headerName) } } - // https://webidl.spec.whatwg.org/#dfn-iterator-prototype-object - // @ts-ignore - delete FastIterableIterator.prototype.constructor - - Object.setPrototypeOf(FastIterableIterator.prototype, esIteratorPrototype) + // 13. If request’s current URL’s origin is not same origin with locationURL’s + // origin, then for each headerName of CORS non-wildcard request-header name, + // delete headerName from request’s header list. + if (!sameOrigin(requestCurrentURL(request), locationURL)) { + // https://fetch.spec.whatwg.org/#cors-non-wildcard-request-header-name + request.headersList.delete('authorization', true) - Object.defineProperties(FastIterableIterator.prototype, { - [Symbol.toStringTag]: { - writable: false, - enumerable: false, - configurable: true, - value: `${name} Iterator` - }, - next: { writable: true, enumerable: true, configurable: true } - }) + // https://fetch.spec.whatwg.org/#authentication-entries + request.headersList.delete('proxy-authorization', true) - /** - * @param {unknown} target - * @param {'key' | 'value' | 'key+value'} kind - * @returns {IterableIterator} - */ - return function (target, kind) { - return new FastIterableIterator(target, kind) + // "Cookie" and "Host" are forbidden request-headers, which undici doesn't implement. + request.headersList.delete('cookie', true) + request.headersList.delete('host', true) } -} - -/** - * @see https://webidl.spec.whatwg.org/#dfn-iterator-prototype-object - * @param {string} name name of the instance - * @param {any} object class - * @param {(target: any) => any} kInternalIterator - * @param {string | number} [keyIndex] - * @param {string | number} [valueIndex] - */ -function iteratorMixin (name, object, kInternalIterator, keyIndex = 0, valueIndex = 1) { - const makeIterator = createIterator(name, kInternalIterator, keyIndex, valueIndex) - const properties = { - keys: { - writable: true, - enumerable: true, - configurable: true, - value: function keys () { - webidl.brandCheck(this, object) - return makeIterator(this, 'key') - } - }, - values: { - writable: true, - enumerable: true, - configurable: true, - value: function values () { - webidl.brandCheck(this, object) - return makeIterator(this, 'value') - } - }, - entries: { - writable: true, - enumerable: true, - configurable: true, - value: function entries () { - webidl.brandCheck(this, object) - return makeIterator(this, 'key+value') - } - }, - forEach: { - writable: true, - enumerable: true, - configurable: true, - value: function forEach (callbackfn, thisArg = globalThis) { - webidl.brandCheck(this, object) - webidl.argumentLengthCheck(arguments, 1, `${name}.forEach`) - if (typeof callbackfn !== 'function') { - throw new TypeError( - `Failed to execute 'forEach' on '${name}': parameter 1 is not of type 'Function'.` - ) - } - for (const { 0: key, 1: value } of makeIterator(this, 'key+value')) { - callbackfn.call(thisArg, value, key, this) - } - } - } + // 14. If request's body is non-null, then set request's body to the first return + // value of safely extracting request's body's source. + if (request.body != null) { + assert(request.body.source != null) + request.body = safelyExtractBody(request.body.source)[0] } - return Object.defineProperties(object.prototype, { - ...properties, - [Symbol.iterator]: { - writable: true, - enumerable: false, - configurable: true, - value: properties.entries.value - } - }) -} - -/** - * @param {import('./body').ExtractBodyResult} body - * @param {(bytes: Uint8Array) => void} processBody - * @param {(error: Error) => void} processBodyError - * @returns {void} - * - * @see https://fetch.spec.whatwg.org/#body-fully-read - */ -function fullyReadBody (body, processBody, processBodyError) { - // 1. If taskDestination is null, then set taskDestination to - // the result of starting a new parallel queue. + // 15. Let timingInfo be fetchParams’s timing info. + const timingInfo = fetchParams.timingInfo - // 2. Let successSteps given a byte sequence bytes be to queue a - // fetch task to run processBody given bytes, with taskDestination. - const successSteps = processBody + // 16. Set timingInfo’s redirect end time and post-redirect start time to the + // coarsened shared current time given fetchParams’s cross-origin isolated + // capability. + timingInfo.redirectEndTime = timingInfo.postRedirectStartTime = + coarsenedSharedCurrentTime(fetchParams.crossOriginIsolatedCapability) - // 3. Let errorSteps be to queue a fetch task to run processBodyError, - // with taskDestination. - const errorSteps = processBodyError + // 17. If timingInfo’s redirect start time is 0, then set timingInfo’s + // redirect start time to timingInfo’s start time. + if (timingInfo.redirectStartTime === 0) { + timingInfo.redirectStartTime = timingInfo.startTime + } - try { - // 4. Let reader be the result of getting a reader for body’s stream. - // If that threw an exception, then run errorSteps with that - // exception and return. - const reader = body.stream.getReader() + // 18. Append locationURL to request’s URL list. + request.urlList.push(locationURL) - // 5. Read all bytes from reader, given successSteps and errorSteps. - readAllBytes(reader, successSteps, errorSteps) - } catch (e) { - errorSteps(e) - } -} + // 19. Invoke set request’s referrer policy on redirect on request and + // actualResponse. + setRequestReferrerPolicyOnRedirect(request, actualResponse) -/** - * @param {ReadableStreamController} controller - */ -function readableStreamClose (controller) { - try { - controller.close() - controller.byobRequest?.respond(0) - } catch (err) { - // TODO: add comment explaining why this error occurs. - if (!err.message.includes('Controller is already closed') && !err.message.includes('ReadableStream is already closed')) { - throw err - } - } + // 20. Return the result of running main fetch given fetchParams and true. + return mainFetch(fetchParams, true) } -/** - * @see https://streams.spec.whatwg.org/#readablestreamdefaultreader-read-all-bytes - * @see https://streams.spec.whatwg.org/#read-loop - * @param {ReadableStream>} reader - * @param {(bytes: Uint8Array) => void} successSteps - * @param {(error: Error) => void} failureSteps - * @returns {Promise} - */ -async function readAllBytes (reader, successSteps, failureSteps) { - try { - const bytes = [] - let byteLength = 0 +// https://fetch.spec.whatwg.org/#http-network-or-cache-fetch +async function httpNetworkOrCacheFetch ( + fetchParams, + isAuthenticationFetch = false, + isNewConnectionFetch = false +) { + // 1. Let request be fetchParams’s request. + const request = fetchParams.request - do { - const { done, value: chunk } = await reader.read() + // 2. Let httpFetchParams be null. + let httpFetchParams = null - if (done) { - // 1. Call successSteps with bytes. - successSteps(Buffer.concat(bytes, byteLength)) - return - } + // 3. Let httpRequest be null. + let httpRequest = null - // 1. If chunk is not a Uint8Array object, call failureSteps - // with a TypeError and abort these steps. - if (!isUint8Array(chunk)) { - failureSteps(new TypeError('Received non-Uint8Array chunk')) - return - } + // 4. Let response be null. + let response = null - // 2. Append the bytes represented by chunk to bytes. - bytes.push(chunk) - byteLength += chunk.length + // 5. Let storedResponse be null. + // TODO: cache - // 3. Read-loop given reader, bytes, successSteps, and failureSteps. - } while (true) - } catch (e) { - // 1. Call failureSteps with e. - failureSteps(e) - } -} + // 6. Let httpCache be null. + const httpCache = null -/** - * @see https://fetch.spec.whatwg.org/#is-local - * @param {URL} url - * @returns {boolean} - */ -function urlIsLocal (url) { - assert('protocol' in url) // ensure it's a url object + // 7. Let the revalidatingFlag be unset. + const revalidatingFlag = false - const protocol = url.protocol + // 8. Run these steps, but abort when the ongoing fetch is terminated: - // A URL is local if its scheme is a local scheme. - // A local scheme is "about", "blob", or "data". - return protocol === 'about:' || protocol === 'blob:' || protocol === 'data:' -} + // 1. If request’s window is "no-window" and request’s redirect mode is + // "error", then set httpFetchParams to fetchParams and httpRequest to + // request. + if (request.window === 'no-window' && request.redirect === 'error') { + httpFetchParams = fetchParams + httpRequest = request + } else { + // Otherwise: -/** - * @param {string|URL} url - * @returns {boolean} - */ -function urlHasHttpsScheme (url) { - return ( - ( - typeof url === 'string' && - url[5] === ':' && - url[0] === 'h' && - url[1] === 't' && - url[2] === 't' && - url[3] === 'p' && - url[4] === 's' - ) || - url.protocol === 'https:' - ) -} + // 1. Set httpRequest to a clone of request. + httpRequest = cloneRequest(request) -/** - * @see https://fetch.spec.whatwg.org/#http-scheme - * @param {URL} url - */ -function urlIsHttpHttpsScheme (url) { - assert('protocol' in url) // ensure it's a url object + // 2. Set httpFetchParams to a copy of fetchParams. + httpFetchParams = { ...fetchParams } - const protocol = url.protocol + // 3. Set httpFetchParams’s request to httpRequest. + httpFetchParams.request = httpRequest + } - return protocol === 'http:' || protocol === 'https:' -} + // 3. Let includeCredentials be true if one of + const includeCredentials = + request.credentials === 'include' || + (request.credentials === 'same-origin' && + request.responseTainting === 'basic') -/** - * @typedef {Object} RangeHeaderValue - * @property {number|null} rangeStartValue - * @property {number|null} rangeEndValue - */ + // 4. Let contentLength be httpRequest’s body’s length, if httpRequest’s + // body is non-null; otherwise null. + const contentLength = httpRequest.body ? httpRequest.body.length : null -/** - * @see https://fetch.spec.whatwg.org/#simple-range-header-value - * @param {string} value - * @param {boolean} allowWhitespace - * @return {RangeHeaderValue|'failure'} - */ -function simpleRangeHeaderValue (value, allowWhitespace) { - // 1. Let data be the isomorphic decoding of value. - // Note: isomorphic decoding takes a sequence of bytes (ie. a Uint8Array) and turns it into a string, - // nothing more. We obviously don't need to do that if value is a string already. - const data = value + // 5. Let contentLengthHeaderValue be null. + let contentLengthHeaderValue = null - // 2. If data does not start with "bytes", then return failure. - if (!data.startsWith('bytes')) { - return 'failure' + // 6. If httpRequest’s body is null and httpRequest’s method is `POST` or + // `PUT`, then set contentLengthHeaderValue to `0`. + if ( + httpRequest.body == null && + ['POST', 'PUT'].includes(httpRequest.method) + ) { + contentLengthHeaderValue = '0' } - // 3. Let position be a position variable for data, initially pointing at the 5th code point of data. - const position = { position: 5 } - - // 4. If allowWhitespace is true, collect a sequence of code points that are HTTP tab or space, - // from data given position. - if (allowWhitespace) { - collectASequenceOfCodePoints( - (char) => char === '\t' || char === ' ', - data, - position - ) + // 7. If contentLength is non-null, then set contentLengthHeaderValue to + // contentLength, serialized and isomorphic encoded. + if (contentLength != null) { + contentLengthHeaderValue = isomorphicEncode(`${contentLength}`) } - // 5. If the code point at position within data is not U+003D (=), then return failure. - if (data.charCodeAt(position.position) !== 0x3D) { - return 'failure' + // 8. If contentLengthHeaderValue is non-null, then append + // `Content-Length`/contentLengthHeaderValue to httpRequest’s header + // list. + if (contentLengthHeaderValue != null) { + httpRequest.headersList.append('content-length', contentLengthHeaderValue, true) } - // 6. Advance position by 1. - position.position++ + // 9. If contentLengthHeaderValue is non-null, then append (`Content-Length`, + // contentLengthHeaderValue) to httpRequest’s header list. - // 7. If allowWhitespace is true, collect a sequence of code points that are HTTP tab or space, from - // data given position. - if (allowWhitespace) { - collectASequenceOfCodePoints( - (char) => char === '\t' || char === ' ', - data, - position - ) + // 10. If contentLength is non-null and httpRequest’s keepalive is true, + // then: + if (contentLength != null && httpRequest.keepalive) { + // NOTE: keepalive is a noop outside of browser context. } - // 8. Let rangeStart be the result of collecting a sequence of code points that are ASCII digits, - // from data given position. - const rangeStart = collectASequenceOfCodePoints( - (char) => { - const code = char.charCodeAt(0) + // 11. If httpRequest’s referrer is a URL, then append + // `Referer`/httpRequest’s referrer, serialized and isomorphic encoded, + // to httpRequest’s header list. + if (webidl.is.URL(httpRequest.referrer)) { + httpRequest.headersList.append('referer', isomorphicEncode(httpRequest.referrer.href), true) + } - return code >= 0x30 && code <= 0x39 - }, - data, - position - ) + // 12. Append a request `Origin` header for httpRequest. + appendRequestOriginHeader(httpRequest) - // 9. Let rangeStartValue be rangeStart, interpreted as decimal number, if rangeStart is not the - // empty string; otherwise null. - const rangeStartValue = rangeStart.length ? Number(rangeStart) : null + // 13. Append the Fetch metadata headers for httpRequest. [FETCH-METADATA] + appendFetchMetadata(httpRequest) - // 10. If allowWhitespace is true, collect a sequence of code points that are HTTP tab or space, - // from data given position. - if (allowWhitespace) { - collectASequenceOfCodePoints( - (char) => char === '\t' || char === ' ', - data, - position - ) + // 14. If httpRequest’s header list does not contain `User-Agent`, then + // user agents should append `User-Agent`/default `User-Agent` value to + // httpRequest’s header list. + if (!httpRequest.headersList.contains('user-agent', true)) { + httpRequest.headersList.append('user-agent', defaultUserAgent, true) } - // 11. If the code point at position within data is not U+002D (-), then return failure. - if (data.charCodeAt(position.position) !== 0x2D) { - return 'failure' - } - - // 12. Advance position by 1. - position.position++ - - // 13. If allowWhitespace is true, collect a sequence of code points that are HTTP tab - // or space, from data given position. - // Note from Khafra: its the same step as in #8 again lol - if (allowWhitespace) { - collectASequenceOfCodePoints( - (char) => char === '\t' || char === ' ', - data, - position - ) + // 15. If httpRequest’s cache mode is "default" and httpRequest’s header + // list contains `If-Modified-Since`, `If-None-Match`, + // `If-Unmodified-Since`, `If-Match`, or `If-Range`, then set + // httpRequest’s cache mode to "no-store". + if ( + httpRequest.cache === 'default' && + (httpRequest.headersList.contains('if-modified-since', true) || + httpRequest.headersList.contains('if-none-match', true) || + httpRequest.headersList.contains('if-unmodified-since', true) || + httpRequest.headersList.contains('if-match', true) || + httpRequest.headersList.contains('if-range', true)) + ) { + httpRequest.cache = 'no-store' } - // 14. Let rangeEnd be the result of collecting a sequence of code points that are - // ASCII digits, from data given position. - // Note from Khafra: you wouldn't guess it, but this is also the same step as #8 - const rangeEnd = collectASequenceOfCodePoints( - (char) => { - const code = char.charCodeAt(0) - - return code >= 0x30 && code <= 0x39 - }, - data, - position - ) + // 16. If httpRequest’s cache mode is "no-cache", httpRequest’s prevent + // no-cache cache-control header modification flag is unset, and + // httpRequest’s header list does not contain `Cache-Control`, then append + // `Cache-Control`/`max-age=0` to httpRequest’s header list. + if ( + httpRequest.cache === 'no-cache' && + !httpRequest.preventNoCacheCacheControlHeaderModification && + !httpRequest.headersList.contains('cache-control', true) + ) { + httpRequest.headersList.append('cache-control', 'max-age=0', true) + } - // 15. Let rangeEndValue be rangeEnd, interpreted as decimal number, if rangeEnd - // is not the empty string; otherwise null. - // Note from Khafra: THE SAME STEP, AGAIN!!! - // Note: why interpret as a decimal if we only collect ascii digits? - const rangeEndValue = rangeEnd.length ? Number(rangeEnd) : null + // 17. If httpRequest’s cache mode is "no-store" or "reload", then: + if (httpRequest.cache === 'no-store' || httpRequest.cache === 'reload') { + // 1. If httpRequest’s header list does not contain `Pragma`, then append + // `Pragma`/`no-cache` to httpRequest’s header list. + if (!httpRequest.headersList.contains('pragma', true)) { + httpRequest.headersList.append('pragma', 'no-cache', true) + } - // 16. If position is not past the end of data, then return failure. - if (position.position < data.length) { - return 'failure' + // 2. If httpRequest’s header list does not contain `Cache-Control`, + // then append `Cache-Control`/`no-cache` to httpRequest’s header list. + if (!httpRequest.headersList.contains('cache-control', true)) { + httpRequest.headersList.append('cache-control', 'no-cache', true) + } } - // 17. If rangeEndValue and rangeStartValue are null, then return failure. - if (rangeEndValue === null && rangeStartValue === null) { - return 'failure' + // 18. If httpRequest’s header list contains `Range`, then append + // `Accept-Encoding`/`identity` to httpRequest’s header list. + if (httpRequest.headersList.contains('range', true)) { + httpRequest.headersList.append('accept-encoding', 'identity', true) } - // 18. If rangeStartValue and rangeEndValue are numbers, and rangeStartValue is - // greater than rangeEndValue, then return failure. - // Note: ... when can they not be numbers? - if (rangeStartValue > rangeEndValue) { - return 'failure' + // 19. Modify httpRequest’s header list per HTTP. Do not append a given + // header if httpRequest’s header list contains that header’s name. + // TODO: https://github.com/whatwg/fetch/issues/1285#issuecomment-896560129 + if (!httpRequest.headersList.contains('accept-encoding', true)) { + if (urlHasHttpsScheme(requestCurrentURL(httpRequest))) { + httpRequest.headersList.append('accept-encoding', 'br, gzip, deflate', true) + } else { + httpRequest.headersList.append('accept-encoding', 'gzip, deflate', true) + } } - // 19. Return (rangeStartValue, rangeEndValue). - return { rangeStartValue, rangeEndValue } -} - -/** - * @see https://fetch.spec.whatwg.org/#build-a-content-range - * @param {number} rangeStart - * @param {number} rangeEnd - * @param {number} fullLength - */ -function buildContentRange (rangeStart, rangeEnd, fullLength) { - // 1. Let contentRange be `bytes `. - let contentRange = 'bytes ' + httpRequest.headersList.delete('host', true) - // 2. Append rangeStart, serialized and isomorphic encoded, to contentRange. - contentRange += isomorphicEncode(`${rangeStart}`) + // 21. If includeCredentials is true, then: + if (includeCredentials) { + // 1. If the user agent is not configured to block cookies for httpRequest + // (see section 7 of [COOKIES]), then: + // TODO: credentials - // 3. Append 0x2D (-) to contentRange. - contentRange += '-' + // 2. If httpRequest’s header list does not contain `Authorization`, then: + if (!httpRequest.headersList.contains('authorization', true)) { + // 1. Let authorizationValue be null. + let authorizationValue = null - // 4. Append rangeEnd, serialized and isomorphic encoded to contentRange. - contentRange += isomorphicEncode(`${rangeEnd}`) + // 2. If there’s an authentication entry for httpRequest and either + // httpRequest’s use-URL-credentials flag is unset or httpRequest’s + // current URL does not include credentials, then set + // authorizationValue to authentication entry. + if (hasAuthenticationEntry(httpRequest) && ( + httpRequest.useURLCredentials === undefined || !includesCredentials(requestCurrentURL(httpRequest)) + )) { + // TODO + } else if (includesCredentials(requestCurrentURL(httpRequest)) && isAuthenticationFetch) { + // 3. Otherwise, if httpRequest’s current URL does include credentials + // and isAuthenticationFetch is true, set authorizationValue to + // httpRequest’s current URL, converted to an `Authorization` value + const { username, password } = requestCurrentURL(httpRequest) + authorizationValue = `Basic ${Buffer.from(`${username}:${password}`).toString('base64')}` + } - // 5. Append 0x2F (/) to contentRange. - contentRange += '/' + // 4. If authorizationValue is non-null, then append (`Authorization`, + // authorizationValue) to httpRequest’s header list. + if (authorizationValue !== null) { + httpRequest.headersList.append('Authorization', authorizationValue, false) + } + } + } - // 6. Append fullLength, serialized and isomorphic encoded to contentRange. - contentRange += isomorphicEncode(`${fullLength}`) + // 21. If there’s a proxy-authentication entry, use it as appropriate. + // TODO: proxy-authentication - // 7. Return contentRange. - return contentRange -} + // 22. Set httpCache to the result of determining the HTTP cache + // partition, given httpRequest. + // TODO: cache -// A Stream, which pipes the response to zlib.createInflate() or -// zlib.createInflateRaw() depending on the first byte of the Buffer. -// If the lower byte of the first byte is 0x08, then the stream is -// interpreted as a zlib stream, otherwise it's interpreted as a -// raw deflate stream. -class InflateStream extends Transform { - #zlibOptions + // 23. If httpCache is null, then set httpRequest’s cache mode to + // "no-store". + if (httpCache == null) { + httpRequest.cache = 'no-store' + } - /** @param {zlib.ZlibOptions} [zlibOptions] */ - constructor (zlibOptions) { - super() - this.#zlibOptions = zlibOptions + // 24. If httpRequest’s cache mode is neither "no-store" nor "reload", + // then: + if (httpRequest.cache !== 'no-store' && httpRequest.cache !== 'reload') { + // TODO: cache } - _transform (chunk, encoding, callback) { - if (!this._inflateStream) { - if (chunk.length === 0) { - callback() - return - } - this._inflateStream = (chunk[0] & 0x0F) === 0x08 - ? zlib.createInflate(this.#zlibOptions) - : zlib.createInflateRaw(this.#zlibOptions) + // 9. If aborted, then return the appropriate network error for fetchParams. + // TODO - this._inflateStream.on('data', this.push.bind(this)) - this._inflateStream.on('end', () => this.push(null)) - this._inflateStream.on('error', (err) => this.destroy(err)) + // 10. If response is null, then: + if (response == null) { + // 1. If httpRequest’s cache mode is "only-if-cached", then return a + // network error. + if (httpRequest.cache === 'only-if-cached') { + return makeNetworkError('only if cached') } - this._inflateStream.write(chunk, encoding, callback) - } + // 2. Let forwardResponse be the result of running HTTP-network fetch + // given httpFetchParams, includeCredentials, and isNewConnectionFetch. + const forwardResponse = await httpNetworkFetch( + httpFetchParams, + includeCredentials, + isNewConnectionFetch + ) - _final (callback) { - if (this._inflateStream) { - this._inflateStream.end() - this._inflateStream = null + // 3. If httpRequest’s method is unsafe and forwardResponse’s status is + // in the range 200 to 399, inclusive, invalidate appropriate stored + // responses in httpCache, as per the "Invalidation" chapter of HTTP + // Caching, and set storedResponse to null. [HTTP-CACHING] + if ( + !safeMethodsSet.has(httpRequest.method) && + forwardResponse.status >= 200 && + forwardResponse.status <= 399 + ) { + // TODO: cache } - callback() - } -} - -/** - * @param {zlib.ZlibOptions} [zlibOptions] - * @returns {InflateStream} - */ -function createInflate (zlibOptions) { - return new InflateStream(zlibOptions) -} -/** - * @see https://fetch.spec.whatwg.org/#concept-header-extract-mime-type - * @param {import('./headers').HeadersList} headers - */ -function extractMimeType (headers) { - // 1. Let charset be null. - let charset = null + // 4. If the revalidatingFlag is set and forwardResponse’s status is 304, + // then: + if (revalidatingFlag && forwardResponse.status === 304) { + // TODO: cache + } - // 2. Let essence be null. - let essence = null + // 5. If response is null, then: + if (response == null) { + // 1. Set response to forwardResponse. + response = forwardResponse - // 3. Let mimeType be null. - let mimeType = null + // 2. Store httpRequest and forwardResponse in httpCache, as per the + // "Storing Responses in Caches" chapter of HTTP Caching. [HTTP-CACHING] + // TODO: cache + } + } - // 4. Let values be the result of getting, decoding, and splitting `Content-Type` from headers. - const values = getDecodeSplit('content-type', headers) + // 11. Set response’s URL list to a clone of httpRequest’s URL list. + response.urlList = [...httpRequest.urlList] - // 5. If values is null, then return failure. - if (values === null) { - return 'failure' + // 12. If httpRequest’s header list contains `Range`, then set response’s + // range-requested flag. + if (httpRequest.headersList.contains('range', true)) { + response.rangeRequested = true } - // 6. For each value of values: - for (const value of values) { - // 6.1. Let temporaryMimeType be the result of parsing value. - const temporaryMimeType = parseMIMEType(value) - - // 6.2. If temporaryMimeType is failure or its essence is "*/*", then continue. - if (temporaryMimeType === 'failure' || temporaryMimeType.essence === '*/*') { - continue - } + // 13. Set response’s request-includes-credentials to includeCredentials. + response.requestIncludesCredentials = includeCredentials - // 6.3. Set mimeType to temporaryMimeType. - mimeType = temporaryMimeType + // 14. If response’s status is 401, httpRequest’s response tainting is not "cors", + // includeCredentials is true, and request’s traversable for user prompts is + // a traversable navigable: + if (response.status === 401 && httpRequest.responseTainting !== 'cors' && includeCredentials && isTraversableNavigable(request.traversableForUserPrompts)) { + // 2. If request’s body is non-null, then: + if (request.body != null) { + // 1. If request’s body’s source is null, then return a network error. + if (request.body.source == null) { + return makeNetworkError('expected non-null body source') + } - // 6.4. If mimeType’s essence is not essence, then: - if (mimeType.essence !== essence) { - // 6.4.1. Set charset to null. - charset = null + // 2. Set request’s body to the body of the result of safely extracting + // request’s body’s source. + request.body = safelyExtractBody(request.body.source)[0] + } - // 6.4.2. If mimeType’s parameters["charset"] exists, then set charset to - // mimeType’s parameters["charset"]. - if (mimeType.parameters.has('charset')) { - charset = mimeType.parameters.get('charset') + // 3. If request’s use-URL-credentials flag is unset or isAuthenticationFetch is + // true, then: + if (request.useURLCredentials === undefined || isAuthenticationFetch) { + // 1. If fetchParams is canceled, then return the appropriate network error + // for fetchParams. + if (isCancelled(fetchParams)) { + return makeAppropriateNetworkError(fetchParams) } - // 6.4.3. Set essence to mimeType’s essence. - essence = mimeType.essence - } else if (!mimeType.parameters.has('charset') && charset !== null) { - // 6.5. Otherwise, if mimeType’s parameters["charset"] does not exist, and - // charset is non-null, set mimeType’s parameters["charset"] to charset. - mimeType.parameters.set('charset', charset) - } - } + // 2. Let username and password be the result of prompting the end user for a + // username and password, respectively, in request’s traversable for user prompts. + // TODO - // 7. If mimeType is null, then return failure. - if (mimeType == null) { - return 'failure' - } + // 3. Set the username given request’s current URL and username. + // requestCurrentURL(request).username = TODO - // 8. Return mimeType. - return mimeType -} + // 4. Set the password given request’s current URL and password. + // requestCurrentURL(request).password = TODO -/** - * @see https://fetch.spec.whatwg.org/#header-value-get-decode-and-split - * @param {string|null} value - */ -function gettingDecodingSplitting (value) { - // 1. Let input be the result of isomorphic decoding value. - const input = value + // In browsers, the user will be prompted to enter a username/password before the request + // is re-sent. To prevent an infinite 401 loop, return the response for now. + // https://github.com/nodejs/undici/pull/4756 + return response + } - // 2. Let position be a position variable for input, initially pointing at the start of input. - const position = { position: 0 } + // 4. Set response to the result of running HTTP-network-or-cache fetch given + // fetchParams and true. + fetchParams.controller.connection.destroy() - // 3. Let values be a list of strings, initially empty. - const values = [] + response = await httpNetworkOrCacheFetch(fetchParams, true) + } - // 4. Let temporaryValue be the empty string. - let temporaryValue = '' + // 15. If response’s status is 407, then: + if (response.status === 407) { + // 1. If request’s window is "no-window", then return a network error. + if (request.window === 'no-window') { + return makeNetworkError() + } - // 5. While position is not past the end of input: - while (position.position < input.length) { - // 5.1. Append the result of collecting a sequence of code points that are not U+0022 (") - // or U+002C (,) from input, given position, to temporaryValue. - temporaryValue += collectASequenceOfCodePoints( - (char) => char !== '"' && char !== ',', - input, - position - ) + // 2. ??? - // 5.2. If position is not past the end of input, then: - if (position.position < input.length) { - // 5.2.1. If the code point at position within input is U+0022 ("), then: - if (input.charCodeAt(position.position) === 0x22) { - // 5.2.1.1. Append the result of collecting an HTTP quoted string from input, given position, to temporaryValue. - temporaryValue += collectAnHTTPQuotedString( - input, - position - ) + // 3. If fetchParams is canceled, then return the appropriate network error for fetchParams. + if (isCancelled(fetchParams)) { + return makeAppropriateNetworkError(fetchParams) + } - // 5.2.1.2. If position is not past the end of input, then continue. - if (position.position < input.length) { - continue - } - } else { - // 5.2.2. Otherwise: + // 4. Prompt the end user as appropriate in request’s window and store + // the result as a proxy-authentication entry. [HTTP-AUTH] + // TODO: Invoke some kind of callback? - // 5.2.2.1. Assert: the code point at position within input is U+002C (,). - assert(input.charCodeAt(position.position) === 0x2C) + // 5. Set response to the result of running HTTP-network-or-cache fetch given + // fetchParams. + // TODO + return makeNetworkError('proxy authentication required') + } - // 5.2.2.2. Advance position by 1. - position.position++ - } + // 16. If all of the following are true + if ( + // response’s status is 421 + response.status === 421 && + // isNewConnectionFetch is false + !isNewConnectionFetch && + // request’s body is null, or request’s body is non-null and request’s body’s source is non-null + (request.body == null || request.body.source != null) + ) { + // then: + + // 1. If fetchParams is canceled, then return the appropriate network error for fetchParams. + if (isCancelled(fetchParams)) { + return makeAppropriateNetworkError(fetchParams) } - // 5.3. Remove all HTTP tab or space from the start and end of temporaryValue. - temporaryValue = removeChars(temporaryValue, true, true, (char) => char === 0x9 || char === 0x20) + // 2. Set response to the result of running HTTP-network-or-cache + // fetch given fetchParams, isAuthenticationFetch, and true. - // 5.4. Append temporaryValue to values. - values.push(temporaryValue) + // TODO (spec): The spec doesn't specify this but we need to cancel + // the active response before we can start a new one. + // https://github.com/whatwg/fetch/issues/1293 + fetchParams.controller.connection.destroy() - // 5.6. Set temporaryValue to the empty string. - temporaryValue = '' + response = await httpNetworkOrCacheFetch( + fetchParams, + isAuthenticationFetch, + true + ) } - // 6. Return values. - return values + // 17. If isAuthenticationFetch is true, then create an authentication entry + if (isAuthenticationFetch) { + // TODO + } + + // 18. Return response. + return response } -/** - * @see https://fetch.spec.whatwg.org/#concept-header-list-get-decode-split - * @param {string} name lowercase header name - * @param {import('./headers').HeadersList} list - */ -function getDecodeSplit (name, list) { - // 1. Let value be the result of getting name from list. - const value = list.get(name, true) +// https://fetch.spec.whatwg.org/#http-network-fetch +async function httpNetworkFetch ( + fetchParams, + includeCredentials = false, + forceNewConnection = false +) { + assert(!fetchParams.controller.connection || fetchParams.controller.connection.destroyed) - // 2. If value is null, then return null. - if (value === null) { - return null + fetchParams.controller.connection = { + abort: null, + destroyed: false, + destroy (err, abort = true) { + if (!this.destroyed) { + this.destroyed = true + if (abort) { + this.abort?.(err ?? new DOMException('The operation was aborted.', 'AbortError')) + } + } + } } - // 3. Return the result of getting, decoding, and splitting value. - return gettingDecodingSplitting(value) -} - -function hasAuthenticationEntry (request) { - return false -} + // 1. Let request be fetchParams’s request. + const request = fetchParams.request -/** - * @see https://url.spec.whatwg.org/#include-credentials - * @param {URL} url - */ -function includesCredentials (url) { - // A URL includes credentials if its username or password is not the empty string. - return !!(url.username && url.password) -} + // 2. Let response be null. + let response = null -/** - * @see https://html.spec.whatwg.org/multipage/document-sequences.html#traversable-navigable - * @param {object|string} navigable - */ -function isTraversableNavigable (navigable) { - // TODO - return true -} + // 3. Let timingInfo be fetchParams’s timing info. + const timingInfo = fetchParams.timingInfo -class EnvironmentSettingsObjectBase { - get baseUrl () { - return getGlobalOrigin() - } + // 4. Let httpCache be the result of determining the HTTP cache partition, + // given request. + // TODO: cache + const httpCache = null - get origin () { - return this.baseUrl?.origin + // 5. If httpCache is null, then set request’s cache mode to "no-store". + if (httpCache == null) { + request.cache = 'no-store' } - policyContainer = makePolicyContainer() -} + // 6. Let networkPartitionKey be the result of determining the network + // partition key given request. + // TODO -class EnvironmentSettingsObject { - settingsObject = new EnvironmentSettingsObjectBase() -} + // 7. Let newConnection be "yes" if forceNewConnection is true; otherwise + // "no". + const newConnection = forceNewConnection ? 'yes' : 'no' // eslint-disable-line no-unused-vars -const environmentSettingsObject = new EnvironmentSettingsObject() + // 8. Switch on request’s mode: + if (request.mode === 'websocket') { + // Let connection be the result of obtaining a WebSocket connection, + // given request’s current URL. + // TODO + } else { + // Let connection be the result of obtaining a connection, given + // networkPartitionKey, request’s current URL’s origin, + // includeCredentials, and forceNewConnection. + // TODO + } -module.exports = { - isAborted, - isCancelled, - isValidEncodedURL, - ReadableStreamFrom, - tryUpgradeRequestToAPotentiallyTrustworthyURL, - clampAndCoarsenConnectionTimingInfo, - coarsenedSharedCurrentTime, - determineRequestsReferrer, - makePolicyContainer, - clonePolicyContainer, - appendFetchMetadata, - appendRequestOriginHeader, - TAOCheck, - corsCheck, - crossOriginResourcePolicyCheck, - createOpaqueTimingInfo, - setRequestReferrerPolicyOnRedirect, - isValidHTTPToken, - requestBadPort, - requestCurrentURL, - responseURL, - responseLocationURL, - isURLPotentiallyTrustworthy, - isValidReasonPhrase, - sameOrigin, - normalizeMethod, - iteratorMixin, - createIterator, - isValidHeaderName, - isValidHeaderValue, - isErrorLike, - fullyReadBody, - readableStreamClose, - urlIsLocal, - urlHasHttpsScheme, - urlIsHttpHttpsScheme, - readAllBytes, - simpleRangeHeaderValue, - buildContentRange, - createInflate, - extractMimeType, - getDecodeSplit, - environmentSettingsObject, - isOriginIPPotentiallyTrustworthy, - hasAuthenticationEntry, - includesCredentials, - isTraversableNavigable -} + // 9. Run these steps, but abort when the ongoing fetch is terminated: + // 1. If connection is failure, then return a network error. -/***/ }), + // 2. Set timingInfo’s final connection timing info to the result of + // calling clamp and coarsen connection timing info with connection’s + // timing info, timingInfo’s post-redirect start time, and fetchParams’s + // cross-origin isolated capability. -/***/ 3883: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // 3. If connection is not an HTTP/2 connection, request’s body is non-null, + // and request’s body’s source is null, then append (`Transfer-Encoding`, + // `chunked`) to request’s header list. -"use strict"; + // 4. Set timingInfo’s final network-request start time to the coarsened + // shared current time given fetchParams’s cross-origin isolated + // capability. + // 5. Set response to the result of making an HTTP request over connection + // using request with the following caveats: -const assert = __nccwpck_require__(4589) -const { utf8DecodeBytes } = __nccwpck_require__(9825) + // - Follow the relevant requirements from HTTP. [HTTP] [HTTP-SEMANTICS] + // [HTTP-COND] [HTTP-CACHING] [HTTP-AUTH] -/** - * @param {(char: string) => boolean} condition - * @param {string} input - * @param {{ position: number }} position - * @returns {string} - * - * @see https://infra.spec.whatwg.org/#collect-a-sequence-of-code-points - */ -function collectASequenceOfCodePoints (condition, input, position) { - // 1. Let result be the empty string. - let result = '' + // - If request’s body is non-null, and request’s body’s source is null, + // then the user agent may have a buffer of up to 64 kibibytes and store + // a part of request’s body in that buffer. If the user agent reads from + // request’s body beyond that buffer’s size and the user agent needs to + // resend request, then instead return a network error. - // 2. While position doesn’t point past the end of input and the - // code point at position within input meets the condition condition: - while (position.position < input.length && condition(input[position.position])) { - // 1. Append that code point to the end of result. - result += input[position.position] + // - Set timingInfo’s final network-response start time to the coarsened + // shared current time given fetchParams’s cross-origin isolated capability, + // immediately after the user agent’s HTTP parser receives the first byte + // of the response (e.g., frame header bytes for HTTP/2 or response status + // line for HTTP/1.x). - // 2. Advance position by 1. - position.position++ - } + // - Wait until all the headers are transmitted. - // 3. Return result. - return result -} + // - Any responses whose status is in the range 100 to 199, inclusive, + // and is not 101, are to be ignored, except for the purposes of setting + // timingInfo’s final network-response start time above. -/** - * A faster collectASequenceOfCodePoints that only works when comparing a single character. - * @param {string} char - * @param {string} input - * @param {{ position: number }} position - * @returns {string} - * - * @see https://infra.spec.whatwg.org/#collect-a-sequence-of-code-points - */ -function collectASequenceOfCodePointsFast (char, input, position) { - const idx = input.indexOf(char, position.position) - const start = position.position + // - If request’s header list contains `Transfer-Encoding`/`chunked` and + // response is transferred via HTTP/1.0 or older, then return a network + // error. - if (idx === -1) { - position.position = input.length - return input.slice(start) - } + // - If the HTTP request results in a TLS client certificate dialog, then: - position.position = idx - return input.slice(start, position.position) -} + // 1. If request’s window is an environment settings object, make the + // dialog available in request’s window. -const ASCII_WHITESPACE_REPLACE_REGEX = /[\u0009\u000A\u000C\u000D\u0020]/g // eslint-disable-line no-control-regex + // 2. Otherwise, return a network error. -/** - * @param {string} data - * @returns {Uint8Array | 'failure'} - * - * @see https://infra.spec.whatwg.org/#forgiving-base64-decode - */ -function forgivingBase64 (data) { - // 1. Remove all ASCII whitespace from data. - data = data.replace(ASCII_WHITESPACE_REPLACE_REGEX, '') + // To transmit request’s body body, run these steps: + let requestBody = null + // 1. If body is null and fetchParams’s process request end-of-body is + // non-null, then queue a fetch task given fetchParams’s process request + // end-of-body and fetchParams’s task destination. + if (request.body == null && fetchParams.processRequestEndOfBody) { + queueMicrotask(() => fetchParams.processRequestEndOfBody()) + } else if (request.body != null) { + // 2. Otherwise, if body is non-null: - let dataLength = data.length - // 2. If data’s code point length divides by 4 leaving - // no remainder, then: - if (dataLength % 4 === 0) { - // 1. If data ends with one or two U+003D (=) code points, - // then remove them from data. - if (data.charCodeAt(dataLength - 1) === 0x003D) { - --dataLength - if (data.charCodeAt(dataLength - 1) === 0x003D) { - --dataLength + // 1. Let processBodyChunk given bytes be these steps: + const processBodyChunk = async function * (bytes) { + // 1. If the ongoing fetch is terminated, then abort these steps. + if (isCancelled(fetchParams)) { + return } - } - } - // 3. If data’s code point length divides by 4 leaving - // a remainder of 1, then return failure. - if (dataLength % 4 === 1) { - return 'failure' - } + // 2. Run this step in parallel: transmit bytes. + yield bytes - // 4. If data contains a code point that is not one of - // U+002B (+) - // U+002F (/) - // ASCII alphanumeric - // then return failure. - if (/[^+/0-9A-Za-z]/.test(data.length === dataLength ? data : data.substring(0, dataLength))) { - return 'failure' - } + // 3. If fetchParams’s process request body is non-null, then run + // fetchParams’s process request body given bytes’s length. + fetchParams.processRequestBodyChunkLength?.(bytes.byteLength) + } - const buffer = Buffer.from(data, 'base64') - return new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength) -} + // 2. Let processEndOfBody be these steps: + const processEndOfBody = () => { + // 1. If fetchParams is canceled, then abort these steps. + if (isCancelled(fetchParams)) { + return + } -/** - * @param {number} char - * @returns {boolean} - * - * @see https://infra.spec.whatwg.org/#ascii-whitespace - */ -function isASCIIWhitespace (char) { - return ( - char === 0x09 || // \t - char === 0x0a || // \n - char === 0x0c || // \f - char === 0x0d || // \r - char === 0x20 // space - ) -} + // 2. If fetchParams’s process request end-of-body is non-null, + // then run fetchParams’s process request end-of-body. + if (fetchParams.processRequestEndOfBody) { + fetchParams.processRequestEndOfBody() + } + } -/** - * @param {Uint8Array} input - * @returns {string} - * - * @see https://infra.spec.whatwg.org/#isomorphic-decode - */ -function isomorphicDecode (input) { - // 1. To isomorphic decode a byte sequence input, return a string whose code point - // length is equal to input’s length and whose code points have the same values - // as the values of input’s bytes, in the same order. - const length = input.length - if ((2 << 15) - 1 > length) { - return String.fromCharCode.apply(null, input) - } - let result = '' - let i = 0 - let addition = (2 << 15) - 1 - while (i < length) { - if (i + addition > length) { - addition = length - i + // 3. Let processBodyError given e be these steps: + const processBodyError = (e) => { + // 1. If fetchParams is canceled, then abort these steps. + if (isCancelled(fetchParams)) { + return + } + + // 2. If e is an "AbortError" DOMException, then abort fetchParams’s controller. + if (e.name === 'AbortError') { + fetchParams.controller.abort() + } else { + fetchParams.controller.terminate(e) + } } - result += String.fromCharCode.apply(null, input.subarray(i, i += addition)) - } - return result -} -const invalidIsomorphicEncodeValueRegex = /[^\x00-\xFF]/ // eslint-disable-line no-control-regex + // 4. Incrementally read request’s body given processBodyChunk, processEndOfBody, + // processBodyError, and fetchParams’s task destination. + requestBody = (async function * () { + try { + for await (const bytes of request.body.stream) { + yield * processBodyChunk(bytes) + } + processEndOfBody() + } catch (err) { + processBodyError(err) + } + })() + } -/** - * @param {string} input - * @returns {string} - * - * @see https://infra.spec.whatwg.org/#isomorphic-encode - */ -function isomorphicEncode (input) { - // 1. Assert: input contains no code points greater than U+00FF. - assert(!invalidIsomorphicEncodeValueRegex.test(input)) + try { + // socket is only provided for websockets + const { body, status, statusText, headersList, socket } = await dispatch({ body: requestBody }) - // 2. Return a byte sequence whose length is equal to input’s code - // point length and whose bytes have the same values as the - // values of input’s code points, in the same order - return input -} + if (socket) { + response = makeResponse({ status, statusText, headersList, socket }) + } else { + const iterator = body[Symbol.asyncIterator]() + fetchParams.controller.next = () => iterator.next() -/** - * @see https://infra.spec.whatwg.org/#parse-json-bytes-to-a-javascript-value - * @param {Uint8Array} bytes - */ -function parseJSONFromBytes (bytes) { - return JSON.parse(utf8DecodeBytes(bytes)) -} + response = makeResponse({ status, statusText, headersList }) + } + } catch (err) { + // 10. If aborted, then: + if (err.name === 'AbortError') { + // 1. If connection uses HTTP/2, then transmit an RST_STREAM frame. + fetchParams.controller.connection.destroy() -/** - * @param {string} str - * @param {boolean} [leading=true] - * @param {boolean} [trailing=true] - * @returns {string} - * - * @see https://infra.spec.whatwg.org/#strip-leading-and-trailing-ascii-whitespace - */ -function removeASCIIWhitespace (str, leading = true, trailing = true) { - return removeChars(str, leading, trailing, isASCIIWhitespace) -} + // 2. Return the appropriate network error for fetchParams. + return makeAppropriateNetworkError(fetchParams, err) + } -/** - * @param {string} str - * @param {boolean} leading - * @param {boolean} trailing - * @param {(charCode: number) => boolean} predicate - * @returns {string} - */ -function removeChars (str, leading, trailing, predicate) { - let lead = 0 - let trail = str.length - 1 + return makeNetworkError(err) + } - if (leading) { - while (lead < str.length && predicate(str.charCodeAt(lead))) lead++ + // 11. Let pullAlgorithm be an action that resumes the ongoing fetch + // if it is suspended. + const pullAlgorithm = () => { + return fetchParams.controller.resume() } - if (trailing) { - while (trail > 0 && predicate(str.charCodeAt(trail))) trail-- + // 12. Let cancelAlgorithm be an algorithm that aborts fetchParams’s + // controller with reason, given reason. + const cancelAlgorithm = (reason) => { + // If the aborted fetch was already terminated, then we do not + // need to do anything. + if (!isCancelled(fetchParams)) { + fetchParams.controller.abort(reason) + } } - return lead === 0 && trail === str.length - 1 ? str : str.slice(lead, trail + 1) -} + // 13. Let highWaterMark be a non-negative, non-NaN number, chosen by + // the user agent. + // TODO -// https://infra.spec.whatwg.org/#serialize-a-javascript-value-to-a-json-string -function serializeJavascriptValueToJSONString (value) { - // 1. Let result be ? Call(%JSON.stringify%, undefined, « value »). - const result = JSON.stringify(value) + // 14. Let sizeAlgorithm be an algorithm that accepts a chunk object + // and returns a non-negative, non-NaN, non-infinite number, chosen by the user agent. + // TODO - // 2. If result is undefined, then throw a TypeError. - if (result === undefined) { - throw new TypeError('Value is not JSON serializable') - } + // 15. Let stream be a new ReadableStream. + // 16. Set up stream with byte reading support with pullAlgorithm set to pullAlgorithm, + // cancelAlgorithm set to cancelAlgorithm. + const stream = new ReadableStream( + { + start (controller) { + fetchParams.controller.controller = controller + }, + pull: pullAlgorithm, + cancel: cancelAlgorithm, + type: 'bytes' + } + ) - // 3. Assert: result is a string. - assert(typeof result === 'string') + // 17. Run these steps, but abort when the ongoing fetch is terminated: - // 4. Return result. - return result -} + // 1. Set response’s body to a new body whose stream is stream. + response.body = { stream, source: null, length: null } -module.exports = { - collectASequenceOfCodePoints, - collectASequenceOfCodePointsFast, - forgivingBase64, - isASCIIWhitespace, - isomorphicDecode, - isomorphicEncode, - parseJSONFromBytes, - removeASCIIWhitespace, - removeChars, - serializeJavascriptValueToJSONString -} + // 2. If response is not a network error and request’s cache mode is + // not "no-store", then update response in httpCache for request. + // TODO + // 3. If includeCredentials is true and the user agent is not configured + // to block cookies for request (see section 7 of [COOKIES]), then run the + // "set-cookie-string" parsing algorithm (see section 5.2 of [COOKIES]) on + // the value of each header whose name is a byte-case-insensitive match for + // `Set-Cookie` in response’s header list, if any, and request’s current URL. + // TODO -/***/ }), + // 18. If aborted, then: + // TODO -/***/ 8361: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // 19. Run these steps in parallel: -"use strict"; + // 1. Run these steps, but abort when fetchParams is canceled: + if (!fetchParams.controller.resume) { + fetchParams.controller.on('terminated', onAborted) + } + fetchParams.controller.resume = async () => { + // 1. While true + while (true) { + // 1-3. See onData... -const assert = __nccwpck_require__(4589) -const { runtimeFeatures } = __nccwpck_require__(1422) + // 4. Set bytes to the result of handling content codings given + // codings and bytes. + let bytes + let isFailure + try { + const { done, value } = await fetchParams.controller.next() -/** - * @typedef {object} Metadata - * @property {SRIHashAlgorithm} alg - The algorithm used for the hash. - * @property {string} val - The base64-encoded hash value. - */ + if (isAborted(fetchParams)) { + break + } -/** - * @typedef {Metadata[]} MetadataList - */ + bytes = done ? undefined : value + } catch (err) { + if (fetchParams.controller.ended && !timingInfo.encodedBodySize) { + // zlib doesn't like empty streams. + bytes = undefined + } else { + bytes = err -/** - * @typedef {('sha256' | 'sha384' | 'sha512')} SRIHashAlgorithm - */ + // err may be propagated from the result of calling readablestream.cancel, + // which might not be an error. https://github.com/nodejs/undici/issues/2009 + isFailure = true + } + } -/** - * @type {Map} - * - * The valid SRI hash algorithm token set is the ordered set « "sha256", - * "sha384", "sha512" » (corresponding to SHA-256, SHA-384, and SHA-512 - * respectively). The ordering of this set is meaningful, with stronger - * algorithms appearing later in the set. - * - * @see https://w3c.github.io/webappsec-subresource-integrity/#valid-sri-hash-algorithm-token-set - */ -const validSRIHashAlgorithmTokenSet = new Map([['sha256', 0], ['sha384', 1], ['sha512', 2]]) + if (bytes === undefined) { + // 2. Otherwise, if the bytes transmission for response’s message + // body is done normally and stream is readable, then close + // stream, finalize response for fetchParams and response, and + // abort these in-parallel steps. + readableStreamClose(fetchParams.controller.controller) -// https://nodejs.org/api/crypto.html#determining-if-crypto-support-is-unavailable -/** @type {import('node:crypto')} */ -let crypto + finalizeResponse(fetchParams, response) -if (runtimeFeatures.has('crypto')) { - crypto = __nccwpck_require__(7598) - const cryptoHashes = crypto.getHashes() + return + } - // If no hashes are available, we cannot support SRI. - if (cryptoHashes.length === 0) { - validSRIHashAlgorithmTokenSet.clear() - } + // 5. Increase timingInfo’s decoded body size by bytes’s length. + timingInfo.decodedBodySize += bytes?.byteLength ?? 0 - for (const algorithm of validSRIHashAlgorithmTokenSet.keys()) { - // If the algorithm is not supported, remove it from the list. - if (cryptoHashes.includes(algorithm) === false) { - validSRIHashAlgorithmTokenSet.delete(algorithm) - } - } -} else { - // If crypto is not available, we cannot support SRI. - validSRIHashAlgorithmTokenSet.clear() -} + // 6. If bytes is failure, then terminate fetchParams’s controller. + if (isFailure) { + fetchParams.controller.terminate(bytes) + return + } -/** - * @typedef GetSRIHashAlgorithmIndex - * @type {(algorithm: SRIHashAlgorithm) => number} - * @param {SRIHashAlgorithm} algorithm - * @returns {number} The index of the algorithm in the valid SRI hash algorithm - * token set. - */ - -const getSRIHashAlgorithmIndex = /** @type {GetSRIHashAlgorithmIndex} */ (Map.prototype.get.bind( - validSRIHashAlgorithmTokenSet)) + // 7. Enqueue a Uint8Array wrapping an ArrayBuffer containing bytes + // into stream. + const buffer = new Uint8Array(bytes) + if (buffer.byteLength) { + fetchParams.controller.controller.enqueue(buffer) + } -/** - * @typedef IsValidSRIHashAlgorithm - * @type {(algorithm: string) => algorithm is SRIHashAlgorithm} - * @param {*} algorithm - * @returns {algorithm is SRIHashAlgorithm} - */ + // 8. If stream is errored, then terminate the ongoing fetch. + if (isErrored(stream)) { + fetchParams.controller.terminate() + return + } -const isValidSRIHashAlgorithm = /** @type {IsValidSRIHashAlgorithm} */ ( - Map.prototype.has.bind(validSRIHashAlgorithmTokenSet) -) + // 9. If stream doesn’t need more data ask the user agent to suspend + // the ongoing fetch. + if (fetchParams.controller.controller.desiredSize <= 0) { + return + } + } + } -/** - * @param {Uint8Array} bytes - * @param {string} metadataList - * @returns {boolean} - * - * @see https://w3c.github.io/webappsec-subresource-integrity/#does-response-match-metadatalist - */ -const bytesMatch = runtimeFeatures.has('crypto') === false || validSRIHashAlgorithmTokenSet.size === 0 - // If node is not built with OpenSSL support, we cannot check - // a request's integrity, so allow it by default (the spec will - // allow requests if an invalid hash is given, as precedence). - ? () => true - : (bytes, metadataList) => { - // 1. Let parsedMetadata be the result of parsing metadataList. - const parsedMetadata = parseMetadata(metadataList) + // 2. If aborted, then: + function onAborted (reason) { + // 2. If fetchParams is aborted, then: + if (isAborted(fetchParams)) { + // 1. Set response’s aborted flag. + response.aborted = true - // 2. If parsedMetadata is empty set, return true. - if (parsedMetadata.length === 0) { - return true + // 2. If stream is readable, then error stream with the result of + // deserialize a serialized abort reason given fetchParams’s + // controller’s serialized abort reason and an + // implementation-defined realm. + if (isReadable(stream)) { + fetchParams.controller.controller.error( + fetchParams.controller.serializedAbortReason + ) + } + } else { + // 3. Otherwise, if stream is readable, error stream with a TypeError. + if (isReadable(stream)) { + fetchParams.controller.controller.error(new TypeError('terminated', { + cause: isErrorLike(reason) ? reason : undefined + })) } + } - // 3. Let metadata be the result of getting the strongest - // metadata from parsedMetadata. - const metadata = getStrongestMetadata(parsedMetadata) + // 4. If connection uses HTTP/2, then transmit an RST_STREAM frame. + // 5. Otherwise, the user agent should close connection unless it would be bad for performance to do so. + fetchParams.controller.connection.destroy() + } - // 4. For each item in metadata: - for (const item of metadata) { - // 1. Let algorithm be the item["alg"]. - const algorithm = item.alg + // 20. Return response. + return response - // 2. Let expectedValue be the item["val"]. - const expectedValue = item.val + function dispatch ({ body }) { + const url = requestCurrentURL(request) + /** @type {import('../../..').Agent} */ + const agent = fetchParams.controller.dispatcher - // See https://github.com/web-platform-tests/wpt/commit/e4c5cc7a5e48093220528dfdd1c4012dc3837a0e - // "be liberal with padding". This is annoying, and it's not even in the spec. + return new Promise((resolve, reject) => agent.dispatch( + { + path: url.pathname + url.search, + origin: url.origin, + method: request.method, + body: agent.isMockActive ? request.body && (request.body.source || request.body.stream) : body, + headers: request.headersList.entries, + maxRedirections: 0, + upgrade: request.mode === 'websocket' ? 'websocket' : undefined + }, + { + body: null, + abort: null, - // 3. Let actualValue be the result of applying algorithm to bytes . - const actualValue = applyAlgorithmToBytes(algorithm, bytes) + onConnect (abort) { + // TODO (fix): Do we need connection here? + const { connection } = fetchParams.controller - // 4. If actualValue is a case-sensitive match for expectedValue, - // return true. - if (caseSensitiveMatch(actualValue, expectedValue)) { - return true - } - } + // Set timingInfo’s final connection timing info to the result of calling clamp and coarsen + // connection timing info with connection’s timing info, timingInfo’s post-redirect start + // time, and fetchParams’s cross-origin isolated capability. + // TODO: implement connection timing + timingInfo.finalConnectionTimingInfo = clampAndCoarsenConnectionTimingInfo(undefined, timingInfo.postRedirectStartTime, fetchParams.crossOriginIsolatedCapability) - // 5. Return false. - return false - } + if (connection.destroyed) { + abort(new DOMException('The operation was aborted.', 'AbortError')) + } else { + fetchParams.controller.on('terminated', abort) + this.abort = connection.abort = abort + } -/** - * @param {MetadataList} metadataList - * @returns {MetadataList} The strongest hash algorithm from the metadata list. - */ -function getStrongestMetadata (metadataList) { - // 1. Let result be the empty set and strongest be the empty string. - const result = [] - /** @type {Metadata|null} */ - let strongest = null + // Set timingInfo’s final network-request start time to the coarsened shared current time given + // fetchParams’s cross-origin isolated capability. + timingInfo.finalNetworkRequestStartTime = coarsenedSharedCurrentTime(fetchParams.crossOriginIsolatedCapability) + }, - // 2. For each item in set: - for (const item of metadataList) { - // 1. Assert: item["alg"] is a valid SRI hash algorithm token. - assert(isValidSRIHashAlgorithm(item.alg), 'Invalid SRI hash algorithm token') + onResponseStarted () { + // Set timingInfo’s final network-response start time to the coarsened shared current + // time given fetchParams’s cross-origin isolated capability, immediately after the + // user agent’s HTTP parser receives the first byte of the response (e.g., frame header + // bytes for HTTP/2 or response status line for HTTP/1.x). + timingInfo.finalNetworkResponseStartTime = coarsenedSharedCurrentTime(fetchParams.crossOriginIsolatedCapability) + }, - // 2. If result is the empty set, then: - if (result.length === 0) { - // 1. Append item to result. - result.push(item) + onHeaders (status, rawHeaders, resume, statusText) { + if (status < 200) { + return false + } - // 2. Set strongest to item. - strongest = item + const headersList = new HeadersList() - // 3. Continue. - continue - } + for (let i = 0; i < rawHeaders.length; i += 2) { + headersList.append(bufferToLowerCasedHeaderName(rawHeaders[i]), rawHeaders[i + 1].toString('latin1'), true) + } + const location = headersList.get('location', true) - // 3. Let currentAlgorithm be strongest["alg"], and currentAlgorithmIndex be - // the index of currentAlgorithm in the valid SRI hash algorithm token set. - const currentAlgorithm = /** @type {Metadata} */ (strongest).alg - const currentAlgorithmIndex = getSRIHashAlgorithmIndex(currentAlgorithm) + this.body = new Readable({ read: resume }) - // 4. Let newAlgorithm be the item["alg"], and newAlgorithmIndex be the - // index of newAlgorithm in the valid SRI hash algorithm token set. - const newAlgorithm = item.alg - const newAlgorithmIndex = getSRIHashAlgorithmIndex(newAlgorithm) + const willFollow = location && request.redirect === 'follow' && + redirectStatusSet.has(status) - // 5. If newAlgorithmIndex is less than currentAlgorithmIndex, then continue. - if (newAlgorithmIndex < currentAlgorithmIndex) { - continue + const decoders = [] - // 6. Otherwise, if newAlgorithmIndex is greater than - // currentAlgorithmIndex: - } else if (newAlgorithmIndex > currentAlgorithmIndex) { - // 1. Set strongest to item. - strongest = item + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding + if (request.method !== 'HEAD' && request.method !== 'CONNECT' && !nullBodyStatus.includes(status) && !willFollow) { + // https://www.rfc-editor.org/rfc/rfc7231#section-3.1.2.1 + const contentEncoding = headersList.get('content-encoding', true) + // "All content-coding values are case-insensitive..." + /** @type {string[]} */ + const codings = contentEncoding ? contentEncoding.toLowerCase().split(',') : [] - // 2. Set result to « item ». - result[0] = item - result.length = 1 + // Limit the number of content-encodings to prevent resource exhaustion. + // CVE fix similar to urllib3 (GHSA-gm62-xv2j-4w53) and curl (CVE-2022-32206). + const maxContentEncodings = 5 + if (codings.length > maxContentEncodings) { + reject(new Error(`too many content-encodings in response: ${codings.length}, maximum allowed is ${maxContentEncodings}`)) + return true + } - // 7. Otherwise, newAlgorithmIndex and currentAlgorithmIndex are the same - // value. Append item to result. - } else { - result.push(item) - } - } + for (let i = codings.length - 1; i >= 0; --i) { + const coding = codings[i].trim() + // https://www.rfc-editor.org/rfc/rfc9112.html#section-7.2 + if (coding === 'x-gzip' || coding === 'gzip') { + decoders.push(zlib.createGunzip({ + // Be less strict when decoding compressed responses, since sometimes + // servers send slightly invalid responses that are still accepted + // by common browsers. + // Always using Z_SYNC_FLUSH is what cURL does. + flush: zlib.constants.Z_SYNC_FLUSH, + finishFlush: zlib.constants.Z_SYNC_FLUSH + })) + } else if (coding === 'deflate') { + decoders.push(createInflate({ + flush: zlib.constants.Z_SYNC_FLUSH, + finishFlush: zlib.constants.Z_SYNC_FLUSH + })) + } else if (coding === 'br') { + decoders.push(zlib.createBrotliDecompress({ + flush: zlib.constants.BROTLI_OPERATION_FLUSH, + finishFlush: zlib.constants.BROTLI_OPERATION_FLUSH + })) + } else if (coding === 'zstd' && hasZstd) { + decoders.push(zlib.createZstdDecompress({ + flush: zlib.constants.ZSTD_e_continue, + finishFlush: zlib.constants.ZSTD_e_end + })) + } else { + decoders.length = 0 + break + } + } + } - // 3. Return result. - return result -} + const onError = this.onError.bind(this) -/** - * @param {string} metadata - * @returns {MetadataList} - * - * @see https://w3c.github.io/webappsec-subresource-integrity/#parse-metadata - */ -function parseMetadata (metadata) { - // 1. Let result be the empty set. - /** @type {MetadataList} */ - const result = [] + resolve({ + status, + statusText, + headersList, + body: decoders.length + ? pipeline(this.body, ...decoders, (err) => { + if (err) { + this.onError(err) + } + }).on('error', onError) + : this.body.on('error', onError) + }) - // 2. For each item returned by splitting metadata on spaces: - for (const item of metadata.split(' ')) { - // 1. Let expression-and-options be the result of splitting item on U+003F (?). - const expressionAndOptions = item.split('?', 1) + return true + }, - // 2. Let algorithm-expression be expression-and-options[0]. - const algorithmExpression = expressionAndOptions[0] + onData (chunk) { + if (fetchParams.controller.dump) { + return + } - // 3. Let base64-value be the empty string. - let base64Value = '' + // 1. If one or more bytes have been transmitted from response’s + // message body, then: - // 4. Let algorithm-and-value be the result of splitting algorithm-expression on U+002D (-). - const algorithmAndValue = [algorithmExpression.slice(0, 6), algorithmExpression.slice(7)] + // 1. Let bytes be the transmitted bytes. + const bytes = chunk - // 5. Let algorithm be algorithm-and-value[0]. - const algorithm = algorithmAndValue[0] + // 2. Let codings be the result of extracting header list values + // given `Content-Encoding` and response’s header list. + // See pullAlgorithm. - // 6. If algorithm is not a valid SRI hash algorithm token, then continue. - if (!isValidSRIHashAlgorithm(algorithm)) { - continue - } + // 3. Increase timingInfo’s encoded body size by bytes’s length. + timingInfo.encodedBodySize += bytes.byteLength - // 7. If algorithm-and-value[1] exists, set base64-value to - // algorithm-and-value[1]. - if (algorithmAndValue[1]) { - base64Value = algorithmAndValue[1] - } + // 4. See pullAlgorithm... - // 8. Let metadata be the ordered map - // «["alg" → algorithm, "val" → base64-value]». - const metadata = { - alg: algorithm, - val: base64Value - } + return this.body.push(bytes) + }, - // 9. Append metadata to result. - result.push(metadata) - } + onComplete () { + if (this.abort) { + fetchParams.controller.off('terminated', this.abort) + } - // 3. Return result. - return result -} + fetchParams.controller.ended = true -/** - * Applies the specified hash algorithm to the given bytes - * - * @typedef {(algorithm: SRIHashAlgorithm, bytes: Uint8Array) => string} ApplyAlgorithmToBytes - * @param {SRIHashAlgorithm} algorithm - * @param {Uint8Array} bytes - * @returns {string} - */ -const applyAlgorithmToBytes = (algorithm, bytes) => { - return crypto.hash(algorithm, bytes, 'base64') -} + this.body.push(null) + }, -/** - * Compares two base64 strings, allowing for base64url - * in the second string. - * - * @param {string} actualValue base64 encoded string - * @param {string} expectedValue base64 or base64url encoded string - * @returns {boolean} - */ -function caseSensitiveMatch (actualValue, expectedValue) { - // Ignore padding characters from the end of the strings by - // decreasing the length by 1 or 2 if the last characters are `=`. - let actualValueLength = actualValue.length - if (actualValueLength !== 0 && actualValue[actualValueLength - 1] === '=') { - actualValueLength -= 1 - } - if (actualValueLength !== 0 && actualValue[actualValueLength - 1] === '=') { - actualValueLength -= 1 - } - let expectedValueLength = expectedValue.length - if (expectedValueLength !== 0 && expectedValue[expectedValueLength - 1] === '=') { - expectedValueLength -= 1 - } - if (expectedValueLength !== 0 && expectedValue[expectedValueLength - 1] === '=') { - expectedValueLength -= 1 - } + onError (error) { + if (this.abort) { + fetchParams.controller.off('terminated', this.abort) + } - if (actualValueLength !== expectedValueLength) { - return false - } + this.body?.destroy(error) - for (let i = 0; i < actualValueLength; ++i) { - if ( - actualValue[i] === expectedValue[i] || - (actualValue[i] === '+' && expectedValue[i] === '-') || - (actualValue[i] === '/' && expectedValue[i] === '_') - ) { - continue - } - return false - } + fetchParams.controller.terminate(error) - return true + reject(error) + }, + + onUpgrade (status, rawHeaders, socket) { + // We need to support 200 for websocket over h2 as per RFC-8441 + // Absence of session means H1 + if ((socket.session != null && status !== 200) || (socket.session == null && status !== 101)) { + return false + } + + const headersList = new HeadersList() + + for (let i = 0; i < rawHeaders.length; i += 2) { + headersList.append(bufferToLowerCasedHeaderName(rawHeaders[i]), rawHeaders[i + 1].toString('latin1'), true) + } + + resolve({ + status, + statusText: STATUS_CODES[status], + headersList, + socket + }) + + return true + } + } + )) + } } module.exports = { - applyAlgorithmToBytes, - bytesMatch, - caseSensitiveMatch, - isValidSRIHashAlgorithm, - getStrongestMetadata, - parseMetadata + fetch, + Fetch, + fetching, + finalizeAndReportTiming } /***/ }), -/***/ 2318: +/***/ 4517: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; +/* globals AbortController */ -const { types, inspect } = __nccwpck_require__(7975) -const { runtimeFeatures } = __nccwpck_require__(1422) -const UNDEFINED = 1 -const BOOLEAN = 2 -const STRING = 3 -const SYMBOL = 4 -const NUMBER = 5 -const BIGINT = 6 -const NULL = 7 -const OBJECT = 8 // function and object +const { extractBody, mixinBody, cloneBody, bodyUnusable } = __nccwpck_require__(9742) +const { Headers, fill: fillHeaders, HeadersList, setHeadersGuard, getHeadersGuard, setHeadersList, getHeadersList } = __nccwpck_require__(7754) +const util = __nccwpck_require__(2550) +const nodeUtil = __nccwpck_require__(7975) +const { + isValidHTTPToken, + sameOrigin, + environmentSettingsObject +} = __nccwpck_require__(3106) +const { + forbiddenMethodsSet, + corsSafeListedMethodsSet, + referrerPolicy, + requestRedirect, + requestMode, + requestCredentials, + requestCache, + requestDuplex +} = __nccwpck_require__(8973) +const { kEnumerableProperty, normalizedMethodRecordsBase, normalizedMethodRecords } = util +const { webidl } = __nccwpck_require__(909) +const { URLSerializer } = __nccwpck_require__(1410) +const { kConstruct } = __nccwpck_require__(8261) +const assert = __nccwpck_require__(4589) +const { getMaxListeners, setMaxListeners, defaultMaxListeners } = __nccwpck_require__(8474) -const FunctionPrototypeSymbolHasInstance = Function.call.bind(Function.prototype[Symbol.hasInstance]) +const kAbortController = Symbol('abortController') -/** @type {import('../../../types/webidl').Webidl} */ -const webidl = { - converters: {}, - util: {}, - errors: {}, - is: {} -} +const requestFinalizer = new FinalizationRegistry(({ signal, abort }) => { + signal.removeEventListener('abort', abort) +}) -/** - * @description Instantiate an error. - * - * @param {Object} opts - * @param {string} opts.header - * @param {string} opts.message - * @returns {TypeError} - */ -webidl.errors.exception = function (message) { - return new TypeError(`${message.header}: ${message.message}`) -} +const dependentControllerMap = new WeakMap() -/** - * @description Instantiate an error when conversion from one type to another has failed. - * - * @param {Object} opts - * @param {string} opts.prefix - * @param {string} opts.argument - * @param {string[]} opts.types - * @returns {TypeError} - */ -webidl.errors.conversionFailed = function (opts) { - const plural = opts.types.length === 1 ? '' : ' one of' - const message = - `${opts.argument} could not be converted to` + - `${plural}: ${opts.types.join(', ')}.` +let abortSignalHasEventHandlerLeakWarning - return webidl.errors.exception({ - header: opts.prefix, - message - }) +try { + abortSignalHasEventHandlerLeakWarning = getMaxListeners(new AbortController().signal) > 0 +} catch { + abortSignalHasEventHandlerLeakWarning = false } -/** - * @description Instantiate an error when an invalid argument is provided - * - * @param {Object} context - * @param {string} context.prefix - * @param {string} context.value - * @param {string} context.type - * @returns {TypeError} - */ -webidl.errors.invalidArgument = function (context) { - return webidl.errors.exception({ - header: context.prefix, - message: `"${context.value}" is an invalid ${context.type}.` - }) -} +function buildAbort (acRef) { + return abort -// https://webidl.spec.whatwg.org/#implements -webidl.brandCheck = function (V, I) { - if (!FunctionPrototypeSymbolHasInstance(I, V)) { - const err = new TypeError('Illegal invocation') - err.code = 'ERR_INVALID_THIS' // node compat. - throw err - } -} + function abort () { + const ac = acRef.deref() + if (ac !== undefined) { + // Currently, there is a problem with FinalizationRegistry. + // https://github.com/nodejs/node/issues/49344 + // https://github.com/nodejs/node/issues/47748 + // In the case of abort, the first step is to unregister from it. + // If the controller can refer to it, it is still registered. + // It will be removed in the future. + requestFinalizer.unregister(abort) -webidl.brandCheckMultiple = function (List) { - const prototypes = List.map((c) => webidl.util.MakeTypeAssertion(c)) + // Unsubscribe a listener. + // FinalizationRegistry will no longer be called, so this must be done. + this.removeEventListener('abort', abort) - return (V) => { - if (prototypes.every(typeCheck => !typeCheck(V))) { - const err = new TypeError('Illegal invocation') - err.code = 'ERR_INVALID_THIS' // node compat. - throw err + ac.abort(this.reason) + + const controllerList = dependentControllerMap.get(ac.signal) + + if (controllerList !== undefined) { + if (controllerList.size !== 0) { + for (const ref of controllerList) { + const ctrl = ref.deref() + if (ctrl !== undefined) { + ctrl.abort(this.reason) + } + } + controllerList.clear() + } + dependentControllerMap.delete(ac.signal) + } } } } -webidl.argumentLengthCheck = function ({ length }, min, ctx) { - if (length < min) { - throw webidl.errors.exception({ - message: `${min} argument${min !== 1 ? 's' : ''} required, ` + - `but${length ? ' only' : ''} ${length} found.`, - header: ctx - }) - } -} +let patchMethodWarning = false -webidl.illegalConstructor = function () { - throw webidl.errors.exception({ - header: 'TypeError', - message: 'Illegal constructor' - }) -} +// https://fetch.spec.whatwg.org/#request-class +class Request { + /** @type {AbortSignal} */ + #signal -webidl.util.MakeTypeAssertion = function (I) { - return (O) => FunctionPrototypeSymbolHasInstance(I, O) -} + /** @type {import('../../dispatcher/dispatcher')} */ + #dispatcher -// https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values -webidl.util.Type = function (V) { - switch (typeof V) { - case 'undefined': return UNDEFINED - case 'boolean': return BOOLEAN - case 'string': return STRING - case 'symbol': return SYMBOL - case 'number': return NUMBER - case 'bigint': return BIGINT - case 'function': - case 'object': { - if (V === null) { - return NULL - } + /** @type {Headers} */ + #headers - return OBJECT + #state + + // https://fetch.spec.whatwg.org/#dom-request + constructor (input, init = undefined) { + webidl.util.markAsUncloneable(this) + + if (input === kConstruct) { + return } - } -} -webidl.util.Types = { - UNDEFINED, - BOOLEAN, - STRING, - SYMBOL, - NUMBER, - BIGINT, - NULL, - OBJECT -} + const prefix = 'Request constructor' + webidl.argumentLengthCheck(arguments, 1, prefix) -webidl.util.TypeValueToString = function (o) { - switch (webidl.util.Type(o)) { - case UNDEFINED: return 'Undefined' - case BOOLEAN: return 'Boolean' - case STRING: return 'String' - case SYMBOL: return 'Symbol' - case NUMBER: return 'Number' - case BIGINT: return 'BigInt' - case NULL: return 'Null' - case OBJECT: return 'Object' - } -} + input = webidl.converters.RequestInfo(input) + init = webidl.converters.RequestInit(init) -webidl.util.markAsUncloneable = runtimeFeatures.has('markAsUncloneable') - ? (__nccwpck_require__(5919).markAsUncloneable) - : () => {} + // 1. Let request be null. + let request = null -// https://webidl.spec.whatwg.org/#abstract-opdef-converttoint -webidl.util.ConvertToInt = function (V, bitLength, signedness, flags) { - let upperBound - let lowerBound + // 2. Let fallbackMode be null. + let fallbackMode = null - // 1. If bitLength is 64, then: - if (bitLength === 64) { - // 1. Let upperBound be 2^53 − 1. - upperBound = Math.pow(2, 53) - 1 + // 3. Let baseURL be this’s relevant settings object’s API base URL. + const baseUrl = environmentSettingsObject.settingsObject.baseUrl - // 2. If signedness is "unsigned", then let lowerBound be 0. - if (signedness === 'unsigned') { - lowerBound = 0 - } else { - // 3. Otherwise let lowerBound be −2^53 + 1. - lowerBound = Math.pow(-2, 53) + 1 - } - } else if (signedness === 'unsigned') { - // 2. Otherwise, if signedness is "unsigned", then: + // 4. Let signal be null. + let signal = null - // 1. Let lowerBound be 0. - lowerBound = 0 + // 5. If input is a string, then: + if (typeof input === 'string') { + this.#dispatcher = init.dispatcher - // 2. Let upperBound be 2^bitLength − 1. - upperBound = Math.pow(2, bitLength) - 1 - } else { - // 3. Otherwise: + // 1. Let parsedURL be the result of parsing input with baseURL. + // 2. If parsedURL is failure, then throw a TypeError. + let parsedURL + try { + parsedURL = new URL(input, baseUrl) + } catch (err) { + throw new TypeError('Failed to parse URL from ' + input, { cause: err }) + } - // 1. Let lowerBound be -2^bitLength − 1. - lowerBound = Math.pow(-2, bitLength) - 1 + // 3. If parsedURL includes credentials, then throw a TypeError. + if (parsedURL.username || parsedURL.password) { + throw new TypeError( + 'Request cannot be constructed from a URL that includes credentials: ' + + input + ) + } - // 2. Let upperBound be 2^bitLength − 1 − 1. - upperBound = Math.pow(2, bitLength - 1) - 1 - } + // 4. Set request to a new request whose URL is parsedURL. + request = makeRequest({ urlList: [parsedURL] }) - // 4. Let x be ? ToNumber(V). - let x = Number(V) + // 5. Set fallbackMode to "cors". + fallbackMode = 'cors' + } else { + // 6. Otherwise: - // 5. If x is −0, then set x to +0. - if (x === 0) { - x = 0 - } + // 7. Assert: input is a Request object. + assert(webidl.is.Request(input)) - // 6. If the conversion is to an IDL type associated - // with the [EnforceRange] extended attribute, then: - if (webidl.util.HasFlag(flags, webidl.attributes.EnforceRange)) { - // 1. If x is NaN, +∞, or −∞, then throw a TypeError. - if ( - Number.isNaN(x) || - x === Number.POSITIVE_INFINITY || - x === Number.NEGATIVE_INFINITY - ) { - throw webidl.errors.exception({ - header: 'Integer conversion', - message: `Could not convert ${webidl.util.Stringify(V)} to an integer.` - }) - } + // 8. Set request to input’s request. + request = input.#state - // 2. Set x to IntegerPart(x). - x = webidl.util.IntegerPart(x) + // 9. Set signal to input’s signal. + signal = input.#signal - // 3. If x < lowerBound or x > upperBound, then - // throw a TypeError. - if (x < lowerBound || x > upperBound) { - throw webidl.errors.exception({ - header: 'Integer conversion', - message: `Value must be between ${lowerBound}-${upperBound}, got ${x}.` - }) + this.#dispatcher = init.dispatcher || input.#dispatcher } - // 4. Return x. - return x - } + // 7. Let origin be this’s relevant settings object’s origin. + const origin = environmentSettingsObject.settingsObject.origin - // 7. If x is not NaN and the conversion is to an IDL - // type associated with the [Clamp] extended - // attribute, then: - if (!Number.isNaN(x) && webidl.util.HasFlag(flags, webidl.attributes.Clamp)) { - // 1. Set x to min(max(x, lowerBound), upperBound). - x = Math.min(Math.max(x, lowerBound), upperBound) + // 8. Let window be "client". + let window = 'client' - // 2. Round x to the nearest integer, choosing the - // even integer if it lies halfway between two, - // and choosing +0 rather than −0. - if (Math.floor(x) % 2 === 0) { - x = Math.floor(x) - } else { - x = Math.ceil(x) + // 9. If request’s window is an environment settings object and its origin + // is same origin with origin, then set window to request’s window. + if ( + request.window?.constructor?.name === 'EnvironmentSettingsObject' && + sameOrigin(request.window, origin) + ) { + window = request.window } - // 3. Return x. - return x - } + // 10. If init["window"] exists and is non-null, then throw a TypeError. + if (init.window != null) { + throw new TypeError(`'window' option '${window}' must be null`) + } - // 8. If x is NaN, +0, +∞, or −∞, then return +0. - if ( - Number.isNaN(x) || - (x === 0 && Object.is(0, x)) || - x === Number.POSITIVE_INFINITY || - x === Number.NEGATIVE_INFINITY - ) { - return 0 - } + // 11. If init["window"] exists, then set window to "no-window". + if ('window' in init) { + window = 'no-window' + } - // 9. Set x to IntegerPart(x). - x = webidl.util.IntegerPart(x) + // 12. Set request to a new request with the following properties: + request = makeRequest({ + // URL request’s URL. + // undici implementation note: this is set as the first item in request's urlList in makeRequest + // method request’s method. + method: request.method, + // header list A copy of request’s header list. + // undici implementation note: headersList is cloned in makeRequest + headersList: request.headersList, + // unsafe-request flag Set. + unsafeRequest: request.unsafeRequest, + // client This’s relevant settings object. + client: environmentSettingsObject.settingsObject, + // window window. + window, + // priority request’s priority. + priority: request.priority, + // origin request’s origin. The propagation of the origin is only significant for navigation requests + // being handled by a service worker. In this scenario a request can have an origin that is different + // from the current client. + origin: request.origin, + // referrer request’s referrer. + referrer: request.referrer, + // referrer policy request’s referrer policy. + referrerPolicy: request.referrerPolicy, + // mode request’s mode. + mode: request.mode, + // credentials mode request’s credentials mode. + credentials: request.credentials, + // cache mode request’s cache mode. + cache: request.cache, + // redirect mode request’s redirect mode. + redirect: request.redirect, + // integrity metadata request’s integrity metadata. + integrity: request.integrity, + // keepalive request’s keepalive. + keepalive: request.keepalive, + // reload-navigation flag request’s reload-navigation flag. + reloadNavigation: request.reloadNavigation, + // history-navigation flag request’s history-navigation flag. + historyNavigation: request.historyNavigation, + // URL list A clone of request’s URL list. + urlList: [...request.urlList] + }) - // 10. Set x to x modulo 2^bitLength. - x = x % Math.pow(2, bitLength) + const initHasKey = Object.keys(init).length !== 0 - // 11. If signedness is "signed" and x ≥ 2^bitLength − 1, - // then return x − 2^bitLength. - if (signedness === 'signed' && x >= Math.pow(2, bitLength) - 1) { - return x - Math.pow(2, bitLength) - } + // 13. If init is not empty, then: + if (initHasKey) { + // 1. If request’s mode is "navigate", then set it to "same-origin". + if (request.mode === 'navigate') { + request.mode = 'same-origin' + } - // 12. Otherwise, return x. - return x -} + // 2. Unset request’s reload-navigation flag. + request.reloadNavigation = false -// https://webidl.spec.whatwg.org/#abstract-opdef-integerpart -webidl.util.IntegerPart = function (n) { - // 1. Let r be floor(abs(n)). - const r = Math.floor(Math.abs(n)) + // 3. Unset request’s history-navigation flag. + request.historyNavigation = false - // 2. If n < 0, then return -1 × r. - if (n < 0) { - return -1 * r - } + // 4. Set request’s origin to "client". + request.origin = 'client' - // 3. Otherwise, return r. - return r -} + // 5. Set request’s referrer to "client" + request.referrer = 'client' -webidl.util.Stringify = function (V) { - const type = webidl.util.Type(V) + // 6. Set request’s referrer policy to the empty string. + request.referrerPolicy = '' - switch (type) { - case SYMBOL: - return `Symbol(${V.description})` - case OBJECT: - return inspect(V) - case STRING: - return `"${V}"` - case BIGINT: - return `${V}n` - default: - return `${V}` - } -} + // 7. Set request’s URL to request’s current URL. + request.url = request.urlList[request.urlList.length - 1] -webidl.util.IsResizableArrayBuffer = function (V) { - if (types.isArrayBuffer(V)) { - return V.resizable - } + // 8. Set request’s URL list to « request’s URL ». + request.urlList = [request.url] + } - if (types.isSharedArrayBuffer(V)) { - return V.growable - } + // 14. If init["referrer"] exists, then: + if (init.referrer !== undefined) { + // 1. Let referrer be init["referrer"]. + const referrer = init.referrer - throw webidl.errors.exception({ - header: 'IsResizableArrayBuffer', - message: `"${webidl.util.Stringify(V)}" is not an array buffer.` - }) -} + // 2. If referrer is the empty string, then set request’s referrer to "no-referrer". + if (referrer === '') { + request.referrer = 'no-referrer' + } else { + // 1. Let parsedReferrer be the result of parsing referrer with + // baseURL. + // 2. If parsedReferrer is failure, then throw a TypeError. + let parsedReferrer + try { + parsedReferrer = new URL(referrer, baseUrl) + } catch (err) { + throw new TypeError(`Referrer "${referrer}" is not a valid URL.`, { cause: err }) + } -webidl.util.HasFlag = function (flags, attributes) { - return typeof flags === 'number' && (flags & attributes) === attributes -} + // 3. If one of the following is true + // - parsedReferrer’s scheme is "about" and path is the string "client" + // - parsedReferrer’s origin is not same origin with origin + // then set request’s referrer to "client". + if ( + (parsedReferrer.protocol === 'about:' && parsedReferrer.hostname === 'client') || + (origin && !sameOrigin(parsedReferrer, environmentSettingsObject.settingsObject.baseUrl)) + ) { + request.referrer = 'client' + } else { + // 4. Otherwise, set request’s referrer to parsedReferrer. + request.referrer = parsedReferrer + } + } + } -// https://webidl.spec.whatwg.org/#es-sequence -webidl.sequenceConverter = function (converter) { - return (V, prefix, argument, Iterable) => { - // 1. If Type(V) is not Object, throw a TypeError. - if (webidl.util.Type(V) !== OBJECT) { - throw webidl.errors.exception({ - header: prefix, - message: `${argument} (${webidl.util.Stringify(V)}) is not iterable.` - }) + // 15. If init["referrerPolicy"] exists, then set request’s referrer policy + // to it. + if (init.referrerPolicy !== undefined) { + request.referrerPolicy = init.referrerPolicy } - // 2. Let method be ? GetMethod(V, @@iterator). - /** @type {Generator} */ - const method = typeof Iterable === 'function' ? Iterable() : V?.[Symbol.iterator]?.() - const seq = [] - let index = 0 + // 16. Let mode be init["mode"] if it exists, and fallbackMode otherwise. + let mode + if (init.mode !== undefined) { + mode = init.mode + } else { + mode = fallbackMode + } - // 3. If method is undefined, throw a TypeError. - if ( - method === undefined || - typeof method.next !== 'function' - ) { + // 17. If mode is "navigate", then throw a TypeError. + if (mode === 'navigate') { throw webidl.errors.exception({ - header: prefix, - message: `${argument} is not iterable.` + header: 'Request constructor', + message: 'invalid request mode navigate.' }) } - // https://webidl.spec.whatwg.org/#create-sequence-from-iterable - while (true) { - const { done, value } = method.next() - - if (done) { - break - } + // 18. If mode is non-null, set request’s mode to mode. + if (mode != null) { + request.mode = mode + } - seq.push(converter(value, prefix, `${argument}[${index++}]`)) + // 19. If init["credentials"] exists, then set request’s credentials mode + // to it. + if (init.credentials !== undefined) { + request.credentials = init.credentials } - return seq - } -} + // 18. If init["cache"] exists, then set request’s cache mode to it. + if (init.cache !== undefined) { + request.cache = init.cache + } -// https://webidl.spec.whatwg.org/#es-to-record -webidl.recordConverter = function (keyConverter, valueConverter) { - return (O, prefix, argument) => { - // 1. If Type(O) is not Object, throw a TypeError. - if (webidl.util.Type(O) !== OBJECT) { - throw webidl.errors.exception({ - header: prefix, - message: `${argument} ("${webidl.util.TypeValueToString(O)}") is not an Object.` - }) + // 21. If request’s cache mode is "only-if-cached" and request’s mode is + // not "same-origin", then throw a TypeError. + if (request.cache === 'only-if-cached' && request.mode !== 'same-origin') { + throw new TypeError( + "'only-if-cached' can be set only with 'same-origin' mode" + ) } - // 2. Let result be a new empty instance of record. - const result = {} + // 22. If init["redirect"] exists, then set request’s redirect mode to it. + if (init.redirect !== undefined) { + request.redirect = init.redirect + } - if (!types.isProxy(O)) { - // 1. Let desc be ? O.[[GetOwnProperty]](key). - const keys = [...Object.getOwnPropertyNames(O), ...Object.getOwnPropertySymbols(O)] + // 23. If init["integrity"] exists, then set request’s integrity metadata to it. + if (init.integrity != null) { + request.integrity = String(init.integrity) + } - for (const key of keys) { - const keyName = webidl.util.Stringify(key) + // 24. If init["keepalive"] exists, then set request’s keepalive to it. + if (init.keepalive !== undefined) { + request.keepalive = Boolean(init.keepalive) + } - // 1. Let typedKey be key converted to an IDL value of type K. - const typedKey = keyConverter(key, prefix, `Key ${keyName} in ${argument}`) + // 25. If init["method"] exists, then: + if (init.method !== undefined) { + // 1. Let method be init["method"]. + let method = init.method - // 2. Let value be ? Get(O, key). - // 3. Let typedValue be value converted to an IDL value of type V. - const typedValue = valueConverter(O[key], prefix, `${argument}[${keyName}]`) + const mayBeNormalized = normalizedMethodRecords[method] - // 4. Set result[typedKey] to typedValue. - result[typedKey] = typedValue - } + if (mayBeNormalized !== undefined) { + // Note: Bypass validation DELETE, GET, HEAD, OPTIONS, POST, PUT, PATCH and these lowercase ones + request.method = mayBeNormalized + } else { + // 2. If method is not a method or method is a forbidden method, then + // throw a TypeError. + if (!isValidHTTPToken(method)) { + throw new TypeError(`'${method}' is not a valid HTTP method.`) + } - // 5. Return result. - return result - } + const upperCase = method.toUpperCase() - // 3. Let keys be ? O.[[OwnPropertyKeys]](). - const keys = Reflect.ownKeys(O) + if (forbiddenMethodsSet.has(upperCase)) { + throw new TypeError(`'${method}' HTTP method is unsupported.`) + } - // 4. For each key of keys. - for (const key of keys) { - // 1. Let desc be ? O.[[GetOwnProperty]](key). - const desc = Reflect.getOwnPropertyDescriptor(O, key) + // 3. Normalize method. + // https://fetch.spec.whatwg.org/#concept-method-normalize + // Note: must be in uppercase + method = normalizedMethodRecordsBase[upperCase] ?? method - // 2. If desc is not undefined and desc.[[Enumerable]] is true: - if (desc?.enumerable) { - // 1. Let typedKey be key converted to an IDL value of type K. - const typedKey = keyConverter(key, prefix, argument) + // 4. Set request’s method to method. + request.method = method + } - // 2. Let value be ? Get(O, key). - // 3. Let typedValue be value converted to an IDL value of type V. - const typedValue = valueConverter(O[key], prefix, argument) + if (!patchMethodWarning && request.method === 'patch') { + process.emitWarning('Using `patch` is highly likely to result in a `405 Method Not Allowed`. `PATCH` is much more likely to succeed.', { + code: 'UNDICI-FETCH-patch' + }) - // 4. Set result[typedKey] to typedValue. - result[typedKey] = typedValue + patchMethodWarning = true } } - // 5. Return result. - return result - } -} + // 26. If init["signal"] exists, then set signal to it. + if (init.signal !== undefined) { + signal = init.signal + } -webidl.interfaceConverter = function (TypeCheck, name) { - return (V, prefix, argument) => { - if (!TypeCheck(V)) { - throw webidl.errors.exception({ - header: prefix, - message: `Expected ${argument} ("${webidl.util.Stringify(V)}") to be an instance of ${name}.` - }) + // 27. Set this’s request to request. + this.#state = request + + // 28. Set this’s signal to a new AbortSignal object with this’s relevant + // Realm. + // TODO: could this be simplified with AbortSignal.any + // (https://dom.spec.whatwg.org/#dom-abortsignal-any) + const ac = new AbortController() + this.#signal = ac.signal + + // 29. If signal is not null, then make this’s signal follow signal. + if (signal != null) { + if (signal.aborted) { + ac.abort(signal.reason) + } else { + // Keep a strong ref to ac while request object + // is alive. This is needed to prevent AbortController + // from being prematurely garbage collected. + // See, https://github.com/nodejs/undici/issues/1926. + this[kAbortController] = ac + + const acRef = new WeakRef(ac) + const abort = buildAbort(acRef) + + // If the max amount of listeners is equal to the default, increase it + if (abortSignalHasEventHandlerLeakWarning && getMaxListeners(signal) === defaultMaxListeners) { + setMaxListeners(1500, signal) + } + + util.addAbortListener(signal, abort) + // The third argument must be a registry key to be unregistered. + // Without it, you cannot unregister. + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/FinalizationRegistry + // abort is used as the unregister key. (because it is unique) + requestFinalizer.register(ac, { signal, abort }, abort) + } } - return V - } -} + // 30. Set this’s headers to a new Headers object with this’s relevant + // Realm, whose header list is request’s header list and guard is + // "request". + this.#headers = new Headers(kConstruct) + setHeadersList(this.#headers, request.headersList) + setHeadersGuard(this.#headers, 'request') -webidl.dictionaryConverter = function (converters) { - return (dictionary, prefix, argument) => { - const dict = {} + // 31. If this’s request’s mode is "no-cors", then: + if (mode === 'no-cors') { + // 1. If this’s request’s method is not a CORS-safelisted method, + // then throw a TypeError. + if (!corsSafeListedMethodsSet.has(request.method)) { + throw new TypeError( + `'${request.method} is unsupported in no-cors mode.` + ) + } - if (dictionary != null && webidl.util.Type(dictionary) !== OBJECT) { - throw webidl.errors.exception({ - header: prefix, - message: `Expected ${dictionary} to be one of: Null, Undefined, Object.` - }) + // 2. Set this’s headers’s guard to "request-no-cors". + setHeadersGuard(this.#headers, 'request-no-cors') } - for (const options of converters) { - const { key, defaultValue, required, converter } = options + // 32. If init is not empty, then: + if (initHasKey) { + /** @type {HeadersList} */ + const headersList = getHeadersList(this.#headers) + // 1. Let headers be a copy of this’s headers and its associated header + // list. + // 2. If init["headers"] exists, then set headers to init["headers"]. + const headers = init.headers !== undefined ? init.headers : new HeadersList(headersList) - if (required === true) { - if (dictionary == null || !Object.hasOwn(dictionary, key)) { - throw webidl.errors.exception({ - header: prefix, - message: `Missing required key "${key}".` - }) + // 3. Empty this’s headers’s header list. + headersList.clear() + + // 4. If headers is a Headers object, then for each header in its header + // list, append header’s name/header’s value to this’s headers. + if (headers instanceof HeadersList) { + for (const { name, value } of headers.rawValues()) { + headersList.append(name, value, false) } + // Note: Copy the `set-cookie` meta-data. + headersList.cookies = headers.cookies + } else { + // 5. Otherwise, fill this’s headers with headers. + fillHeaders(this.#headers, headers) } + } - let value = dictionary?.[key] - const hasDefault = defaultValue !== undefined + // 33. Let inputBody be input’s request’s body if input is a Request + // object; otherwise null. + const inputBody = webidl.is.Request(input) ? input.#state.body : null - // Only use defaultValue if value is undefined and - // a defaultValue options was provided. - if (hasDefault && value === undefined) { - value = defaultValue() + // 34. If either init["body"] exists and is non-null or inputBody is + // non-null, and request’s method is `GET` or `HEAD`, then throw a + // TypeError. + if ( + (init.body != null || inputBody != null) && + (request.method === 'GET' || request.method === 'HEAD') + ) { + throw new TypeError('Request with GET/HEAD method cannot have body.') + } + + // 35. Let initBody be null. + let initBody = null + + // 36. If init["body"] exists and is non-null, then: + if (init.body != null) { + // 1. Let Content-Type be null. + // 2. Set initBody and Content-Type to the result of extracting + // init["body"], with keepalive set to request’s keepalive. + const [extractedBody, contentType] = extractBody( + init.body, + request.keepalive + ) + initBody = extractedBody + + // 3, If Content-Type is non-null and this’s headers’s header list does + // not contain `Content-Type`, then append `Content-Type`/Content-Type to + // this’s headers. + if (contentType && !getHeadersList(this.#headers).contains('content-type', true)) { + this.#headers.append('content-type', contentType, true) } + } - // A key can be optional and have no default value. - // When this happens, do not perform a conversion, - // and do not assign the key a value. - if (required || hasDefault || value !== undefined) { - value = converter(value, prefix, `${argument}.${key}`) + // 37. Let inputOrInitBody be initBody if it is non-null; otherwise + // inputBody. + const inputOrInitBody = initBody ?? inputBody - if ( - options.allowedValues && - !options.allowedValues.includes(value) - ) { - throw webidl.errors.exception({ - header: prefix, - message: `${value} is not an accepted type. Expected one of ${options.allowedValues.join(', ')}.` - }) - } + // 38. If inputOrInitBody is non-null and inputOrInitBody’s source is + // null, then: + if (inputOrInitBody != null && inputOrInitBody.source == null) { + // 1. If initBody is non-null and init["duplex"] does not exist, + // then throw a TypeError. + if (initBody != null && init.duplex == null) { + throw new TypeError('RequestInit: duplex option is required when sending a body.') + } - dict[key] = value + // 2. If this’s request’s mode is neither "same-origin" nor "cors", + // then throw a TypeError. + if (request.mode !== 'same-origin' && request.mode !== 'cors') { + throw new TypeError( + 'If request is made from ReadableStream, mode should be "same-origin" or "cors"' + ) } + + // 3. Set this’s request’s use-CORS-preflight flag. + request.useCORSPreflightFlag = true } - return dict - } -} + // 39. Let finalBody be inputOrInitBody. + let finalBody = inputOrInitBody -webidl.nullableConverter = function (converter) { - return (V, prefix, argument) => { - if (V === null) { - return V + // 40. If initBody is null and inputBody is non-null, then: + if (initBody == null && inputBody != null) { + // 1. If input is unusable, then throw a TypeError. + if (bodyUnusable(input.#state)) { + throw new TypeError( + 'Cannot construct a Request with a Request object that has already been used.' + ) + } + + // 2. Set finalBody to the result of creating a proxy for inputBody. + // https://streams.spec.whatwg.org/#readablestream-create-a-proxy + const identityTransform = new TransformStream() + inputBody.stream.pipeThrough(identityTransform) + finalBody = { + source: inputBody.source, + length: inputBody.length, + stream: identityTransform.readable + } } - return converter(V, prefix, argument) + // 41. Set this’s request’s body to finalBody. + this.#state.body = finalBody } -} -/** - * @param {*} value - * @returns {boolean} - */ -webidl.is.USVString = function (value) { - return ( - typeof value === 'string' && - value.isWellFormed() - ) -} + // Returns request’s HTTP method, which is "GET" by default. + get method () { + webidl.brandCheck(this, Request) -webidl.is.ReadableStream = webidl.util.MakeTypeAssertion(ReadableStream) -webidl.is.Blob = webidl.util.MakeTypeAssertion(Blob) -webidl.is.URLSearchParams = webidl.util.MakeTypeAssertion(URLSearchParams) -webidl.is.File = webidl.util.MakeTypeAssertion(File) -webidl.is.URL = webidl.util.MakeTypeAssertion(URL) -webidl.is.AbortSignal = webidl.util.MakeTypeAssertion(AbortSignal) -webidl.is.MessagePort = webidl.util.MakeTypeAssertion(MessagePort) + // The method getter steps are to return this’s request’s method. + return this.#state.method + } -webidl.is.BufferSource = function (V) { - return types.isArrayBuffer(V) || ( - ArrayBuffer.isView(V) && - types.isArrayBuffer(V.buffer) - ) -} + // Returns the URL of request as a string. + get url () { + webidl.brandCheck(this, Request) -// https://webidl.spec.whatwg.org/#es-DOMString -webidl.converters.DOMString = function (V, prefix, argument, flags) { - // 1. If V is null and the conversion is to an IDL type - // associated with the [LegacyNullToEmptyString] - // extended attribute, then return the DOMString value - // that represents the empty string. - if (V === null && webidl.util.HasFlag(flags, webidl.attributes.LegacyNullToEmptyString)) { - return '' + // The url getter steps are to return this’s request’s URL, serialized. + return URLSerializer(this.#state.url) } - // 2. Let x be ? ToString(V). - if (typeof V === 'symbol') { - throw webidl.errors.exception({ - header: prefix, - message: `${argument} is a symbol, which cannot be converted to a DOMString.` - }) + // Returns a Headers object consisting of the headers associated with request. + // Note that headers added in the network layer by the user agent will not + // be accounted for in this object, e.g., the "Host" header. + get headers () { + webidl.brandCheck(this, Request) + + // The headers getter steps are to return this’s headers. + return this.#headers } - // 3. Return the IDL DOMString value that represents the - // same sequence of code units as the one the - // ECMAScript String value x represents. - return String(V) -} + // Returns the kind of resource requested by request, e.g., "document" + // or "script". + get destination () { + webidl.brandCheck(this, Request) -// https://webidl.spec.whatwg.org/#es-ByteString -webidl.converters.ByteString = function (V, prefix, argument) { - // 1. Let x be ? ToString(V). - if (typeof V === 'symbol') { - throw webidl.errors.exception({ - header: prefix, - message: `${argument} is a symbol, which cannot be converted to a ByteString.` - }) + // The destination getter are to return this’s request’s destination. + return this.#state.destination } - const x = String(V) + // Returns the referrer of request. Its value can be a same-origin URL if + // explicitly set in init, the empty string to indicate no referrer, and + // "about:client" when defaulting to the global’s default. This is used + // during fetching to determine the value of the `Referer` header of the + // request being made. + get referrer () { + webidl.brandCheck(this, Request) - // 2. If the value of any element of x is greater than - // 255, then throw a TypeError. - for (let index = 0; index < x.length; index++) { - if (x.charCodeAt(index) > 255) { - throw new TypeError( - 'Cannot convert argument to a ByteString because the character at ' + - `index ${index} has a value of ${x.charCodeAt(index)} which is greater than 255.` - ) + // 1. If this’s request’s referrer is "no-referrer", then return the + // empty string. + if (this.#state.referrer === 'no-referrer') { + return '' } - } - // 3. Return an IDL ByteString value whose length is the - // length of x, and where the value of each element is - // the value of the corresponding element of x. - return x -} + // 2. If this’s request’s referrer is "client", then return + // "about:client". + if (this.#state.referrer === 'client') { + return 'about:client' + } -/** - * @param {unknown} value - * @returns {string} - * @see https://webidl.spec.whatwg.org/#es-USVString - */ -webidl.converters.USVString = function (value) { - // TODO: rewrite this so we can control the errors thrown - if (typeof value === 'string') { - return value.toWellFormed() + // Return this’s request’s referrer, serialized. + return this.#state.referrer.toString() } - return `${value}`.toWellFormed() -} -// https://webidl.spec.whatwg.org/#es-boolean -webidl.converters.boolean = function (V) { - // 1. Let x be the result of computing ToBoolean(V). - // https://262.ecma-international.org/10.0/index.html#table-10 - const x = Boolean(V) + // Returns the referrer policy associated with request. + // This is used during fetching to compute the value of the request’s + // referrer. + get referrerPolicy () { + webidl.brandCheck(this, Request) - // 2. Return the IDL boolean value that is the one that represents - // the same truth value as the ECMAScript Boolean value x. - return x -} + // The referrerPolicy getter steps are to return this’s request’s referrer policy. + return this.#state.referrerPolicy + } -// https://webidl.spec.whatwg.org/#es-any -webidl.converters.any = function (V) { - return V -} + // Returns the mode associated with request, which is a string indicating + // whether the request will use CORS, or will be restricted to same-origin + // URLs. + get mode () { + webidl.brandCheck(this, Request) -// https://webidl.spec.whatwg.org/#es-long-long -webidl.converters['long long'] = function (V, prefix, argument) { - // 1. Let x be ? ConvertToInt(V, 64, "signed"). - const x = webidl.util.ConvertToInt(V, 64, 'signed', 0, prefix, argument) + // The mode getter steps are to return this’s request’s mode. + return this.#state.mode + } - // 2. Return the IDL long long value that represents - // the same numeric value as x. - return x -} + // Returns the credentials mode associated with request, + // which is a string indicating whether credentials will be sent with the + // request always, never, or only when sent to a same-origin URL. + get credentials () { + webidl.brandCheck(this, Request) -// https://webidl.spec.whatwg.org/#es-unsigned-long-long -webidl.converters['unsigned long long'] = function (V, prefix, argument) { - // 1. Let x be ? ConvertToInt(V, 64, "unsigned"). - const x = webidl.util.ConvertToInt(V, 64, 'unsigned', 0, prefix, argument) + // The credentials getter steps are to return this’s request’s credentials mode. + return this.#state.credentials + } - // 2. Return the IDL unsigned long long value that - // represents the same numeric value as x. - return x -} + // Returns the cache mode associated with request, + // which is a string indicating how the request will + // interact with the browser’s cache when fetching. + get cache () { + webidl.brandCheck(this, Request) -// https://webidl.spec.whatwg.org/#es-unsigned-long -webidl.converters['unsigned long'] = function (V, prefix, argument) { - // 1. Let x be ? ConvertToInt(V, 32, "unsigned"). - const x = webidl.util.ConvertToInt(V, 32, 'unsigned', 0, prefix, argument) + // The cache getter steps are to return this’s request’s cache mode. + return this.#state.cache + } - // 2. Return the IDL unsigned long value that - // represents the same numeric value as x. - return x -} + // Returns the redirect mode associated with request, + // which is a string indicating how redirects for the + // request will be handled during fetching. A request + // will follow redirects by default. + get redirect () { + webidl.brandCheck(this, Request) -// https://webidl.spec.whatwg.org/#es-unsigned-short -webidl.converters['unsigned short'] = function (V, prefix, argument, flags) { - // 1. Let x be ? ConvertToInt(V, 16, "unsigned"). - const x = webidl.util.ConvertToInt(V, 16, 'unsigned', flags, prefix, argument) + // The redirect getter steps are to return this’s request’s redirect mode. + return this.#state.redirect + } - // 2. Return the IDL unsigned short value that represents - // the same numeric value as x. - return x -} + // Returns request’s subresource integrity metadata, which is a + // cryptographic hash of the resource being fetched. Its value + // consists of multiple hashes separated by whitespace. [SRI] + get integrity () { + webidl.brandCheck(this, Request) -// https://webidl.spec.whatwg.org/#idl-ArrayBuffer -webidl.converters.ArrayBuffer = function (V, prefix, argument, flags) { - // 1. If V is not an Object, or V does not have an - // [[ArrayBufferData]] internal slot, then throw a - // TypeError. - // 2. If IsSharedArrayBuffer(V) is true, then throw a - // TypeError. - // see: https://tc39.es/ecma262/#sec-properties-of-the-arraybuffer-instances - if ( - webidl.util.Type(V) !== OBJECT || - !types.isArrayBuffer(V) - ) { - throw webidl.errors.conversionFailed({ - prefix, - argument: `${argument} ("${webidl.util.Stringify(V)}")`, - types: ['ArrayBuffer'] - }) + // The integrity getter steps are to return this’s request’s integrity + // metadata. + return this.#state.integrity } - // 3. If the conversion is not to an IDL type associated - // with the [AllowResizable] extended attribute, and - // IsResizableArrayBuffer(V) is true, then throw a - // TypeError. - if (!webidl.util.HasFlag(flags, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V)) { - throw webidl.errors.exception({ - header: prefix, - message: `${argument} cannot be a resizable ArrayBuffer.` - }) + // Returns a boolean indicating whether or not request can outlive the + // global in which it was created. + get keepalive () { + webidl.brandCheck(this, Request) + + // The keepalive getter steps are to return this’s request’s keepalive. + return this.#state.keepalive } - // 4. Return the IDL ArrayBuffer value that is a - // reference to the same object as V. - return V -} + // Returns a boolean indicating whether or not request is for a reload + // navigation. + get isReloadNavigation () { + webidl.brandCheck(this, Request) -// https://webidl.spec.whatwg.org/#idl-SharedArrayBuffer -webidl.converters.SharedArrayBuffer = function (V, prefix, argument, flags) { - // 1. If V is not an Object, or V does not have an - // [[ArrayBufferData]] internal slot, then throw a - // TypeError. - // 2. If IsSharedArrayBuffer(V) is false, then throw a - // TypeError. - // see: https://tc39.es/ecma262/#sec-properties-of-the-sharedarraybuffer-instances - if ( - webidl.util.Type(V) !== OBJECT || - !types.isSharedArrayBuffer(V) - ) { - throw webidl.errors.conversionFailed({ - prefix, - argument: `${argument} ("${webidl.util.Stringify(V)}")`, - types: ['SharedArrayBuffer'] - }) + // The isReloadNavigation getter steps are to return true if this’s + // request’s reload-navigation flag is set; otherwise false. + return this.#state.reloadNavigation } - // 3. If the conversion is not to an IDL type associated - // with the [AllowResizable] extended attribute, and - // IsResizableArrayBuffer(V) is true, then throw a - // TypeError. - if (!webidl.util.HasFlag(flags, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V)) { - throw webidl.errors.exception({ - header: prefix, - message: `${argument} cannot be a resizable SharedArrayBuffer.` - }) - } + // Returns a boolean indicating whether or not request is for a history + // navigation (a.k.a. back-forward navigation). + get isHistoryNavigation () { + webidl.brandCheck(this, Request) - // 4. Return the IDL SharedArrayBuffer value that is a - // reference to the same object as V. - return V -} + // The isHistoryNavigation getter steps are to return true if this’s request’s + // history-navigation flag is set; otherwise false. + return this.#state.historyNavigation + } -// https://webidl.spec.whatwg.org/#dfn-typed-array-type -webidl.converters.TypedArray = function (V, T, prefix, argument, flags) { - // 1. Let T be the IDL type V is being converted to. + // Returns the signal associated with request, which is an AbortSignal + // object indicating whether or not request has been aborted, and its + // abort event handler. + get signal () { + webidl.brandCheck(this, Request) - // 2. If Type(V) is not Object, or V does not have a - // [[TypedArrayName]] internal slot with a value - // equal to T’s name, then throw a TypeError. - if ( - webidl.util.Type(V) !== OBJECT || - !types.isTypedArray(V) || - V.constructor.name !== T.name - ) { - throw webidl.errors.conversionFailed({ - prefix, - argument: `${argument} ("${webidl.util.Stringify(V)}")`, - types: [T.name] - }) + // The signal getter steps are to return this’s signal. + return this.#signal } - // 3. If the conversion is not to an IDL type associated - // with the [AllowShared] extended attribute, and - // IsSharedArrayBuffer(V.[[ViewedArrayBuffer]]) is - // true, then throw a TypeError. - if (!webidl.util.HasFlag(flags, webidl.attributes.AllowShared) && types.isSharedArrayBuffer(V.buffer)) { - throw webidl.errors.exception({ - header: prefix, - message: `${argument} cannot be a view on a shared array buffer.` - }) - } + get body () { + webidl.brandCheck(this, Request) - // 4. If the conversion is not to an IDL type associated - // with the [AllowResizable] extended attribute, and - // IsResizableArrayBuffer(V.[[ViewedArrayBuffer]]) is - // true, then throw a TypeError. - if (!webidl.util.HasFlag(flags, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V.buffer)) { - throw webidl.errors.exception({ - header: prefix, - message: `${argument} cannot be a view on a resizable array buffer.` - }) + return this.#state.body ? this.#state.body.stream : null } - // 5. Return the IDL value of type T that is a reference - // to the same object as V. - return V -} + get bodyUsed () { + webidl.brandCheck(this, Request) -// https://webidl.spec.whatwg.org/#idl-DataView -webidl.converters.DataView = function (V, prefix, argument, flags) { - // 1. If Type(V) is not Object, or V does not have a - // [[DataView]] internal slot, then throw a TypeError. - if (webidl.util.Type(V) !== OBJECT || !types.isDataView(V)) { - throw webidl.errors.conversionFailed({ - prefix, - argument: `${argument} ("${webidl.util.Stringify(V)}")`, - types: ['DataView'] - }) + return !!this.#state.body && util.isDisturbed(this.#state.body.stream) } - // 2. If the conversion is not to an IDL type associated - // with the [AllowShared] extended attribute, and - // IsSharedArrayBuffer(V.[[ViewedArrayBuffer]]) is true, - // then throw a TypeError. - if (!webidl.util.HasFlag(flags, webidl.attributes.AllowShared) && types.isSharedArrayBuffer(V.buffer)) { - throw webidl.errors.exception({ - header: prefix, - message: `${argument} cannot be a view on a shared array buffer.` - }) - } + get duplex () { + webidl.brandCheck(this, Request) - // 3. If the conversion is not to an IDL type associated - // with the [AllowResizable] extended attribute, and - // IsResizableArrayBuffer(V.[[ViewedArrayBuffer]]) is - // true, then throw a TypeError. - if (!webidl.util.HasFlag(flags, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V.buffer)) { - throw webidl.errors.exception({ - header: prefix, - message: `${argument} cannot be a view on a resizable array buffer.` - }) + return 'half' } - // 4. Return the IDL DataView value that is a reference - // to the same object as V. - return V -} + // Returns a clone of request. + clone () { + webidl.brandCheck(this, Request) -// https://webidl.spec.whatwg.org/#ArrayBufferView -webidl.converters.ArrayBufferView = function (V, prefix, argument, flags) { - if ( - webidl.util.Type(V) !== OBJECT || - !types.isArrayBufferView(V) - ) { - throw webidl.errors.conversionFailed({ - prefix, - argument: `${argument} ("${webidl.util.Stringify(V)}")`, - types: ['ArrayBufferView'] - }) - } + // 1. If this is unusable, then throw a TypeError. + if (bodyUnusable(this.#state)) { + throw new TypeError('unusable') + } - if (!webidl.util.HasFlag(flags, webidl.attributes.AllowShared) && types.isSharedArrayBuffer(V.buffer)) { - throw webidl.errors.exception({ - header: prefix, - message: `${argument} cannot be a view on a shared array buffer.` - }) - } + // 2. Let clonedRequest be the result of cloning this’s request. + const clonedRequest = cloneRequest(this.#state) - if (!webidl.util.HasFlag(flags, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V.buffer)) { - throw webidl.errors.exception({ - header: prefix, - message: `${argument} cannot be a view on a resizable array buffer.` - }) + // 3. Let clonedRequestObject be the result of creating a Request object, + // given clonedRequest, this’s headers’s guard, and this’s relevant Realm. + // 4. Make clonedRequestObject’s signal follow this’s signal. + const ac = new AbortController() + if (this.signal.aborted) { + ac.abort(this.signal.reason) + } else { + let list = dependentControllerMap.get(this.signal) + if (list === undefined) { + list = new Set() + dependentControllerMap.set(this.signal, list) + } + const acRef = new WeakRef(ac) + list.add(acRef) + util.addAbortListener( + ac.signal, + buildAbort(acRef) + ) + } + + // 4. Return clonedRequestObject. + return fromInnerRequest(clonedRequest, this.#dispatcher, ac.signal, getHeadersGuard(this.#headers)) } - return V -} + [nodeUtil.inspect.custom] (depth, options) { + if (options.depth === null) { + options.depth = 2 + } -// https://webidl.spec.whatwg.org/#BufferSource -webidl.converters.BufferSource = function (V, prefix, argument, flags) { - if (types.isArrayBuffer(V)) { - return webidl.converters.ArrayBuffer(V, prefix, argument, flags) - } + options.colors ??= true - if (types.isArrayBufferView(V)) { - flags &= ~webidl.attributes.AllowShared + const properties = { + method: this.method, + url: this.url, + headers: this.headers, + destination: this.destination, + referrer: this.referrer, + referrerPolicy: this.referrerPolicy, + mode: this.mode, + credentials: this.credentials, + cache: this.cache, + redirect: this.redirect, + integrity: this.integrity, + keepalive: this.keepalive, + isReloadNavigation: this.isReloadNavigation, + isHistoryNavigation: this.isHistoryNavigation, + signal: this.signal + } - return webidl.converters.ArrayBufferView(V, prefix, argument, flags) + return `Request ${nodeUtil.formatWithOptions(options, properties)}` } - // Make this explicit for easier debugging - if (types.isSharedArrayBuffer(V)) { - throw webidl.errors.exception({ - header: prefix, - message: `${argument} cannot be a SharedArrayBuffer.` - }) + /** + * @param {Request} request + * @param {AbortSignal} newSignal + */ + static setRequestSignal (request, newSignal) { + request.#signal = newSignal + return request } - throw webidl.errors.conversionFailed({ - prefix, - argument: `${argument} ("${webidl.util.Stringify(V)}")`, - types: ['ArrayBuffer', 'ArrayBufferView'] - }) -} + /** + * @param {Request} request + */ + static getRequestDispatcher (request) { + return request.#dispatcher + } -// https://webidl.spec.whatwg.org/#AllowSharedBufferSource -webidl.converters.AllowSharedBufferSource = function (V, prefix, argument, flags) { - if (types.isArrayBuffer(V)) { - return webidl.converters.ArrayBuffer(V, prefix, argument, flags) + /** + * @param {Request} request + * @param {import('../../dispatcher/dispatcher')} newDispatcher + */ + static setRequestDispatcher (request, newDispatcher) { + request.#dispatcher = newDispatcher } - if (types.isSharedArrayBuffer(V)) { - return webidl.converters.SharedArrayBuffer(V, prefix, argument, flags) + /** + * @param {Request} request + * @param {Headers} newHeaders + */ + static setRequestHeaders (request, newHeaders) { + request.#headers = newHeaders } - if (types.isArrayBufferView(V)) { - flags |= webidl.attributes.AllowShared - return webidl.converters.ArrayBufferView(V, prefix, argument, flags) + /** + * @param {Request} request + */ + static getRequestState (request) { + return request.#state } - throw webidl.errors.conversionFailed({ - prefix, - argument: `${argument} ("${webidl.util.Stringify(V)}")`, - types: ['ArrayBuffer', 'SharedArrayBuffer', 'ArrayBufferView'] - }) + /** + * @param {Request} request + * @param {any} newState + */ + static setRequestState (request, newState) { + request.#state = newState + } } -webidl.converters['sequence'] = webidl.sequenceConverter( - webidl.converters.ByteString -) - -webidl.converters['sequence>'] = webidl.sequenceConverter( - webidl.converters['sequence'] -) +const { setRequestSignal, getRequestDispatcher, setRequestDispatcher, setRequestHeaders, getRequestState, setRequestState } = Request +Reflect.deleteProperty(Request, 'setRequestSignal') +Reflect.deleteProperty(Request, 'getRequestDispatcher') +Reflect.deleteProperty(Request, 'setRequestDispatcher') +Reflect.deleteProperty(Request, 'setRequestHeaders') +Reflect.deleteProperty(Request, 'getRequestState') +Reflect.deleteProperty(Request, 'setRequestState') -webidl.converters['record'] = webidl.recordConverter( - webidl.converters.ByteString, - webidl.converters.ByteString -) +mixinBody(Request, getRequestState) -webidl.converters.Blob = webidl.interfaceConverter(webidl.is.Blob, 'Blob') +// https://fetch.spec.whatwg.org/#requests +function makeRequest (init) { + return { + method: init.method ?? 'GET', + localURLsOnly: init.localURLsOnly ?? false, + unsafeRequest: init.unsafeRequest ?? false, + body: init.body ?? null, + client: init.client ?? null, + reservedClient: init.reservedClient ?? null, + replacesClientId: init.replacesClientId ?? '', + window: init.window ?? 'client', + keepalive: init.keepalive ?? false, + serviceWorkers: init.serviceWorkers ?? 'all', + initiator: init.initiator ?? '', + destination: init.destination ?? '', + priority: init.priority ?? null, + origin: init.origin ?? 'client', + policyContainer: init.policyContainer ?? 'client', + referrer: init.referrer ?? 'client', + referrerPolicy: init.referrerPolicy ?? '', + mode: init.mode ?? 'no-cors', + useCORSPreflightFlag: init.useCORSPreflightFlag ?? false, + credentials: init.credentials ?? 'same-origin', + useCredentials: init.useCredentials ?? false, + cache: init.cache ?? 'default', + redirect: init.redirect ?? 'follow', + integrity: init.integrity ?? '', + cryptoGraphicsNonceMetadata: init.cryptoGraphicsNonceMetadata ?? '', + parserMetadata: init.parserMetadata ?? '', + reloadNavigation: init.reloadNavigation ?? false, + historyNavigation: init.historyNavigation ?? false, + userActivation: init.userActivation ?? false, + taintedOrigin: init.taintedOrigin ?? false, + redirectCount: init.redirectCount ?? 0, + responseTainting: init.responseTainting ?? 'basic', + preventNoCacheCacheControlHeaderModification: init.preventNoCacheCacheControlHeaderModification ?? false, + done: init.done ?? false, + timingAllowFailed: init.timingAllowFailed ?? false, + useURLCredentials: init.useURLCredentials ?? undefined, + traversableForUserPrompts: init.traversableForUserPrompts ?? 'client', + urlList: init.urlList, + url: init.urlList[0], + headersList: init.headersList + ? new HeadersList(init.headersList) + : new HeadersList() + } +} -webidl.converters.AbortSignal = webidl.interfaceConverter( - webidl.is.AbortSignal, - 'AbortSignal' -) +// https://fetch.spec.whatwg.org/#concept-request-clone +function cloneRequest (request) { + // To clone a request request, run these steps: -/** - * [LegacyTreatNonObjectAsNull] - * callback EventHandlerNonNull = any (Event event); - * typedef EventHandlerNonNull? EventHandler; - * @param {*} V - */ -webidl.converters.EventHandlerNonNull = function (V) { - if (webidl.util.Type(V) !== OBJECT) { - return null - } + // 1. Let newRequest be a copy of request, except for its body. + const newRequest = makeRequest({ ...request, body: null }) - // [I]f the value is not an object, it will be converted to null, and if the value is not callable, - // it will be converted to a callback function value that does nothing when called. - if (typeof V === 'function') { - return V + // 2. If request’s body is non-null, set newRequest’s body to the + // result of cloning request’s body. + if (request.body != null) { + newRequest.body = cloneBody(request.body) } - return () => {} -} - -webidl.attributes = { - Clamp: 1 << 0, - EnforceRange: 1 << 1, - AllowShared: 1 << 2, - AllowResizable: 1 << 3, - LegacyNullToEmptyString: 1 << 4 + // 3. Return newRequest. + return newRequest } -module.exports = { - webidl +/** + * @see https://fetch.spec.whatwg.org/#request-create + * @param {any} innerRequest + * @param {import('../../dispatcher/agent')} dispatcher + * @param {AbortSignal} signal + * @param {'request' | 'immutable' | 'request-no-cors' | 'response' | 'none'} guard + * @returns {Request} + */ +function fromInnerRequest (innerRequest, dispatcher, signal, guard) { + const request = new Request(kConstruct) + setRequestState(request, innerRequest) + setRequestDispatcher(request, dispatcher) + setRequestSignal(request, signal) + const headers = new Headers(kConstruct) + setRequestHeaders(request, headers) + setHeadersList(headers, innerRequest.headersList) + setHeadersGuard(headers, guard) + return request } +Object.defineProperties(Request.prototype, { + method: kEnumerableProperty, + url: kEnumerableProperty, + headers: kEnumerableProperty, + redirect: kEnumerableProperty, + clone: kEnumerableProperty, + signal: kEnumerableProperty, + duplex: kEnumerableProperty, + destination: kEnumerableProperty, + body: kEnumerableProperty, + bodyUsed: kEnumerableProperty, + isHistoryNavigation: kEnumerableProperty, + isReloadNavigation: kEnumerableProperty, + keepalive: kEnumerableProperty, + integrity: kEnumerableProperty, + cache: kEnumerableProperty, + credentials: kEnumerableProperty, + attribute: kEnumerableProperty, + referrerPolicy: kEnumerableProperty, + referrer: kEnumerableProperty, + mode: kEnumerableProperty, + [Symbol.toStringTag]: { + value: 'Request', + configurable: true + } +}) -/***/ }), - -/***/ 9136: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -"use strict"; - - -const { uid, states, sentCloseFrameState, emptyBuffer, opcodes } = __nccwpck_require__(163) -const { parseExtensions, isClosed, isClosing, isEstablished, isConnecting, validateCloseCodeAndReason } = __nccwpck_require__(7484) -const { makeRequest } = __nccwpck_require__(8140) -const { fetching } = __nccwpck_require__(6377) -const { Headers, getHeadersList } = __nccwpck_require__(8447) -const { getDecodeSplit } = __nccwpck_require__(8913) -const { WebsocketFrameSend } = __nccwpck_require__(2647) -const assert = __nccwpck_require__(4589) -const { runtimeFeatures } = __nccwpck_require__(1422) - -const crypto = runtimeFeatures.has('crypto') - ? __nccwpck_require__(7598) - : null - -let warningEmitted = false +webidl.is.Request = webidl.util.MakeTypeAssertion(Request) /** - * @see https://websockets.spec.whatwg.org/#concept-websocket-establish - * @param {URL} url - * @param {string|string[]} protocols - * @param {import('./websocket').Handler} handler - * @param {Partial} options + * @param {*} V + * @returns {import('../../../types/fetch').Request|string} + * + * @see https://fetch.spec.whatwg.org/#requestinfo */ -function establishWebSocketConnection (url, protocols, client, handler, options) { - // 1. Let requestURL be a copy of url, with its scheme set to "http", if url’s - // scheme is "ws", and to "https" otherwise. - const requestURL = url - - requestURL.protocol = url.protocol === 'ws:' ? 'http:' : 'https:' - - // 2. Let request be a new request, whose URL is requestURL, client is client, - // service-workers mode is "none", referrer is "no-referrer", mode is - // "websocket", credentials mode is "include", cache mode is "no-store" , - // redirect mode is "error", and use-URL-credentials flag is set. - const request = makeRequest({ - urlList: [requestURL], - client, - serviceWorkers: 'none', - referrer: 'no-referrer', - mode: 'websocket', - credentials: 'include', - cache: 'no-store', - redirect: 'error', - useURLCredentials: true - }) - - // Note: undici extension, allow setting custom headers. - if (options.headers) { - const headersList = getHeadersList(new Headers(options.headers)) +webidl.converters.RequestInfo = function (V) { + if (typeof V === 'string') { + return webidl.converters.USVString(V) + } - request.headersList = headersList + if (webidl.is.Request(V)) { + return V } - // 3. Append (`Upgrade`, `websocket`) to request’s header list. - // 4. Append (`Connection`, `Upgrade`) to request’s header list. - // Note: both of these are handled by undici currently. - // https://github.com/nodejs/undici/blob/68c269c4144c446f3f1220951338daef4a6b5ec4/lib/client.js#L1397 + return webidl.converters.USVString(V) +} - // 5. Let keyValue be a nonce consisting of a randomly selected - // 16-byte value that has been forgiving-base64-encoded and - // isomorphic encoded. - const keyValue = crypto.randomBytes(16).toString('base64') +/** + * @param {*} V + * @returns {import('../../../types/fetch').RequestInit} + * @see https://fetch.spec.whatwg.org/#requestinit + */ +webidl.converters.RequestInit = webidl.dictionaryConverter([ + { + key: 'method', + converter: webidl.converters.ByteString + }, + { + key: 'headers', + converter: webidl.converters.HeadersInit + }, + { + key: 'body', + converter: webidl.nullableConverter( + webidl.converters.BodyInit + ) + }, + { + key: 'referrer', + converter: webidl.converters.USVString + }, + { + key: 'referrerPolicy', + converter: webidl.converters.DOMString, + // https://w3c.github.io/webappsec-referrer-policy/#referrer-policy + allowedValues: referrerPolicy + }, + { + key: 'mode', + converter: webidl.converters.DOMString, + // https://fetch.spec.whatwg.org/#concept-request-mode + allowedValues: requestMode + }, + { + key: 'credentials', + converter: webidl.converters.DOMString, + // https://fetch.spec.whatwg.org/#requestcredentials + allowedValues: requestCredentials + }, + { + key: 'cache', + converter: webidl.converters.DOMString, + // https://fetch.spec.whatwg.org/#requestcache + allowedValues: requestCache + }, + { + key: 'redirect', + converter: webidl.converters.DOMString, + // https://fetch.spec.whatwg.org/#requestredirect + allowedValues: requestRedirect + }, + { + key: 'integrity', + converter: webidl.converters.DOMString + }, + { + key: 'keepalive', + converter: webidl.converters.boolean + }, + { + key: 'signal', + converter: webidl.nullableConverter( + (signal) => webidl.converters.AbortSignal( + signal, + 'RequestInit', + 'signal' + ) + ) + }, + { + key: 'window', + converter: webidl.converters.any + }, + { + key: 'duplex', + converter: webidl.converters.DOMString, + allowedValues: requestDuplex + }, + { + key: 'dispatcher', // undici specific option + converter: webidl.converters.any + }, + { + key: 'priority', + converter: webidl.converters.DOMString, + allowedValues: ['high', 'low', 'auto'], + defaultValue: () => 'auto' + } +]) - // 6. Append (`Sec-WebSocket-Key`, keyValue) to request’s - // header list. - request.headersList.append('sec-websocket-key', keyValue, true) +module.exports = { + Request, + makeRequest, + fromInnerRequest, + cloneRequest, + getRequestDispatcher, + getRequestState +} - // 7. Append (`Sec-WebSocket-Version`, `13`) to request’s - // header list. - request.headersList.append('sec-websocket-version', '13', true) - // 8. For each protocol in protocols, combine - // (`Sec-WebSocket-Protocol`, protocol) in request’s header - // list. - for (const protocol of protocols) { - request.headersList.append('sec-websocket-protocol', protocol, true) - } +/***/ }), - // 9. Let permessageDeflate be a user-agent defined - // "permessage-deflate" extension header value. - // https://github.com/mozilla/gecko-dev/blob/ce78234f5e653a5d3916813ff990f053510227bc/netwerk/protocol/websocket/WebSocketChannel.cpp#L2673 - const permessageDeflate = 'permessage-deflate; client_max_window_bits' +/***/ 4545: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - // 10. Append (`Sec-WebSocket-Extensions`, permessageDeflate) to - // request’s header list. - request.headersList.append('sec-websocket-extensions', permessageDeflate, true) - // 11. Fetch request with useParallelQueue set to true, and - // processResponse given response being these steps: - const controller = fetching({ - request, - useParallelQueue: true, - dispatcher: options.dispatcher, - processResponse (response) { - // 1. If response is a network error or its status is not 101, - // fail the WebSocket connection. - // if (response.type === 'error' || ((response.socket?.session != null && response.status !== 200) && response.status !== 101)) { - if (response.type === 'error' || response.status !== 101) { - // The presence of a session property on the socket indicates HTTP2 - // HTTP1 - if (response.socket?.session == null) { - failWebsocketConnection(handler, 1002, 'Received network error or non-101 status code.', response.error) - return - } - // HTTP2 - if (response.status !== 200) { - failWebsocketConnection(handler, 1002, 'Received network error or non-200 status code.', response.error) - return - } - } +const { Headers, HeadersList, fill, getHeadersGuard, setHeadersGuard, setHeadersList } = __nccwpck_require__(7754) +const { extractBody, cloneBody, mixinBody, streamRegistry, bodyUnusable } = __nccwpck_require__(9742) +const util = __nccwpck_require__(2550) +const nodeUtil = __nccwpck_require__(7975) +const { kEnumerableProperty } = util +const { + isValidReasonPhrase, + isCancelled, + isAborted, + isErrorLike, + environmentSettingsObject: relevantRealm +} = __nccwpck_require__(3106) +const { + redirectStatusSet, + nullBodyStatus +} = __nccwpck_require__(8973) +const { webidl } = __nccwpck_require__(909) +const { URLSerializer } = __nccwpck_require__(1410) +const { kConstruct } = __nccwpck_require__(8261) +const assert = __nccwpck_require__(4589) +const { isomorphicEncode, serializeJavascriptValueToJSONString } = __nccwpck_require__(5074) - if (warningEmitted === false && response.socket?.session != null) { - process.emitWarning('WebSocket over HTTP2 is experimental, and subject to change.', 'ExperimentalWarning') - warningEmitted = true - } +const textEncoder = new TextEncoder('utf-8') - // 2. If protocols is not the empty list and extracting header - // list values given `Sec-WebSocket-Protocol` and response’s - // header list results in null, failure, or the empty byte - // sequence, then fail the WebSocket connection. - if (protocols.length !== 0 && !response.headersList.get('Sec-WebSocket-Protocol')) { - failWebsocketConnection(handler, 1002, 'Server did not respond with sent protocols.') - return - } +// https://fetch.spec.whatwg.org/#response-class +class Response { + /** @type {Headers} */ + #headers - // 3. Follow the requirements stated step 2 to step 6, inclusive, - // of the last set of steps in section 4.1 of The WebSocket - // Protocol to validate response. This either results in fail - // the WebSocket connection or the WebSocket connection is - // established. + #state - // 2. If the response lacks an |Upgrade| header field or the |Upgrade| - // header field contains a value that is not an ASCII case- - // insensitive match for the value "websocket", the client MUST - // _Fail the WebSocket Connection_. - // For H2, no upgrade header is expected. - if (response.socket.session == null && response.headersList.get('Upgrade')?.toLowerCase() !== 'websocket') { - failWebsocketConnection(handler, 1002, 'Server did not set Upgrade header to "websocket".') - return - } + // Creates network error Response. + static error () { + // The static error() method steps are to return the result of creating a + // Response object, given a new network error, "immutable", and this’s + // relevant Realm. + const responseObject = fromInnerResponse(makeNetworkError(), 'immutable') - // 3. If the response lacks a |Connection| header field or the - // |Connection| header field doesn't contain a token that is an - // ASCII case-insensitive match for the value "Upgrade", the client - // MUST _Fail the WebSocket Connection_. - // For H2, no connection header is expected. - if (response.socket.session == null && response.headersList.get('Connection')?.toLowerCase() !== 'upgrade') { - failWebsocketConnection(handler, 1002, 'Server did not set Connection header to "upgrade".') - return - } + return responseObject + } - // 4. If the response lacks a |Sec-WebSocket-Accept| header field or - // the |Sec-WebSocket-Accept| contains a value other than the - // base64-encoded SHA-1 of the concatenation of the |Sec-WebSocket- - // Key| (as a string, not base64-decoded) with the string "258EAFA5- - // E914-47DA-95CA-C5AB0DC85B11" but ignoring any leading and - // trailing whitespace, the client MUST _Fail the WebSocket - // Connection_. - const secWSAccept = response.headersList.get('Sec-WebSocket-Accept') - const digest = crypto.hash('sha1', keyValue + uid, 'base64') - if (secWSAccept !== digest) { - failWebsocketConnection(handler, 1002, 'Incorrect hash received in Sec-WebSocket-Accept header.') - return - } + // https://fetch.spec.whatwg.org/#dom-response-json + static json (data, init = undefined) { + webidl.argumentLengthCheck(arguments, 1, 'Response.json') - // 5. If the response includes a |Sec-WebSocket-Extensions| header - // field and this header field indicates the use of an extension - // that was not present in the client's handshake (the server has - // indicated an extension not requested by the client), the client - // MUST _Fail the WebSocket Connection_. (The parsing of this - // header field to determine which extensions are requested is - // discussed in Section 9.1.) - const secExtension = response.headersList.get('Sec-WebSocket-Extensions') - let extensions + if (init !== null) { + init = webidl.converters.ResponseInit(init) + } - if (secExtension !== null) { - extensions = parseExtensions(secExtension) + // 1. Let bytes the result of running serialize a JavaScript value to JSON bytes on data. + const bytes = textEncoder.encode( + serializeJavascriptValueToJSONString(data) + ) - if (!extensions.has('permessage-deflate')) { - failWebsocketConnection(handler, 1002, 'Sec-WebSocket-Extensions header does not match.') - return - } - } + // 2. Let body be the result of extracting bytes. + const body = extractBody(bytes) - // 6. If the response includes a |Sec-WebSocket-Protocol| header field - // and this header field indicates the use of a subprotocol that was - // not present in the client's handshake (the server has indicated a - // subprotocol not requested by the client), the client MUST _Fail - // the WebSocket Connection_. - const secProtocol = response.headersList.get('Sec-WebSocket-Protocol') + // 3. Let responseObject be the result of creating a Response object, given a new response, + // "response", and this’s relevant Realm. + const responseObject = fromInnerResponse(makeResponse({}), 'response') - if (secProtocol !== null) { - const requestProtocols = getDecodeSplit('sec-websocket-protocol', request.headersList) + // 4. Perform initialize a response given responseObject, init, and (body, "application/json"). + initializeResponse(responseObject, init, { body: body[0], type: 'application/json' }) - // The client can request that the server use a specific subprotocol by - // including the |Sec-WebSocket-Protocol| field in its handshake. If it - // is specified, the server needs to include the same field and one of - // the selected subprotocol values in its response for the connection to - // be established. - if (!requestProtocols.includes(secProtocol)) { - failWebsocketConnection(handler, 1002, 'Protocol was not set in the opening handshake.') - return - } - } + // 5. Return responseObject. + return responseObject + } - response.socket.on('data', handler.onSocketData) - response.socket.on('close', handler.onSocketClose) - response.socket.on('error', handler.onSocketError) + // Creates a redirect Response that redirects to url with status status. + static redirect (url, status = 302) { + webidl.argumentLengthCheck(arguments, 1, 'Response.redirect') - handler.wasEverConnected = true - handler.onConnectionEstablished(response, extensions) + url = webidl.converters.USVString(url) + status = webidl.converters['unsigned short'](status) + + // 1. Let parsedURL be the result of parsing url with current settings + // object’s API base URL. + // 2. If parsedURL is failure, then throw a TypeError. + // TODO: base-URL? + let parsedURL + try { + parsedURL = new URL(url, relevantRealm.settingsObject.baseUrl) + } catch (err) { + throw new TypeError(`Failed to parse URL from ${url}`, { cause: err }) } - }) - return controller -} + // 3. If status is not a redirect status, then throw a RangeError. + if (!redirectStatusSet.has(status)) { + throw new RangeError(`Invalid status code ${status}`) + } -/** - * @see https://whatpr.org/websockets/48.html#close-the-websocket - * @param {import('./websocket').Handler} object - * @param {number} [code=null] - * @param {string} [reason=''] - */ -function closeWebSocketConnection (object, code, reason, validate = false) { - // 1. If code was not supplied, let code be null. - code ??= null + // 4. Let responseObject be the result of creating a Response object, + // given a new response, "immutable", and this’s relevant Realm. + const responseObject = fromInnerResponse(makeResponse({}), 'immutable') - // 2. If reason was not supplied, let reason be the empty string. - reason ??= '' + // 5. Set responseObject’s response’s status to status. + responseObject.#state.status = status - // 3. Validate close code and reason with code and reason. - if (validate) validateCloseCodeAndReason(code, reason) + // 6. Let value be parsedURL, serialized and isomorphic encoded. + const value = isomorphicEncode(URLSerializer(parsedURL)) - // 4. Run the first matching steps from the following list: - // - If object’s ready state is CLOSING (2) or CLOSED (3) - // - If the WebSocket connection is not yet established [WSP] - // - If the WebSocket closing handshake has not yet been started [WSP] - // - Otherwise - if (isClosed(object.readyState) || isClosing(object.readyState)) { - // Do nothing. - } else if (!isEstablished(object.readyState)) { - // Fail the WebSocket connection and set object’s ready state to CLOSING (2). [WSP] - failWebsocketConnection(object) - object.readyState = states.CLOSING - } else if (!object.closeState.has(sentCloseFrameState.SENT) && !object.closeState.has(sentCloseFrameState.RECEIVED)) { - // Upon either sending or receiving a Close control frame, it is said - // that _The WebSocket Closing Handshake is Started_ and that the - // WebSocket connection is in the CLOSING state. + // 7. Append `Location`/value to responseObject’s response’s header list. + responseObject.#state.headersList.append('location', value, true) - const frame = new WebsocketFrameSend() + // 8. Return responseObject. + return responseObject + } - // If neither code nor reason is present, the WebSocket Close - // message must not have a body. + // https://fetch.spec.whatwg.org/#dom-response + constructor (body = null, init = undefined) { + webidl.util.markAsUncloneable(this) - // If code is present, then the status code to use in the - // WebSocket Close message must be the integer given by code. - // If code is null and reason is the empty string, the WebSocket Close frame must not have a body. - // If reason is non-empty but code is null, then set code to 1000 ("Normal Closure"). - if (reason.length !== 0 && code === null) { - code = 1000 + if (body === kConstruct) { + return } - // If code is set, then the status code to use in the WebSocket Close frame must be the integer given by code. - assert(code === null || Number.isInteger(code)) + if (body !== null) { + body = webidl.converters.BodyInit(body, 'Response', 'body') + } - if (code === null && reason.length === 0) { - frame.frameData = emptyBuffer - } else if (code !== null && reason === null) { - frame.frameData = Buffer.allocUnsafe(2) - frame.frameData.writeUInt16BE(code, 0) - } else if (code !== null && reason !== null) { - // If reason is also present, then reasonBytes must be - // provided in the Close message after the status code. - frame.frameData = Buffer.allocUnsafe(2 + Buffer.byteLength(reason)) - frame.frameData.writeUInt16BE(code, 0) - // the body MAY contain UTF-8-encoded data with value /reason/ - frame.frameData.write(reason, 2, 'utf-8') - } else { - frame.frameData = emptyBuffer + init = webidl.converters.ResponseInit(init) + + // 1. Set this’s response to a new response. + this.#state = makeResponse({}) + + // 2. Set this’s headers to a new Headers object with this’s relevant + // Realm, whose header list is this’s response’s header list and guard + // is "response". + this.#headers = new Headers(kConstruct) + setHeadersGuard(this.#headers, 'response') + setHeadersList(this.#headers, this.#state.headersList) + + // 3. Let bodyWithType be null. + let bodyWithType = null + + // 4. If body is non-null, then set bodyWithType to the result of extracting body. + if (body != null) { + const [extractedBody, type] = extractBody(body) + bodyWithType = { body: extractedBody, type } } - object.socket.write(frame.createFrame(opcodes.CLOSE)) + // 5. Perform initialize a response given this, init, and bodyWithType. + initializeResponse(this, init, bodyWithType) + } - object.closeState.add(sentCloseFrameState.SENT) + // Returns response’s type, e.g., "cors". + get type () { + webidl.brandCheck(this, Response) - // Upon either sending or receiving a Close control frame, it is said - // that _The WebSocket Closing Handshake is Started_ and that the - // WebSocket connection is in the CLOSING state. - object.readyState = states.CLOSING - } else { - // Set object’s ready state to CLOSING (2). - object.readyState = states.CLOSING + // The type getter steps are to return this’s response’s type. + return this.#state.type } -} -/** - * @param {import('./websocket').Handler} handler - * @param {number} code - * @param {string|undefined} reason - * @param {unknown} cause - * @returns {void} - */ -function failWebsocketConnection (handler, code, reason, cause) { - // If _The WebSocket Connection is Established_ prior to the point where - // the endpoint is required to _Fail the WebSocket Connection_, the - // endpoint SHOULD send a Close frame with an appropriate status code - // (Section 7.4) before proceeding to _Close the WebSocket Connection_. - if (isEstablished(handler.readyState)) { - closeWebSocketConnection(handler, code, reason, false) + // Returns response’s URL, if it has one; otherwise the empty string. + get url () { + webidl.brandCheck(this, Response) + + const urlList = this.#state.urlList + + // The url getter steps are to return the empty string if this’s + // response’s URL is null; otherwise this’s response’s URL, + // serialized with exclude fragment set to true. + const url = urlList[urlList.length - 1] ?? null + + if (url === null) { + return '' + } + + return URLSerializer(url, true) } - handler.controller.abort() + // Returns whether response was obtained through a redirect. + get redirected () { + webidl.brandCheck(this, Response) - if (isConnecting(handler.readyState)) { - // If the connection was not established, we must still emit an 'error' and 'close' events - handler.onSocketClose() - } else if (handler.socket?.destroyed === false) { - handler.socket.destroy() + // The redirected getter steps are to return true if this’s response’s URL + // list has more than one item; otherwise false. + return this.#state.urlList.length > 1 } -} -module.exports = { - establishWebSocketConnection, - failWebsocketConnection, - closeWebSocketConnection -} + // Returns response’s status. + get status () { + webidl.brandCheck(this, Response) + // The status getter steps are to return this’s response’s status. + return this.#state.status + } -/***/ }), + // Returns whether response’s status is an ok status. + get ok () { + webidl.brandCheck(this, Response) -/***/ 163: -/***/ ((module) => { + // The ok getter steps are to return true if this’s response’s status is an + // ok status; otherwise false. + return this.#state.status >= 200 && this.#state.status <= 299 + } -"use strict"; + // Returns response’s status message. + get statusText () { + webidl.brandCheck(this, Response) + // The statusText getter steps are to return this’s response’s status + // message. + return this.#state.statusText + } -/** - * This is a Globally Unique Identifier unique used to validate that the - * endpoint accepts websocket connections. - * @see https://www.rfc-editor.org/rfc/rfc6455.html#section-1.3 - * @type {'258EAFA5-E914-47DA-95CA-C5AB0DC85B11'} - */ -const uid = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11' + // Returns response’s headers as Headers. + get headers () { + webidl.brandCheck(this, Response) -/** - * @type {PropertyDescriptor} - */ -const staticPropertyDescriptors = { - enumerable: true, - writable: false, - configurable: false -} + // The headers getter steps are to return this’s headers. + return this.#headers + } -/** - * The states of the WebSocket connection. - * - * @readonly - * @enum - * @property {0} CONNECTING - * @property {1} OPEN - * @property {2} CLOSING - * @property {3} CLOSED - */ -const states = { - CONNECTING: 0, - OPEN: 1, - CLOSING: 2, - CLOSED: 3 -} + get body () { + webidl.brandCheck(this, Response) -/** - * @readonly - * @enum - * @property {0} NOT_SENT - * @property {1} PROCESSING - * @property {2} SENT - */ -const sentCloseFrameState = { - SENT: 1, - RECEIVED: 2 -} + return this.#state.body ? this.#state.body.stream : null + } -/** - * The WebSocket opcodes. - * - * @readonly - * @enum - * @property {0x0} CONTINUATION - * @property {0x1} TEXT - * @property {0x2} BINARY - * @property {0x8} CLOSE - * @property {0x9} PING - * @property {0xA} PONG - * @see https://datatracker.ietf.org/doc/html/rfc6455#section-5.2 - */ -const opcodes = { - CONTINUATION: 0x0, - TEXT: 0x1, - BINARY: 0x2, - CLOSE: 0x8, - PING: 0x9, - PONG: 0xA -} + get bodyUsed () { + webidl.brandCheck(this, Response) -/** - * The maximum value for an unsigned 16-bit integer. - * - * @type {65535} 2 ** 16 - 1 - */ -const maxUnsigned16Bit = 65535 + return !!this.#state.body && util.isDisturbed(this.#state.body.stream) + } -/** - * The states of the parser. - * - * @readonly - * @enum - * @property {0} INFO - * @property {2} PAYLOADLENGTH_16 - * @property {3} PAYLOADLENGTH_64 - * @property {4} READ_DATA - */ -const parserStates = { - INFO: 0, - PAYLOADLENGTH_16: 2, - PAYLOADLENGTH_64: 3, - READ_DATA: 4 -} + // Returns a clone of response. + clone () { + webidl.brandCheck(this, Response) -/** - * An empty buffer. - * - * @type {Buffer} - */ -const emptyBuffer = Buffer.allocUnsafe(0) + // 1. If this is unusable, then throw a TypeError. + if (bodyUnusable(this.#state)) { + throw webidl.errors.exception({ + header: 'Response.clone', + message: 'Body has already been consumed.' + }) + } -/** - * @readonly - * @property {1} text - * @property {2} typedArray - * @property {3} arrayBuffer - * @property {4} blob - */ -const sendHints = { - text: 1, - typedArray: 2, - arrayBuffer: 3, - blob: 4 -} + // 2. Let clonedResponse be the result of cloning this’s response. + const clonedResponse = cloneResponse(this.#state) -module.exports = { - uid, - sentCloseFrameState, - staticPropertyDescriptors, - states, - opcodes, - maxUnsigned16Bit, - parserStates, - emptyBuffer, - sendHints -} + // Note: To re-register because of a new stream. + if (this.#state.body?.stream) { + streamRegistry.register(this, new WeakRef(this.#state.body.stream)) + } + // 3. Return the result of creating a Response object, given + // clonedResponse, this’s headers’s guard, and this’s relevant Realm. + return fromInnerResponse(clonedResponse, getHeadersGuard(this.#headers)) + } -/***/ }), + [nodeUtil.inspect.custom] (depth, options) { + if (options.depth === null) { + options.depth = 2 + } -/***/ 649: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + options.colors ??= true -"use strict"; + const properties = { + status: this.status, + statusText: this.statusText, + headers: this.headers, + body: this.body, + bodyUsed: this.bodyUsed, + ok: this.ok, + redirected: this.redirected, + type: this.type, + url: this.url + } + return `Response ${nodeUtil.formatWithOptions(options, properties)}` + } -const { webidl } = __nccwpck_require__(2318) -const { kEnumerableProperty } = __nccwpck_require__(983) -const { kConstruct } = __nccwpck_require__(9562) + /** + * @param {Response} response + */ + static getResponseHeaders (response) { + return response.#headers + } -/** - * @see https://html.spec.whatwg.org/multipage/comms.html#messageevent - */ -class MessageEvent extends Event { - #eventInit + /** + * @param {Response} response + * @param {Headers} newHeaders + */ + static setResponseHeaders (response, newHeaders) { + response.#headers = newHeaders + } - constructor (type, eventInitDict = {}) { - if (type === kConstruct) { - super(arguments[1], arguments[2]) - webidl.util.markAsUncloneable(this) - return - } + /** + * @param {Response} response + */ + static getResponseState (response) { + return response.#state + } - const prefix = 'MessageEvent constructor' - webidl.argumentLengthCheck(arguments, 1, prefix) + /** + * @param {Response} response + * @param {any} newState + */ + static setResponseState (response, newState) { + response.#state = newState + } +} - type = webidl.converters.DOMString(type, prefix, 'type') - eventInitDict = webidl.converters.MessageEventInit(eventInitDict, prefix, 'eventInitDict') +const { getResponseHeaders, setResponseHeaders, getResponseState, setResponseState } = Response +Reflect.deleteProperty(Response, 'getResponseHeaders') +Reflect.deleteProperty(Response, 'setResponseHeaders') +Reflect.deleteProperty(Response, 'getResponseState') +Reflect.deleteProperty(Response, 'setResponseState') - super(type, eventInitDict) +mixinBody(Response, getResponseState) - this.#eventInit = eventInitDict - webidl.util.markAsUncloneable(this) +Object.defineProperties(Response.prototype, { + type: kEnumerableProperty, + url: kEnumerableProperty, + status: kEnumerableProperty, + ok: kEnumerableProperty, + redirected: kEnumerableProperty, + statusText: kEnumerableProperty, + headers: kEnumerableProperty, + clone: kEnumerableProperty, + body: kEnumerableProperty, + bodyUsed: kEnumerableProperty, + [Symbol.toStringTag]: { + value: 'Response', + configurable: true } +}) - get data () { - webidl.brandCheck(this, MessageEvent) +Object.defineProperties(Response, { + json: kEnumerableProperty, + redirect: kEnumerableProperty, + error: kEnumerableProperty +}) - return this.#eventInit.data +// https://fetch.spec.whatwg.org/#concept-response-clone +function cloneResponse (response) { + // To clone a response response, run these steps: + + // 1. If response is a filtered response, then return a new identical + // filtered response whose internal response is a clone of response’s + // internal response. + if (response.internalResponse) { + return filterResponse( + cloneResponse(response.internalResponse), + response.type + ) } - get origin () { - webidl.brandCheck(this, MessageEvent) + // 2. Let newResponse be a copy of response, except for its body. + const newResponse = makeResponse({ ...response, body: null }) - return this.#eventInit.origin + // 3. If response’s body is non-null, then set newResponse’s body to the + // result of cloning response’s body. + if (response.body != null) { + newResponse.body = cloneBody(response.body) } - get lastEventId () { - webidl.brandCheck(this, MessageEvent) + // 4. Return newResponse. + return newResponse +} - return this.#eventInit.lastEventId +function makeResponse (init) { + return { + aborted: false, + rangeRequested: false, + timingAllowPassed: false, + requestIncludesCredentials: false, + type: 'default', + status: 200, + timingInfo: null, + cacheState: '', + statusText: '', + ...init, + headersList: init?.headersList + ? new HeadersList(init?.headersList) + : new HeadersList(), + urlList: init?.urlList ? [...init.urlList] : [] } +} - get source () { - webidl.brandCheck(this, MessageEvent) +function makeNetworkError (reason) { + const isError = isErrorLike(reason) + return makeResponse({ + type: 'error', + status: 0, + error: isError + ? reason + : new Error(reason ? String(reason) : reason), + aborted: reason && reason.name === 'AbortError' + }) +} - return this.#eventInit.source - } +// @see https://fetch.spec.whatwg.org/#concept-network-error +function isNetworkError (response) { + return ( + // A network error is a response whose type is "error", + response.type === 'error' && + // status is 0 + response.status === 0 + ) +} - get ports () { - webidl.brandCheck(this, MessageEvent) +function makeFilteredResponse (response, state) { + state = { + internalResponse: response, + ...state + } - if (!Object.isFrozen(this.#eventInit.ports)) { - Object.freeze(this.#eventInit.ports) + return new Proxy(response, { + get (target, p) { + return p in state ? state[p] : target[p] + }, + set (target, p, value) { + assert(!(p in state)) + target[p] = value + return true } + }) +} - return this.#eventInit.ports - } +// https://fetch.spec.whatwg.org/#concept-filtered-response +function filterResponse (response, type) { + // Set response to the following filtered response with response as its + // internal response, depending on request’s response tainting: + if (type === 'basic') { + // A basic filtered response is a filtered response whose type is "basic" + // and header list excludes any headers in internal response’s header list + // whose name is a forbidden response-header name. - initMessageEvent ( - type, - bubbles = false, - cancelable = false, - data = null, - origin = '', - lastEventId = '', - source = null, - ports = [] - ) { - webidl.brandCheck(this, MessageEvent) + // Note: undici does not implement forbidden response-header names + return makeFilteredResponse(response, { + type: 'basic', + headersList: response.headersList + }) + } else if (type === 'cors') { + // A CORS filtered response is a filtered response whose type is "cors" + // and header list excludes any headers in internal response’s header + // list whose name is not a CORS-safelisted response-header name, given + // internal response’s CORS-exposed header-name list. - webidl.argumentLengthCheck(arguments, 1, 'MessageEvent.initMessageEvent') + // Note: undici does not implement CORS-safelisted response-header names + return makeFilteredResponse(response, { + type: 'cors', + headersList: response.headersList + }) + } else if (type === 'opaque') { + // An opaque filtered response is a filtered response whose type is + // "opaque", URL list is the empty list, status is 0, status message + // is the empty byte sequence, header list is empty, and body is null. - return new MessageEvent(type, { - bubbles, cancelable, data, origin, lastEventId, source, ports + return makeFilteredResponse(response, { + type: 'opaque', + urlList: [], + status: 0, + statusText: '', + body: null }) - } + } else if (type === 'opaqueredirect') { + // An opaque-redirect filtered response is a filtered response whose type + // is "opaqueredirect", status is 0, status message is the empty byte + // sequence, header list is empty, and body is null. - static createFastMessageEvent (type, init) { - const messageEvent = new MessageEvent(kConstruct, type, init) - messageEvent.#eventInit = init - messageEvent.#eventInit.data ??= null - messageEvent.#eventInit.origin ??= '' - messageEvent.#eventInit.lastEventId ??= '' - messageEvent.#eventInit.source ??= null - messageEvent.#eventInit.ports ??= [] - return messageEvent + return makeFilteredResponse(response, { + type: 'opaqueredirect', + status: 0, + statusText: '', + headersList: [], + body: null + }) + } else { + assert(false) } } -const { createFastMessageEvent } = MessageEvent -delete MessageEvent.createFastMessageEvent - -/** - * @see https://websockets.spec.whatwg.org/#the-closeevent-interface - */ -class CloseEvent extends Event { - #eventInit - - constructor (type, eventInitDict = {}) { - const prefix = 'CloseEvent constructor' - webidl.argumentLengthCheck(arguments, 1, prefix) - - type = webidl.converters.DOMString(type, prefix, 'type') - eventInitDict = webidl.converters.CloseEventInit(eventInitDict) +// https://fetch.spec.whatwg.org/#appropriate-network-error +function makeAppropriateNetworkError (fetchParams, err = null) { + // 1. Assert: fetchParams is canceled. + assert(isCancelled(fetchParams)) - super(type, eventInitDict) + // 2. Return an aborted network error if fetchParams is aborted; + // otherwise return a network error. + return isAborted(fetchParams) + ? makeNetworkError(Object.assign(new DOMException('The operation was aborted.', 'AbortError'), { cause: err })) + : makeNetworkError(Object.assign(new DOMException('Request was cancelled.'), { cause: err })) +} - this.#eventInit = eventInitDict - webidl.util.markAsUncloneable(this) +// https://whatpr.org/fetch/1392.html#initialize-a-response +function initializeResponse (response, init, body) { + // 1. If init["status"] is not in the range 200 to 599, inclusive, then + // throw a RangeError. + if (init.status !== null && (init.status < 200 || init.status > 599)) { + throw new RangeError('init["status"] must be in the range of 200 to 599, inclusive.') } - get wasClean () { - webidl.brandCheck(this, CloseEvent) + // 2. If init["statusText"] does not match the reason-phrase token production, + // then throw a TypeError. + if ('statusText' in init && init.statusText != null) { + // See, https://datatracker.ietf.org/doc/html/rfc7230#section-3.1.2: + // reason-phrase = *( HTAB / SP / VCHAR / obs-text ) + if (!isValidReasonPhrase(String(init.statusText))) { + throw new TypeError('Invalid statusText') + } + } - return this.#eventInit.wasClean + // 3. Set response’s response’s status to init["status"]. + if ('status' in init && init.status != null) { + getResponseState(response).status = init.status } - get code () { - webidl.brandCheck(this, CloseEvent) + // 4. Set response’s response’s status message to init["statusText"]. + if ('statusText' in init && init.statusText != null) { + getResponseState(response).statusText = init.statusText + } - return this.#eventInit.code + // 5. If init["headers"] exists, then fill response’s headers with init["headers"]. + if ('headers' in init && init.headers != null) { + fill(getResponseHeaders(response), init.headers) } - get reason () { - webidl.brandCheck(this, CloseEvent) + // 6. If body was given, then: + if (body) { + // 1. If response's status is a null body status, then throw a TypeError. + if (nullBodyStatus.includes(response.status)) { + throw webidl.errors.exception({ + header: 'Response constructor', + message: `Invalid response status code ${response.status}` + }) + } - return this.#eventInit.reason + // 2. Set response's body to body's body. + getResponseState(response).body = body.body + + // 3. If body's type is non-null and response's header list does not contain + // `Content-Type`, then append (`Content-Type`, body's type) to response's header list. + if (body.type != null && !getResponseState(response).headersList.contains('content-type', true)) { + getResponseState(response).headersList.append('content-type', body.type, true) + } } } -// https://html.spec.whatwg.org/multipage/webappapis.html#the-errorevent-interface -class ErrorEvent extends Event { - #eventInit - - constructor (type, eventInitDict) { - const prefix = 'ErrorEvent constructor' - webidl.argumentLengthCheck(arguments, 1, prefix) +/** + * @see https://fetch.spec.whatwg.org/#response-create + * @param {any} innerResponse + * @param {'request' | 'immutable' | 'request-no-cors' | 'response' | 'none'} guard + * @returns {Response} + */ +function fromInnerResponse (innerResponse, guard) { + const response = new Response(kConstruct) + setResponseState(response, innerResponse) + const headers = new Headers(kConstruct) + setResponseHeaders(response, headers) + setHeadersList(headers, innerResponse.headersList) + setHeadersGuard(headers, guard) - super(type, eventInitDict) - webidl.util.markAsUncloneable(this) + // Note: If innerResponse's urlList contains a URL, it is a fetch response. + if (innerResponse.urlList.length !== 0 && innerResponse.body?.stream) { + // If the target (response) is reclaimed, the cleanup callback may be called at some point with + // the held value provided for it (innerResponse.body.stream). The held value can be any value: + // a primitive or an object, even undefined. If the held value is an object, the registry keeps + // a strong reference to it (so it can pass it to the cleanup callback later). Reworded from + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/FinalizationRegistry + streamRegistry.register(response, new WeakRef(innerResponse.body.stream)) + } - type = webidl.converters.DOMString(type, prefix, 'type') - eventInitDict = webidl.converters.ErrorEventInit(eventInitDict ?? {}) + return response +} - this.#eventInit = eventInitDict +// https://fetch.spec.whatwg.org/#typedefdef-xmlhttprequestbodyinit +webidl.converters.XMLHttpRequestBodyInit = function (V, prefix, name) { + if (typeof V === 'string') { + return webidl.converters.USVString(V, prefix, name) } - get message () { - webidl.brandCheck(this, ErrorEvent) + if (webidl.is.Blob(V)) { + return V + } - return this.#eventInit.message + if (webidl.is.BufferSource(V)) { + return V } - get filename () { - webidl.brandCheck(this, ErrorEvent) + if (webidl.is.FormData(V)) { + return V + } - return this.#eventInit.filename + if (webidl.is.URLSearchParams(V)) { + return V } - get lineno () { - webidl.brandCheck(this, ErrorEvent) + return webidl.converters.DOMString(V, prefix, name) +} - return this.#eventInit.lineno +// https://fetch.spec.whatwg.org/#bodyinit +webidl.converters.BodyInit = function (V, prefix, argument) { + if (webidl.is.ReadableStream(V)) { + return V } - get colno () { - webidl.brandCheck(this, ErrorEvent) - - return this.#eventInit.colno + // Note: the spec doesn't include async iterables, + // this is an undici extension. + if (V?.[Symbol.asyncIterator]) { + return V } - get error () { - webidl.brandCheck(this, ErrorEvent) - - return this.#eventInit.error - } + return webidl.converters.XMLHttpRequestBodyInit(V, prefix, argument) } -Object.defineProperties(MessageEvent.prototype, { - [Symbol.toStringTag]: { - value: 'MessageEvent', - configurable: true - }, - data: kEnumerableProperty, - origin: kEnumerableProperty, - lastEventId: kEnumerableProperty, - source: kEnumerableProperty, - ports: kEnumerableProperty, - initMessageEvent: kEnumerableProperty -}) - -Object.defineProperties(CloseEvent.prototype, { - [Symbol.toStringTag]: { - value: 'CloseEvent', - configurable: true - }, - reason: kEnumerableProperty, - code: kEnumerableProperty, - wasClean: kEnumerableProperty -}) - -Object.defineProperties(ErrorEvent.prototype, { - [Symbol.toStringTag]: { - value: 'ErrorEvent', - configurable: true - }, - message: kEnumerableProperty, - filename: kEnumerableProperty, - lineno: kEnumerableProperty, - colno: kEnumerableProperty, - error: kEnumerableProperty -}) - -webidl.converters.MessagePort = webidl.interfaceConverter( - webidl.is.MessagePort, - 'MessagePort' -) - -webidl.converters['sequence'] = webidl.sequenceConverter( - webidl.converters.MessagePort -) - -const eventInit = [ - { - key: 'bubbles', - converter: webidl.converters.boolean, - defaultValue: () => false - }, - { - key: 'cancelable', - converter: webidl.converters.boolean, - defaultValue: () => false - }, - { - key: 'composed', - converter: webidl.converters.boolean, - defaultValue: () => false - } -] - -webidl.converters.MessageEventInit = webidl.dictionaryConverter([ - ...eventInit, - { - key: 'data', - converter: webidl.converters.any, - defaultValue: () => null - }, - { - key: 'origin', - converter: webidl.converters.USVString, - defaultValue: () => '' - }, - { - key: 'lastEventId', - converter: webidl.converters.DOMString, - defaultValue: () => '' - }, - { - key: 'source', - // Node doesn't implement WindowProxy or ServiceWorker, so the only - // valid value for source is a MessagePort. - converter: webidl.nullableConverter(webidl.converters.MessagePort), - defaultValue: () => null - }, - { - key: 'ports', - converter: webidl.converters['sequence'], - defaultValue: () => [] - } -]) - -webidl.converters.CloseEventInit = webidl.dictionaryConverter([ - ...eventInit, - { - key: 'wasClean', - converter: webidl.converters.boolean, - defaultValue: () => false - }, +webidl.converters.ResponseInit = webidl.dictionaryConverter([ { - key: 'code', + key: 'status', converter: webidl.converters['unsigned short'], - defaultValue: () => 0 - }, - { - key: 'reason', - converter: webidl.converters.USVString, - defaultValue: () => '' - } -]) - -webidl.converters.ErrorEventInit = webidl.dictionaryConverter([ - ...eventInit, - { - key: 'message', - converter: webidl.converters.DOMString, - defaultValue: () => '' + defaultValue: () => 200 }, { - key: 'filename', - converter: webidl.converters.USVString, + key: 'statusText', + converter: webidl.converters.ByteString, defaultValue: () => '' }, { - key: 'lineno', - converter: webidl.converters['unsigned long'], - defaultValue: () => 0 - }, - { - key: 'colno', - converter: webidl.converters['unsigned long'], - defaultValue: () => 0 - }, - { - key: 'error', - converter: webidl.converters.any + key: 'headers', + converter: webidl.converters.HeadersInit } ]) +webidl.is.Response = webidl.util.MakeTypeAssertion(Response) + module.exports = { - MessageEvent, - CloseEvent, - ErrorEvent, - createFastMessageEvent + isNetworkError, + makeNetworkError, + makeResponse, + makeAppropriateNetworkError, + filterResponse, + Response, + cloneResponse, + fromInnerResponse, + getResponseState } /***/ }), -/***/ 2647: +/***/ 3106: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -const { runtimeFeatures } = __nccwpck_require__(1422) -const { maxUnsigned16Bit, opcodes } = __nccwpck_require__(163) - -const BUFFER_SIZE = 8 * 1024 +const { Transform } = __nccwpck_require__(7075) +const zlib = __nccwpck_require__(8522) +const { redirectStatusSet, referrerPolicyTokens, badPortsSet } = __nccwpck_require__(8973) +const { getGlobalOrigin } = __nccwpck_require__(1393) +const { collectAnHTTPQuotedString, parseMIMEType } = __nccwpck_require__(1410) +const { performance } = __nccwpck_require__(643) +const { ReadableStreamFrom, isValidHTTPToken, normalizedMethodRecordsBase } = __nccwpck_require__(2550) +const assert = __nccwpck_require__(4589) +const { isUint8Array } = __nccwpck_require__(3429) +const { webidl } = __nccwpck_require__(909) +const { isomorphicEncode, collectASequenceOfCodePoints, removeChars } = __nccwpck_require__(5074) -let buffer = null -let bufIdx = BUFFER_SIZE +function responseURL (response) { + // https://fetch.spec.whatwg.org/#responses + // A response has an associated URL. It is a pointer to the last URL + // in response’s URL list and null if response’s URL list is empty. + const urlList = response.urlList + const length = urlList.length + return length === 0 ? null : urlList[length - 1].toString() +} -const randomFillSync = runtimeFeatures.has('crypto') - ? (__nccwpck_require__(7598).randomFillSync) - // not full compatibility, but minimum. - : function randomFillSync (buffer, _offset, _size) { - for (let i = 0; i < buffer.length; ++i) { - buffer[i] = Math.random() * 255 | 0 - } - return buffer +// https://fetch.spec.whatwg.org/#concept-response-location-url +function responseLocationURL (response, requestFragment) { + // 1. If response’s status is not a redirect status, then return null. + if (!redirectStatusSet.has(response.status)) { + return null } -function generateMask () { - if (bufIdx === BUFFER_SIZE) { - bufIdx = 0 - randomFillSync((buffer ??= Buffer.allocUnsafeSlow(BUFFER_SIZE)), 0, BUFFER_SIZE) + // 2. Let location be the result of extracting header list values given + // `Location` and response’s header list. + let location = response.headersList.get('location', true) + + // 3. If location is a header value, then set location to the result of + // parsing location with response’s URL. + if (location !== null && isValidHeaderValue(location)) { + if (!isValidEncodedURL(location)) { + // Some websites respond location header in UTF-8 form without encoding them as ASCII + // and major browsers redirect them to correctly UTF-8 encoded addresses. + // Here, we handle that behavior in the same way. + location = normalizeBinaryStringToUtf8(location) + } + location = new URL(location, responseURL(response)) } - return [buffer[bufIdx++], buffer[bufIdx++], buffer[bufIdx++], buffer[bufIdx++]] -} -class WebsocketFrameSend { - /** - * @param {Buffer|undefined} data - */ - constructor (data) { - this.frameData = data + // 4. If location is a URL whose fragment is null, then set location’s + // fragment to requestFragment. + if (location && !location.hash) { + location.hash = requestFragment } - createFrame (opcode) { - const frameData = this.frameData - const maskKey = generateMask() - const bodyLength = frameData?.byteLength ?? 0 + // 5. Return location. + return location +} - /** @type {number} */ - let payloadLength = bodyLength // 0-125 - let offset = 6 +/** + * @see https://www.rfc-editor.org/rfc/rfc1738#section-2.2 + * @param {string} url + * @returns {boolean} + */ +function isValidEncodedURL (url) { + for (let i = 0; i < url.length; ++i) { + const code = url.charCodeAt(i) - if (bodyLength > maxUnsigned16Bit) { - offset += 8 // payload length is next 8 bytes - payloadLength = 127 - } else if (bodyLength > 125) { - offset += 2 // payload length is next 2 bytes - payloadLength = 126 + if ( + code > 0x7E || // Non-US-ASCII + DEL + code < 0x20 // Control characters NUL - US + ) { + return false } + } + return true +} - const buffer = Buffer.allocUnsafe(bodyLength + offset) +/** + * If string contains non-ASCII characters, assumes it's UTF-8 encoded and decodes it. + * Since UTF-8 is a superset of ASCII, this will work for ASCII strings as well. + * @param {string} value + * @returns {string} + */ +function normalizeBinaryStringToUtf8 (value) { + return Buffer.from(value, 'binary').toString('utf8') +} - // Clear first 2 bytes, everything else is overwritten - buffer[0] = buffer[1] = 0 - buffer[0] |= 0x80 // FIN - buffer[0] = (buffer[0] & 0xF0) + opcode // opcode +/** @returns {URL} */ +function requestCurrentURL (request) { + return request.urlList[request.urlList.length - 1] +} - /*! ws. MIT License. Einar Otto Stangvik */ - buffer[offset - 4] = maskKey[0] - buffer[offset - 3] = maskKey[1] - buffer[offset - 2] = maskKey[2] - buffer[offset - 1] = maskKey[3] +function requestBadPort (request) { + // 1. Let url be request’s current URL. + const url = requestCurrentURL(request) - buffer[1] = payloadLength + // 2. If url’s scheme is an HTTP(S) scheme and url’s port is a bad port, + // then return blocked. + if (urlIsHttpHttpsScheme(url) && badPortsSet.has(url.port)) { + return 'blocked' + } - if (payloadLength === 126) { - buffer.writeUInt16BE(bodyLength, 2) - } else if (payloadLength === 127) { - // Clear extended payload length - buffer[2] = buffer[3] = 0 - buffer.writeUIntBE(bodyLength, 4, 6) - } + // 3. Return allowed. + return 'allowed' +} - buffer[1] |= 0x80 // MASK +function isErrorLike (object) { + return object instanceof Error || ( + object?.constructor?.name === 'Error' || + object?.constructor?.name === 'DOMException' + ) +} - // mask body - for (let i = 0; i < bodyLength; ++i) { - buffer[offset + i] = frameData[i] ^ maskKey[i & 3] +// Check whether |statusText| is a ByteString and +// matches the Reason-Phrase token production. +// RFC 2616: https://tools.ietf.org/html/rfc2616 +// RFC 7230: https://tools.ietf.org/html/rfc7230 +// "reason-phrase = *( HTAB / SP / VCHAR / obs-text )" +// https://github.com/chromium/chromium/blob/94.0.4604.1/third_party/blink/renderer/core/fetch/response.cc#L116 +function isValidReasonPhrase (statusText) { + for (let i = 0; i < statusText.length; ++i) { + const c = statusText.charCodeAt(i) + if ( + !( + ( + c === 0x09 || // HTAB + (c >= 0x20 && c <= 0x7e) || // SP / VCHAR + (c >= 0x80 && c <= 0xff) + ) // obs-text + ) + ) { + return false } - - return buffer } + return true +} - /** - * @param {Uint8Array} buffer - */ - static createFastTextFrame (buffer) { - const maskKey = generateMask() +/** + * @see https://fetch.spec.whatwg.org/#header-name + * @param {string} potentialValue + */ +const isValidHeaderName = isValidHTTPToken - const bodyLength = buffer.length +/** + * @see https://fetch.spec.whatwg.org/#header-value + * @param {string} potentialValue + */ +function isValidHeaderValue (potentialValue) { + // - Has no leading or trailing HTTP tab or space bytes. + // - Contains no 0x00 (NUL) or HTTP newline bytes. + return ( + potentialValue[0] === '\t' || + potentialValue[0] === ' ' || + potentialValue[potentialValue.length - 1] === '\t' || + potentialValue[potentialValue.length - 1] === ' ' || + potentialValue.includes('\n') || + potentialValue.includes('\r') || + potentialValue.includes('\0') + ) === false +} - // mask body - for (let i = 0; i < bodyLength; ++i) { - buffer[i] ^= maskKey[i & 3] - } +/** + * Parse a referrer policy from a Referrer-Policy header + * @see https://w3c.github.io/webappsec-referrer-policy/#parse-referrer-policy-from-header + */ +function parseReferrerPolicy (actualResponse) { + // 1. Let policy-tokens be the result of extracting header list values given `Referrer-Policy` and response’s header list. + const policyHeader = (actualResponse.headersList.get('referrer-policy', true) ?? '').split(',') - let payloadLength = bodyLength - let offset = 6 + // 2. Let policy be the empty string. + let policy = '' - if (bodyLength > maxUnsigned16Bit) { - offset += 8 // payload length is next 8 bytes - payloadLength = 127 - } else if (bodyLength > 125) { - offset += 2 // payload length is next 2 bytes - payloadLength = 126 + // 3. For each token in policy-tokens, if token is a referrer policy and token is not the empty string, then set policy to token. + + // Note: As the referrer-policy can contain multiple policies + // separated by comma, we need to loop through all of them + // and pick the first valid one. + // Ref: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy#specify_a_fallback_policy + if (policyHeader.length) { + // The right-most policy takes precedence. + // The left-most policy is the fallback. + for (let i = policyHeader.length; i !== 0; i--) { + const token = policyHeader[i - 1].trim() + if (referrerPolicyTokens.has(token)) { + policy = token + break + } } - const head = Buffer.allocUnsafeSlow(offset) + } - head[0] = 0x80 /* FIN */ | opcodes.TEXT /* opcode TEXT */ - head[1] = payloadLength | 0x80 /* MASK */ - head[offset - 4] = maskKey[0] - head[offset - 3] = maskKey[1] - head[offset - 2] = maskKey[2] - head[offset - 1] = maskKey[3] + // 4. Return policy. + return policy +} - if (payloadLength === 126) { - head.writeUInt16BE(bodyLength, 2) - } else if (payloadLength === 127) { - head[2] = head[3] = 0 - head.writeUIntBE(bodyLength, 4, 6) - } +/** + * Given a request request and a response actualResponse, this algorithm + * updates request’s referrer policy according to the Referrer-Policy + * header (if any) in actualResponse. + * @see https://w3c.github.io/webappsec-referrer-policy/#set-requests-referrer-policy-on-redirect + * @param {import('./request').Request} request + * @param {import('./response').Response} actualResponse + */ +function setRequestReferrerPolicyOnRedirect (request, actualResponse) { + // 1. Let policy be the result of executing § 8.1 Parse a referrer policy + // from a Referrer-Policy header on actualResponse. + const policy = parseReferrerPolicy(actualResponse) - return [head, buffer] + // 2. If policy is not the empty string, then set request’s referrer policy to policy. + if (policy !== '') { + request.referrerPolicy = policy } } -module.exports = { - WebsocketFrameSend, - generateMask // for benchmark +// https://fetch.spec.whatwg.org/#cross-origin-resource-policy-check +function crossOriginResourcePolicyCheck () { + // TODO + return 'allowed' } +// https://fetch.spec.whatwg.org/#concept-cors-check +function corsCheck () { + // TODO + return 'success' +} -/***/ }), +// https://fetch.spec.whatwg.org/#concept-tao-check +function TAOCheck () { + // TODO + return 'success' +} -/***/ 8748: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +function appendFetchMetadata (httpRequest) { + // https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-dest-header + // TODO -"use strict"; + // https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-mode-header + // 1. Assert: r’s url is a potentially trustworthy URL. + // TODO -const { createInflateRaw, Z_DEFAULT_WINDOWBITS } = __nccwpck_require__(8522) -const { isValidClientWindowBits } = __nccwpck_require__(7484) + // 2. Let header be a Structured Header whose value is a token. + let header = null -const tail = Buffer.from([0x00, 0x00, 0xff, 0xff]) -const kBuffer = Symbol('kBuffer') -const kLength = Symbol('kLength') + // 3. Set header’s value to r’s mode. + header = httpRequest.mode -class PerMessageDeflate { - /** @type {import('node:zlib').InflateRaw} */ - #inflate + // 4. Set a structured field value `Sec-Fetch-Mode`/header in r’s header list. + httpRequest.headersList.set('sec-fetch-mode', header, true) - #options = {} + // https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-site-header + // TODO - constructor (extensions) { - this.#options.serverNoContextTakeover = extensions.has('server_no_context_takeover') - this.#options.serverMaxWindowBits = extensions.get('server_max_window_bits') - } + // https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-user-header + // TODO +} - decompress (chunk, fin, callback) { - // An endpoint uses the following algorithm to decompress a message. - // 1. Append 4 octets of 0x00 0x00 0xff 0xff to the tail end of the - // payload of the message. - // 2. Decompress the resulting data using DEFLATE. +// https://fetch.spec.whatwg.org/#append-a-request-origin-header +function appendRequestOriginHeader (request) { + // 1. Let serializedOrigin be the result of byte-serializing a request origin + // with request. + // TODO: implement "byte-serializing a request origin" + let serializedOrigin = request.origin - if (!this.#inflate) { - let windowBits = Z_DEFAULT_WINDOWBITS + // - "'client' is changed to an origin during fetching." + // This doesn't happen in undici (in most cases) because undici, by default, + // has no concept of origin. + // - request.origin can also be set to request.client.origin (client being + // an environment settings object), which is undefined without using + // setGlobalOrigin. + if (serializedOrigin === 'client' || serializedOrigin === undefined) { + return + } - if (this.#options.serverMaxWindowBits) { // empty values default to Z_DEFAULT_WINDOWBITS - if (!isValidClientWindowBits(this.#options.serverMaxWindowBits)) { - callback(new Error('Invalid server_max_window_bits')) - return + // 2. If request’s response tainting is "cors" or request’s mode is "websocket", + // then append (`Origin`, serializedOrigin) to request’s header list. + // 3. Otherwise, if request’s method is neither `GET` nor `HEAD`, then: + if (request.responseTainting === 'cors' || request.mode === 'websocket') { + request.headersList.append('origin', serializedOrigin, true) + } else if (request.method !== 'GET' && request.method !== 'HEAD') { + // 1. Switch on request’s referrer policy: + switch (request.referrerPolicy) { + case 'no-referrer': + // Set serializedOrigin to `null`. + serializedOrigin = null + break + case 'no-referrer-when-downgrade': + case 'strict-origin': + case 'strict-origin-when-cross-origin': + // If request’s origin is a tuple origin, its scheme is "https", and + // request’s current URL’s scheme is not "https", then set + // serializedOrigin to `null`. + if (request.origin && urlHasHttpsScheme(request.origin) && !urlHasHttpsScheme(requestCurrentURL(request))) { + serializedOrigin = null } + break + case 'same-origin': + // If request’s origin is not same origin with request’s current URL’s + // origin, then set serializedOrigin to `null`. + if (!sameOrigin(request, requestCurrentURL(request))) { + serializedOrigin = null + } + break + default: + // Do nothing. + } - windowBits = Number.parseInt(this.#options.serverMaxWindowBits) - } - - this.#inflate = createInflateRaw({ windowBits }) - this.#inflate[kBuffer] = [] - this.#inflate[kLength] = 0 + // 2. Append (`Origin`, serializedOrigin) to request’s header list. + request.headersList.append('origin', serializedOrigin, true) + } +} - this.#inflate.on('data', (data) => { - this.#inflate[kBuffer].push(data) - this.#inflate[kLength] += data.length - }) +// https://w3c.github.io/hr-time/#dfn-coarsen-time +function coarsenTime (timestamp, crossOriginIsolatedCapability) { + // TODO + return timestamp +} - this.#inflate.on('error', (err) => { - this.#inflate = null - callback(err) - }) +// https://fetch.spec.whatwg.org/#clamp-and-coarsen-connection-timing-info +function clampAndCoarsenConnectionTimingInfo (connectionTimingInfo, defaultStartTime, crossOriginIsolatedCapability) { + if (!connectionTimingInfo?.startTime || connectionTimingInfo.startTime < defaultStartTime) { + return { + domainLookupStartTime: defaultStartTime, + domainLookupEndTime: defaultStartTime, + connectionStartTime: defaultStartTime, + connectionEndTime: defaultStartTime, + secureConnectionStartTime: defaultStartTime, + ALPNNegotiatedProtocol: connectionTimingInfo?.ALPNNegotiatedProtocol } + } - this.#inflate.write(chunk) - if (fin) { - this.#inflate.write(tail) - } + return { + domainLookupStartTime: coarsenTime(connectionTimingInfo.domainLookupStartTime, crossOriginIsolatedCapability), + domainLookupEndTime: coarsenTime(connectionTimingInfo.domainLookupEndTime, crossOriginIsolatedCapability), + connectionStartTime: coarsenTime(connectionTimingInfo.connectionStartTime, crossOriginIsolatedCapability), + connectionEndTime: coarsenTime(connectionTimingInfo.connectionEndTime, crossOriginIsolatedCapability), + secureConnectionStartTime: coarsenTime(connectionTimingInfo.secureConnectionStartTime, crossOriginIsolatedCapability), + ALPNNegotiatedProtocol: connectionTimingInfo.ALPNNegotiatedProtocol + } +} - this.#inflate.flush(() => { - const full = Buffer.concat(this.#inflate[kBuffer], this.#inflate[kLength]) +// https://w3c.github.io/hr-time/#dfn-coarsened-shared-current-time +function coarsenedSharedCurrentTime (crossOriginIsolatedCapability) { + return coarsenTime(performance.now(), crossOriginIsolatedCapability) +} - this.#inflate[kBuffer].length = 0 - this.#inflate[kLength] = 0 +// https://fetch.spec.whatwg.org/#create-an-opaque-timing-info +function createOpaqueTimingInfo (timingInfo) { + return { + startTime: timingInfo.startTime ?? 0, + redirectStartTime: 0, + redirectEndTime: 0, + postRedirectStartTime: timingInfo.startTime ?? 0, + finalServiceWorkerStartTime: 0, + finalNetworkResponseStartTime: 0, + finalNetworkRequestStartTime: 0, + endTime: 0, + encodedBodySize: 0, + decodedBodySize: 0, + finalConnectionTimingInfo: null + } +} - callback(null, full) - }) +// https://html.spec.whatwg.org/multipage/origin.html#policy-container +function makePolicyContainer () { + // Note: the fetch spec doesn't make use of embedder policy or CSP list + return { + referrerPolicy: 'strict-origin-when-cross-origin' } } -module.exports = { PerMessageDeflate } +// https://html.spec.whatwg.org/multipage/origin.html#clone-a-policy-container +function clonePolicyContainer (policyContainer) { + return { + referrerPolicy: policyContainer.referrerPolicy + } +} +/** + * Determine request’s Referrer + * + * @see https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer + */ +function determineRequestsReferrer (request) { + // Given a request request, we can determine the correct referrer information + // to send by examining its referrer policy as detailed in the following + // steps, which return either no referrer or a URL: -/***/ }), + // 1. Let policy be request's referrer policy. + const policy = request.referrerPolicy -/***/ 7713: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // Note: policy cannot (shouldn't) be null or an empty string. + assert(policy) -"use strict"; + // 2. Let environment be request’s client. + let referrerSource = null -const { Writable } = __nccwpck_require__(7075) -const assert = __nccwpck_require__(4589) -const { parserStates, opcodes, states, emptyBuffer, sentCloseFrameState } = __nccwpck_require__(163) -const { - isValidStatusCode, - isValidOpcode, - websocketMessageReceived, - utf8Decode, - isControlFrame, - isTextBinaryFrame, - isContinuationFrame -} = __nccwpck_require__(7484) -const { failWebsocketConnection } = __nccwpck_require__(9136) -const { WebsocketFrameSend } = __nccwpck_require__(2647) -const { PerMessageDeflate } = __nccwpck_require__(8748) + // 3. Switch on request’s referrer: -// This code was influenced by ws released under the MIT license. -// Copyright (c) 2011 Einar Otto Stangvik -// Copyright (c) 2013 Arnout Kazemier and contributors -// Copyright (c) 2016 Luigi Pinca and contributors + // "client" + if (request.referrer === 'client') { + // Note: node isn't a browser and doesn't implement document/iframes, + // so we bypass this step and replace it with our own. -class ByteParser extends Writable { - #buffers = [] - #fragmentsBytes = 0 - #byteOffset = 0 - #loop = false + const globalOrigin = getGlobalOrigin() - #state = parserStates.INFO + if (!globalOrigin || globalOrigin.origin === 'null') { + return 'no-referrer' + } - #info = {} - #fragments = [] + // Note: we need to clone it as it's mutated + referrerSource = new URL(globalOrigin) + // a URL + } else if (webidl.is.URL(request.referrer)) { + // Let referrerSource be request’s referrer. + referrerSource = request.referrer + } - /** @type {Map} */ - #extensions + // 4. Let request’s referrerURL be the result of stripping referrerSource for + // use as a referrer. + let referrerURL = stripURLForReferrer(referrerSource) - /** @type {import('./websocket').Handler} */ - #handler + // 5. Let referrerOrigin be the result of stripping referrerSource for use as + // a referrer, with the origin-only flag set to true. + const referrerOrigin = stripURLForReferrer(referrerSource, true) - constructor (handler, extensions) { - super() + // 6. If the result of serializing referrerURL is a string whose length is + // greater than 4096, set referrerURL to referrerOrigin. + if (referrerURL.toString().length > 4096) { + referrerURL = referrerOrigin + } - this.#handler = handler - this.#extensions = extensions == null ? new Map() : extensions + // 7. The user agent MAY alter referrerURL or referrerOrigin at this point + // to enforce arbitrary policy considerations in the interests of minimizing + // data leakage. For example, the user agent could strip the URL down to an + // origin, modify its host, replace it with an empty string, etc. - if (this.#extensions.has('permessage-deflate')) { - this.#extensions.set('permessage-deflate', new PerMessageDeflate(extensions)) + // 8. Execute the switch statements corresponding to the value of policy: + switch (policy) { + case 'no-referrer': + // Return no referrer + return 'no-referrer' + case 'origin': + // Return referrerOrigin + if (referrerOrigin != null) { + return referrerOrigin + } + return stripURLForReferrer(referrerSource, true) + case 'unsafe-url': + // Return referrerURL. + return referrerURL + case 'strict-origin': { + const currentURL = requestCurrentURL(request) + + // 1. If referrerURL is a potentially trustworthy URL and request’s + // current URL is not a potentially trustworthy URL, then return no + // referrer. + if (isURLPotentiallyTrustworthy(referrerURL) && !isURLPotentiallyTrustworthy(currentURL)) { + return 'no-referrer' + } + // 2. Return referrerOrigin + return referrerOrigin } - } + case 'strict-origin-when-cross-origin': { + const currentURL = requestCurrentURL(request) - /** - * @param {Buffer} chunk - * @param {() => void} callback - */ - _write (chunk, _, callback) { - this.#buffers.push(chunk) - this.#byteOffset += chunk.length - this.#loop = true + // 1. If the origin of referrerURL and the origin of request’s current + // URL are the same, then return referrerURL. + if (sameOrigin(referrerURL, currentURL)) { + return referrerURL + } - this.run(callback) + // 2. If referrerURL is a potentially trustworthy URL and request’s + // current URL is not a potentially trustworthy URL, then return no + // referrer. + if (isURLPotentiallyTrustworthy(referrerURL) && !isURLPotentiallyTrustworthy(currentURL)) { + return 'no-referrer' + } + + // 3. Return referrerOrigin. + return referrerOrigin + } + case 'same-origin': + // 1. If the origin of referrerURL and the origin of request’s current + // URL are the same, then return referrerURL. + if (sameOrigin(request, referrerURL)) { + return referrerURL + } + // 2. Return no referrer. + return 'no-referrer' + case 'origin-when-cross-origin': + // 1. If the origin of referrerURL and the origin of request’s current + // URL are the same, then return referrerURL. + if (sameOrigin(request, referrerURL)) { + return referrerURL + } + // 2. Return referrerOrigin. + return referrerOrigin + case 'no-referrer-when-downgrade': { + const currentURL = requestCurrentURL(request) + + // 1. If referrerURL is a potentially trustworthy URL and request’s + // current URL is not a potentially trustworthy URL, then return no + // referrer. + if (isURLPotentiallyTrustworthy(referrerURL) && !isURLPotentiallyTrustworthy(currentURL)) { + return 'no-referrer' + } + // 2. Return referrerURL. + return referrerURL + } } +} - /** - * Runs whenever a new chunk is received. - * Callback is called whenever there are no more chunks buffering, - * or not enough bytes are buffered to parse. - */ - run (callback) { - while (this.#loop) { - if (this.#state === parserStates.INFO) { - // If there aren't enough bytes to parse the payload length, etc. - if (this.#byteOffset < 2) { - return callback() - } +/** + * Certain portions of URLs must not be included when sending a URL as the + * value of a `Referer` header: a URLs fragment, username, and password + * components must be stripped from the URL before it’s sent out. This + * algorithm accepts a origin-only flag, which defaults to false. If set to + * true, the algorithm will additionally remove the URL’s path and query + * components, leaving only the scheme, host, and port. + * + * @see https://w3c.github.io/webappsec-referrer-policy/#strip-url + * @param {URL} url + * @param {boolean} [originOnly=false] + */ +function stripURLForReferrer (url, originOnly = false) { + // 1. Assert: url is a URL. + assert(webidl.is.URL(url)) - const buffer = this.consume(2) - const fin = (buffer[0] & 0x80) !== 0 - const opcode = buffer[0] & 0x0F - const masked = (buffer[1] & 0x80) === 0x80 + // Note: Create a new URL instance to avoid mutating the original URL. + url = new URL(url) - const fragmented = !fin && opcode !== opcodes.CONTINUATION - const payloadLength = buffer[1] & 0x7F + // 2. If url’s scheme is a local scheme, then return no referrer. + if (urlIsLocal(url)) { + return 'no-referrer' + } - const rsv1 = buffer[0] & 0x40 - const rsv2 = buffer[0] & 0x20 - const rsv3 = buffer[0] & 0x10 + // 3. Set url’s username to the empty string. + url.username = '' - if (!isValidOpcode(opcode)) { - failWebsocketConnection(this.#handler, 1002, 'Invalid opcode received') - return callback() - } + // 4. Set url’s password to the empty string. + url.password = '' - if (masked) { - failWebsocketConnection(this.#handler, 1002, 'Frame cannot be masked') - return callback() - } + // 5. Set url’s fragment to null. + url.hash = '' - // MUST be 0 unless an extension is negotiated that defines meanings - // for non-zero values. If a nonzero value is received and none of - // the negotiated extensions defines the meaning of such a nonzero - // value, the receiving endpoint MUST _Fail the WebSocket - // Connection_. - // This document allocates the RSV1 bit of the WebSocket header for - // PMCEs and calls the bit the "Per-Message Compressed" bit. On a - // WebSocket connection where a PMCE is in use, this bit indicates - // whether a message is compressed or not. - if (rsv1 !== 0 && !this.#extensions.has('permessage-deflate')) { - failWebsocketConnection(this.#handler, 1002, 'Expected RSV1 to be clear.') - return - } + // 6. If the origin-only flag is true, then: + if (originOnly === true) { + // 1. Set url’s path to « the empty string ». + url.pathname = '' - if (rsv2 !== 0 || rsv3 !== 0) { - failWebsocketConnection(this.#handler, 1002, 'RSV1, RSV2, RSV3 must be clear') - return - } + // 2. Set url’s query to null. + url.search = '' + } - if (fragmented && !isTextBinaryFrame(opcode)) { - // Only text and binary frames can be fragmented - failWebsocketConnection(this.#handler, 1002, 'Invalid frame type was fragmented.') - return - } + // 7. Return url. + return url +} - // If we are already parsing a text/binary frame and do not receive either - // a continuation frame or close frame, fail the connection. - if (isTextBinaryFrame(opcode) && this.#fragments.length > 0) { - failWebsocketConnection(this.#handler, 1002, 'Expected continuation frame') - return - } +const isPotentialleTrustworthyIPv4 = RegExp.prototype.test + .bind(/^127\.(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)\.){2}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)$/) - if (this.#info.fragmented && fragmented) { - // A fragmented frame can't be fragmented itself - failWebsocketConnection(this.#handler, 1002, 'Fragmented frame exceeded 125 bytes.') - return - } +const isPotentiallyTrustworthyIPv6 = RegExp.prototype.test + .bind(/^(?:(?:0{1,4}:){7}|(?:0{1,4}:){1,6}:|::)0{0,3}1$/) - // "All control frames MUST have a payload length of 125 bytes or less - // and MUST NOT be fragmented." - if ((payloadLength > 125 || fragmented) && isControlFrame(opcode)) { - failWebsocketConnection(this.#handler, 1002, 'Control frame either too large or fragmented') - return - } +/** + * Check if host matches one of the CIDR notations 127.0.0.0/8 or ::1/128. + * + * @param {string} origin + * @returns {boolean} + */ +function isOriginIPPotentiallyTrustworthy (origin) { + // IPv6 + if (origin.includes(':')) { + // Remove brackets from IPv6 addresses + if (origin[0] === '[' && origin[origin.length - 1] === ']') { + origin = origin.slice(1, -1) + } + return isPotentiallyTrustworthyIPv6(origin) + } - if (isContinuationFrame(opcode) && this.#fragments.length === 0 && !this.#info.compressed) { - failWebsocketConnection(this.#handler, 1002, 'Unexpected continuation frame') - return - } + // IPv4 + return isPotentialleTrustworthyIPv4(origin) +} - if (payloadLength <= 125) { - this.#info.payloadLength = payloadLength - this.#state = parserStates.READ_DATA - } else if (payloadLength === 126) { - this.#state = parserStates.PAYLOADLENGTH_16 - } else if (payloadLength === 127) { - this.#state = parserStates.PAYLOADLENGTH_64 - } +/** + * A potentially trustworthy origin is one which a user agent can generally + * trust as delivering data securely. + * + * Return value `true` means `Potentially Trustworthy`. + * Return value `false` means `Not Trustworthy`. + * + * @see https://w3c.github.io/webappsec-secure-contexts/#is-origin-trustworthy + * @param {string} origin + * @returns {boolean} + */ +function isOriginPotentiallyTrustworthy (origin) { + // 1. If origin is an opaque origin, return "Not Trustworthy". + if (origin == null || origin === 'null') { + return false + } - if (isTextBinaryFrame(opcode)) { - this.#info.binaryType = opcode - this.#info.compressed = rsv1 !== 0 - } + // 2. Assert: origin is a tuple origin. + origin = new URL(origin) - this.#info.opcode = opcode - this.#info.masked = masked - this.#info.fin = fin - this.#info.fragmented = fragmented - } else if (this.#state === parserStates.PAYLOADLENGTH_16) { - if (this.#byteOffset < 2) { - return callback() - } + // 3. If origin’s scheme is either "https" or "wss", + // return "Potentially Trustworthy". + if (origin.protocol === 'https:' || origin.protocol === 'wss:') { + return true + } - const buffer = this.consume(2) + // 4. If origin’s host matches one of the CIDR notations 127.0.0.0/8 or + // ::1/128 [RFC4632], return "Potentially Trustworthy". + if (isOriginIPPotentiallyTrustworthy(origin.hostname)) { + return true + } - this.#info.payloadLength = buffer.readUInt16BE(0) - this.#state = parserStates.READ_DATA - } else if (this.#state === parserStates.PAYLOADLENGTH_64) { - if (this.#byteOffset < 8) { - return callback() - } + // 5. If the user agent conforms to the name resolution rules in + // [let-localhost-be-localhost] and one of the following is true: - const buffer = this.consume(8) - const upper = buffer.readUInt32BE(0) + // origin’s host is "localhost" or "localhost." + if (origin.hostname === 'localhost' || origin.hostname === 'localhost.') { + return true + } - // 2^31 is the maximum bytes an arraybuffer can contain - // on 32-bit systems. Although, on 64-bit systems, this is - // 2^53-1 bytes. - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Invalid_array_length - // https://source.chromium.org/chromium/chromium/src/+/main:v8/src/common/globals.h;drc=1946212ac0100668f14eb9e2843bdd846e510a1e;bpv=1;bpt=1;l=1275 - // https://source.chromium.org/chromium/chromium/src/+/main:v8/src/objects/js-array-buffer.h;l=34;drc=1946212ac0100668f14eb9e2843bdd846e510a1e - if (upper > 2 ** 31 - 1) { - failWebsocketConnection(this.#handler, 1009, 'Received payload length > 2^31 bytes.') - return - } + // origin’s host ends with ".localhost" or ".localhost." + if (origin.hostname.endsWith('.localhost') || origin.hostname.endsWith('.localhost.')) { + return true + } - const lower = buffer.readUInt32BE(4) + // 6. If origin’s scheme is "file", return "Potentially Trustworthy". + if (origin.protocol === 'file:') { + return true + } - this.#info.payloadLength = (upper << 8) + lower - this.#state = parserStates.READ_DATA - } else if (this.#state === parserStates.READ_DATA) { - if (this.#byteOffset < this.#info.payloadLength) { - return callback() - } + // 7. If origin’s scheme component is one which the user agent considers to + // be authenticated, return "Potentially Trustworthy". - const body = this.consume(this.#info.payloadLength) + // 8. If origin has been configured as a trustworthy origin, return + // "Potentially Trustworthy". - if (isControlFrame(this.#info.opcode)) { - this.#loop = this.parseControlFrame(body) - this.#state = parserStates.INFO - } else { - if (!this.#info.compressed) { - this.writeFragments(body) + // 9. Return "Not Trustworthy". + return false +} - // If the frame is not fragmented, a message has been received. - // If the frame is fragmented, it will terminate with a fin bit set - // and an opcode of 0 (continuation), therefore we handle that when - // parsing continuation frames, not here. - if (!this.#info.fragmented && this.#info.fin) { - websocketMessageReceived(this.#handler, this.#info.binaryType, this.consumeFragments()) - } +/** + * A potentially trustworthy URL is one which either inherits context from its + * creator (about:blank, about:srcdoc, data) or one whose origin is a + * potentially trustworthy origin. + * + * Return value `true` means `Potentially Trustworthy`. + * Return value `false` means `Not Trustworthy`. + * + * @see https://www.w3.org/TR/secure-contexts/#is-url-trustworthy + * @param {URL} url + * @returns {boolean} + */ +function isURLPotentiallyTrustworthy (url) { + // Given a URL record (url), the following algorithm returns "Potentially + // Trustworthy" or "Not Trustworthy" as appropriate: + if (!webidl.is.URL(url)) { + return false + } - this.#state = parserStates.INFO - } else { - this.#extensions.get('permessage-deflate').decompress(body, this.#info.fin, (error, data) => { - if (error) { - failWebsocketConnection(this.#handler, 1007, error.message) - return - } + // 1. If url is "about:blank" or "about:srcdoc", + // return "Potentially Trustworthy". + if (url.href === 'about:blank' || url.href === 'about:srcdoc') { + return true + } - this.writeFragments(data) + // 2. If url’s scheme is "data", return "Potentially Trustworthy". + if (url.protocol === 'data:') return true - if (!this.#info.fin) { - this.#state = parserStates.INFO - this.#loop = true - this.run(callback) - return - } + // Note: The origin of blob: URLs is the origin of the context in which they + // were created. Therefore, blobs created in a trustworthy origin will + // themselves be potentially trustworthy. + if (url.protocol === 'blob:') return true - websocketMessageReceived(this.#handler, this.#info.binaryType, this.consumeFragments()) + // 3. Return the result of executing § 3.1 Is origin potentially trustworthy? + // on url’s origin. + return isOriginPotentiallyTrustworthy(url.origin) +} - this.#loop = true - this.#state = parserStates.INFO - this.run(callback) - }) +// https://w3c.github.io/webappsec-upgrade-insecure-requests/#upgrade-request +function tryUpgradeRequestToAPotentiallyTrustworthyURL (request) { + // TODO +} - this.#loop = false - break - } - } - } - } +/** + * @link {https://html.spec.whatwg.org/multipage/origin.html#same-origin} + * @param {URL} A + * @param {URL} B + */ +function sameOrigin (A, B) { + // 1. If A and B are the same opaque origin, then return true. + if (A.origin === B.origin && A.origin === 'null') { + return true } - /** - * Take n bytes from the buffered Buffers - * @param {number} n - * @returns {Buffer} - */ - consume (n) { - if (n > this.#byteOffset) { - throw new Error('Called consume() before buffers satiated.') - } else if (n === 0) { - return emptyBuffer - } - - this.#byteOffset -= n + // 2. If A and B are both tuple origins and their schemes, + // hosts, and port are identical, then return true. + if (A.protocol === B.protocol && A.hostname === B.hostname && A.port === B.port) { + return true + } - const first = this.#buffers[0] + // 3. Return false. + return false +} - if (first.length > n) { - // replace with remaining buffer - this.#buffers[0] = first.subarray(n, first.length) - return first.subarray(0, n) - } else if (first.length === n) { - // prefect match - return this.#buffers.shift() - } else { - let offset = 0 - // If Buffer.allocUnsafe is used, extra copies will be made because the offset is non-zero. - const buffer = Buffer.allocUnsafeSlow(n) - while (offset !== n) { - const next = this.#buffers[0] - const length = next.length +function isAborted (fetchParams) { + return fetchParams.controller.state === 'aborted' +} - if (length + offset === n) { - buffer.set(this.#buffers.shift(), offset) - break - } else if (length + offset > n) { - buffer.set(next.subarray(0, n - offset), offset) - this.#buffers[0] = next.subarray(n - offset) - break - } else { - buffer.set(this.#buffers.shift(), offset) - offset += length - } - } +function isCancelled (fetchParams) { + return fetchParams.controller.state === 'aborted' || + fetchParams.controller.state === 'terminated' +} - return buffer - } - } +/** + * @see https://fetch.spec.whatwg.org/#concept-method-normalize + * @param {string} method + */ +function normalizeMethod (method) { + return normalizedMethodRecordsBase[method.toLowerCase()] ?? method +} - writeFragments (fragment) { - this.#fragmentsBytes += fragment.length - this.#fragments.push(fragment) - } +// https://tc39.es/ecma262/#sec-%25iteratorprototype%25-object +const esIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]())) - consumeFragments () { - const fragments = this.#fragments +/** + * @see https://webidl.spec.whatwg.org/#dfn-iterator-prototype-object + * @param {string} name name of the instance + * @param {((target: any) => any)} kInternalIterator + * @param {string | number} [keyIndex] + * @param {string | number} [valueIndex] + */ +function createIterator (name, kInternalIterator, keyIndex = 0, valueIndex = 1) { + class FastIterableIterator { + /** @type {any} */ + #target + /** @type {'key' | 'value' | 'key+value'} */ + #kind + /** @type {number} */ + #index - if (fragments.length === 1) { - // single fragment - this.#fragmentsBytes = 0 - return fragments.shift() + /** + * @see https://webidl.spec.whatwg.org/#dfn-default-iterator-object + * @param {unknown} target + * @param {'key' | 'value' | 'key+value'} kind + */ + constructor (target, kind) { + this.#target = target + this.#kind = kind + this.#index = 0 } - let offset = 0 - // If Buffer.allocUnsafe is used, extra copies will be made because the offset is non-zero. - const output = Buffer.allocUnsafeSlow(this.#fragmentsBytes) + next () { + // 1. Let interface be the interface for which the iterator prototype object exists. + // 2. Let thisValue be the this value. + // 3. Let object be ? ToObject(thisValue). + // 4. If object is a platform object, then perform a security + // check, passing: + // 5. If object is not a default iterator object for interface, + // then throw a TypeError. + if (typeof this !== 'object' || this === null || !(#target in this)) { + throw new TypeError( + `'next' called on an object that does not implement interface ${name} Iterator.` + ) + } - for (let i = 0; i < fragments.length; ++i) { - const buffer = fragments[i] - output.set(buffer, offset) - offset += buffer.length - } + // 6. Let index be object’s index. + // 7. Let kind be object’s kind. + // 8. Let values be object’s target's value pairs to iterate over. + const index = this.#index + const values = kInternalIterator(this.#target) - this.#fragments = [] - this.#fragmentsBytes = 0 + // 9. Let len be the length of values. + const len = values.length - return output - } + // 10. If index is greater than or equal to len, then return + // CreateIterResultObject(undefined, true). + if (index >= len) { + return { + value: undefined, + done: true + } + } - parseCloseBody (data) { - assert(data.length !== 1) + // 11. Let pair be the entry in values at index index. + const { [keyIndex]: key, [valueIndex]: value } = values[index] - // https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.5 - /** @type {number|undefined} */ - let code + // 12. Set object’s index to index + 1. + this.#index = index + 1 - if (data.length >= 2) { - // _The WebSocket Connection Close Code_ is - // defined as the status code (Section 7.4) contained in the first Close - // control frame received by the application - code = data.readUInt16BE(0) - } + // 13. Return the iterator result for pair and kind. - if (code !== undefined && !isValidStatusCode(code)) { - return { code: 1002, reason: 'Invalid status code', error: true } - } + // https://webidl.spec.whatwg.org/#iterator-result - // https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.6 - /** @type {Buffer} */ - let reason = data.subarray(2) + // 1. Let result be a value determined by the value of kind: + let result + switch (this.#kind) { + case 'key': + // 1. Let idlKey be pair’s key. + // 2. Let key be the result of converting idlKey to an + // ECMAScript value. + // 3. result is key. + result = key + break + case 'value': + // 1. Let idlValue be pair’s value. + // 2. Let value be the result of converting idlValue to + // an ECMAScript value. + // 3. result is value. + result = value + break + case 'key+value': + // 1. Let idlKey be pair’s key. + // 2. Let idlValue be pair’s value. + // 3. Let key be the result of converting idlKey to an + // ECMAScript value. + // 4. Let value be the result of converting idlValue to + // an ECMAScript value. + // 5. Let array be ! ArrayCreate(2). + // 6. Call ! CreateDataProperty(array, "0", key). + // 7. Call ! CreateDataProperty(array, "1", value). + // 8. result is array. + result = [key, value] + break + } - // Remove BOM - if (reason[0] === 0xEF && reason[1] === 0xBB && reason[2] === 0xBF) { - reason = reason.subarray(3) + // 2. Return CreateIterResultObject(result, false). + return { + value: result, + done: false + } } + } - try { - reason = utf8Decode(reason) - } catch { - return { code: 1007, reason: 'Invalid UTF-8', error: true } - } + // https://webidl.spec.whatwg.org/#dfn-iterator-prototype-object + // @ts-ignore + delete FastIterableIterator.prototype.constructor - return { code, reason, error: false } - } + Object.setPrototypeOf(FastIterableIterator.prototype, esIteratorPrototype) + + Object.defineProperties(FastIterableIterator.prototype, { + [Symbol.toStringTag]: { + writable: false, + enumerable: false, + configurable: true, + value: `${name} Iterator` + }, + next: { writable: true, enumerable: true, configurable: true } + }) /** - * Parses control frames. - * @param {Buffer} body + * @param {unknown} target + * @param {'key' | 'value' | 'key+value'} kind + * @returns {IterableIterator} */ - parseControlFrame (body) { - const { opcode, payloadLength } = this.#info - - if (opcode === opcodes.CLOSE) { - if (payloadLength === 1) { - failWebsocketConnection(this.#handler, 1002, 'Received close frame with a 1-byte body.') - return false - } - - this.#info.closeInfo = this.parseCloseBody(body) + return function (target, kind) { + return new FastIterableIterator(target, kind) + } +} - if (this.#info.closeInfo.error) { - const { code, reason } = this.#info.closeInfo +/** + * @see https://webidl.spec.whatwg.org/#dfn-iterator-prototype-object + * @param {string} name name of the instance + * @param {any} object class + * @param {(target: any) => any} kInternalIterator + * @param {string | number} [keyIndex] + * @param {string | number} [valueIndex] + */ +function iteratorMixin (name, object, kInternalIterator, keyIndex = 0, valueIndex = 1) { + const makeIterator = createIterator(name, kInternalIterator, keyIndex, valueIndex) - failWebsocketConnection(this.#handler, code, reason) - return false + const properties = { + keys: { + writable: true, + enumerable: true, + configurable: true, + value: function keys () { + webidl.brandCheck(this, object) + return makeIterator(this, 'key') } - - // Upon receiving such a frame, the other peer sends a - // Close frame in response, if it hasn't already sent one. - if (!this.#handler.closeState.has(sentCloseFrameState.SENT) && !this.#handler.closeState.has(sentCloseFrameState.RECEIVED)) { - // If an endpoint receives a Close frame and did not previously send a - // Close frame, the endpoint MUST send a Close frame in response. (When - // sending a Close frame in response, the endpoint typically echos the - // status code it received.) - let body = emptyBuffer - if (this.#info.closeInfo.code) { - body = Buffer.allocUnsafe(2) - body.writeUInt16BE(this.#info.closeInfo.code, 0) + }, + values: { + writable: true, + enumerable: true, + configurable: true, + value: function values () { + webidl.brandCheck(this, object) + return makeIterator(this, 'value') + } + }, + entries: { + writable: true, + enumerable: true, + configurable: true, + value: function entries () { + webidl.brandCheck(this, object) + return makeIterator(this, 'key+value') + } + }, + forEach: { + writable: true, + enumerable: true, + configurable: true, + value: function forEach (callbackfn, thisArg = globalThis) { + webidl.brandCheck(this, object) + webidl.argumentLengthCheck(arguments, 1, `${name}.forEach`) + if (typeof callbackfn !== 'function') { + throw new TypeError( + `Failed to execute 'forEach' on '${name}': parameter 1 is not of type 'Function'.` + ) + } + for (const { 0: key, 1: value } of makeIterator(this, 'key+value')) { + callbackfn.call(thisArg, value, key, this) } - const closeFrame = new WebsocketFrameSend(body) - - this.#handler.socket.write(closeFrame.createFrame(opcodes.CLOSE)) - this.#handler.closeState.add(sentCloseFrameState.SENT) } + } + } - // Upon either sending or receiving a Close control frame, it is said - // that _The WebSocket Closing Handshake is Started_ and that the - // WebSocket connection is in the CLOSING state. - this.#handler.readyState = states.CLOSING - this.#handler.closeState.add(sentCloseFrameState.RECEIVED) - - return false - } else if (opcode === opcodes.PING) { - // Upon receipt of a Ping frame, an endpoint MUST send a Pong frame in - // response, unless it already received a Close frame. - // A Pong frame sent in response to a Ping frame must have identical - // "Application data" + return Object.defineProperties(object.prototype, { + ...properties, + [Symbol.iterator]: { + writable: true, + enumerable: false, + configurable: true, + value: properties.entries.value + } + }) +} - if (!this.#handler.closeState.has(sentCloseFrameState.RECEIVED)) { - const frame = new WebsocketFrameSend(body) +/** + * @param {import('./body').ExtractBodyResult} body + * @param {(bytes: Uint8Array) => void} processBody + * @param {(error: Error) => void} processBodyError + * @returns {void} + * + * @see https://fetch.spec.whatwg.org/#body-fully-read + */ +function fullyReadBody (body, processBody, processBodyError) { + // 1. If taskDestination is null, then set taskDestination to + // the result of starting a new parallel queue. - this.#handler.socket.write(frame.createFrame(opcodes.PONG)) + // 2. Let successSteps given a byte sequence bytes be to queue a + // fetch task to run processBody given bytes, with taskDestination. + const successSteps = processBody - this.#handler.onPing(body) - } - } else if (opcode === opcodes.PONG) { - // A Pong frame MAY be sent unsolicited. This serves as a - // unidirectional heartbeat. A response to an unsolicited Pong frame is - // not expected. - this.#handler.onPong(body) - } + // 3. Let errorSteps be to queue a fetch task to run processBodyError, + // with taskDestination. + const errorSteps = processBodyError - return true - } + try { + // 4. Let reader be the result of getting a reader for body’s stream. + // If that threw an exception, then run errorSteps with that + // exception and return. + const reader = body.stream.getReader() - get closingInfo () { - return this.#info.closeInfo + // 5. Read all bytes from reader, given successSteps and errorSteps. + readAllBytes(reader, successSteps, errorSteps) + } catch (e) { + errorSteps(e) } } -module.exports = { - ByteParser +/** + * @param {ReadableStreamController} controller + */ +function readableStreamClose (controller) { + try { + controller.close() + controller.byobRequest?.respond(0) + } catch (err) { + // TODO: add comment explaining why this error occurs. + if (!err.message.includes('Controller is already closed') && !err.message.includes('ReadableStream is already closed')) { + throw err + } + } } +/** + * @see https://streams.spec.whatwg.org/#readablestreamdefaultreader-read-all-bytes + * @see https://streams.spec.whatwg.org/#read-loop + * @param {ReadableStream>} reader + * @param {(bytes: Uint8Array) => void} successSteps + * @param {(error: Error) => void} failureSteps + * @returns {Promise} + */ +async function readAllBytes (reader, successSteps, failureSteps) { + try { + const bytes = [] + let byteLength = 0 -/***/ }), + do { + const { done, value: chunk } = await reader.read() -/***/ 1217: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + if (done) { + // 1. Call successSteps with bytes. + successSteps(Buffer.concat(bytes, byteLength)) + return + } -"use strict"; + // 1. If chunk is not a Uint8Array object, call failureSteps + // with a TypeError and abort these steps. + if (!isUint8Array(chunk)) { + failureSteps(new TypeError('Received non-Uint8Array chunk')) + return + } + // 2. Append the bytes represented by chunk to bytes. + bytes.push(chunk) + byteLength += chunk.length -const { WebsocketFrameSend } = __nccwpck_require__(2647) -const { opcodes, sendHints } = __nccwpck_require__(163) -const FixedQueue = __nccwpck_require__(6677) + // 3. Read-loop given reader, bytes, successSteps, and failureSteps. + } while (true) + } catch (e) { + // 1. Call failureSteps with e. + failureSteps(e) + } +} /** - * @typedef {object} SendQueueNode - * @property {Promise | null} promise - * @property {((...args: any[]) => any)} callback - * @property {Buffer | null} frame + * @see https://fetch.spec.whatwg.org/#is-local + * @param {URL} url + * @returns {boolean} */ +function urlIsLocal (url) { + assert('protocol' in url) // ensure it's a url object -class SendQueue { - /** - * @type {FixedQueue} - */ - #queue = new FixedQueue() + const protocol = url.protocol - /** - * @type {boolean} - */ - #running = false + // A URL is local if its scheme is a local scheme. + // A local scheme is "about", "blob", or "data". + return protocol === 'about:' || protocol === 'blob:' || protocol === 'data:' +} - /** @type {import('node:net').Socket} */ - #socket +/** + * @param {string|URL} url + * @returns {boolean} + */ +function urlHasHttpsScheme (url) { + return ( + ( + typeof url === 'string' && + url[5] === ':' && + url[0] === 'h' && + url[1] === 't' && + url[2] === 't' && + url[3] === 'p' && + url[4] === 's' + ) || + url.protocol === 'https:' + ) +} - constructor (socket) { - this.#socket = socket - } +/** + * @see https://fetch.spec.whatwg.org/#http-scheme + * @param {URL} url + */ +function urlIsHttpHttpsScheme (url) { + assert('protocol' in url) // ensure it's a url object - add (item, cb, hint) { - if (hint !== sendHints.blob) { - if (!this.#running) { - // TODO(@tsctx): support fast-path for string on running - if (hint === sendHints.text) { - // special fast-path for string - const { 0: head, 1: body } = WebsocketFrameSend.createFastTextFrame(item) - this.#socket.cork() - this.#socket.write(head) - this.#socket.write(body, cb) - this.#socket.uncork() - } else { - // direct writing - this.#socket.write(createFrame(item, hint), cb) - } - } else { - /** @type {SendQueueNode} */ - const node = { - promise: null, - callback: cb, - frame: createFrame(item, hint) - } - this.#queue.push(node) - } - return - } + const protocol = url.protocol - /** @type {SendQueueNode} */ - const node = { - promise: item.arrayBuffer().then((ab) => { - node.promise = null - node.frame = createFrame(ab, hint) - }), - callback: cb, - frame: null - } + return protocol === 'http:' || protocol === 'https:' +} - this.#queue.push(node) +/** + * @typedef {Object} RangeHeaderValue + * @property {number|null} rangeStartValue + * @property {number|null} rangeEndValue + */ - if (!this.#running) { - this.#run() - } - } +/** + * @see https://fetch.spec.whatwg.org/#simple-range-header-value + * @param {string} value + * @param {boolean} allowWhitespace + * @return {RangeHeaderValue|'failure'} + */ +function simpleRangeHeaderValue (value, allowWhitespace) { + // 1. Let data be the isomorphic decoding of value. + // Note: isomorphic decoding takes a sequence of bytes (ie. a Uint8Array) and turns it into a string, + // nothing more. We obviously don't need to do that if value is a string already. + const data = value - async #run () { - this.#running = true - const queue = this.#queue - while (!queue.isEmpty()) { - const node = queue.shift() - // wait pending promise - if (node.promise !== null) { - await node.promise - } - // write - this.#socket.write(node.frame, node.callback) - // cleanup - node.callback = node.frame = null - } - this.#running = false + // 2. If data does not start with "bytes", then return failure. + if (!data.startsWith('bytes')) { + return 'failure' } -} -function createFrame (data, hint) { - return new WebsocketFrameSend(toBuffer(data, hint)).createFrame(hint === sendHints.text ? opcodes.TEXT : opcodes.BINARY) -} + // 3. Let position be a position variable for data, initially pointing at the 5th code point of data. + const position = { position: 5 } -function toBuffer (data, hint) { - switch (hint) { - case sendHints.text: - case sendHints.typedArray: - return new Uint8Array(data.buffer, data.byteOffset, data.byteLength) - case sendHints.arrayBuffer: - case sendHints.blob: - return new Uint8Array(data) + // 4. If allowWhitespace is true, collect a sequence of code points that are HTTP tab or space, + // from data given position. + if (allowWhitespace) { + collectASequenceOfCodePoints( + (char) => char === '\t' || char === ' ', + data, + position + ) } -} - -module.exports = { SendQueue } + // 5. If the code point at position within data is not U+003D (=), then return failure. + if (data.charCodeAt(position.position) !== 0x3D) { + return 'failure' + } -/***/ }), + // 6. Advance position by 1. + position.position++ -/***/ 9536: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // 7. If allowWhitespace is true, collect a sequence of code points that are HTTP tab or space, from + // data given position. + if (allowWhitespace) { + collectASequenceOfCodePoints( + (char) => char === '\t' || char === ' ', + data, + position + ) + } -"use strict"; + // 8. Let rangeStart be the result of collecting a sequence of code points that are ASCII digits, + // from data given position. + const rangeStart = collectASequenceOfCodePoints( + (char) => { + const code = char.charCodeAt(0) + return code >= 0x30 && code <= 0x39 + }, + data, + position + ) -const { webidl } = __nccwpck_require__(2318) -const { validateCloseCodeAndReason } = __nccwpck_require__(7484) -const { kConstruct } = __nccwpck_require__(9562) -const { kEnumerableProperty } = __nccwpck_require__(983) + // 9. Let rangeStartValue be rangeStart, interpreted as decimal number, if rangeStart is not the + // empty string; otherwise null. + const rangeStartValue = rangeStart.length ? Number(rangeStart) : null -function createInheritableDOMException () { - // https://github.com/nodejs/node/issues/59677 - class Test extends DOMException { - get reason () { - return '' - } + // 10. If allowWhitespace is true, collect a sequence of code points that are HTTP tab or space, + // from data given position. + if (allowWhitespace) { + collectASequenceOfCodePoints( + (char) => char === '\t' || char === ' ', + data, + position + ) } - if (new Test().reason !== undefined) { - return DOMException + // 11. If the code point at position within data is not U+002D (-), then return failure. + if (data.charCodeAt(position.position) !== 0x2D) { + return 'failure' } - return new Proxy(DOMException, { - construct (target, args, newTarget) { - const instance = Reflect.construct(target, args, target) - Object.setPrototypeOf(instance, newTarget.prototype) - return instance - } - }) -} - -class WebSocketError extends createInheritableDOMException() { - #closeCode - #reason - - constructor (message = '', init = undefined) { - message = webidl.converters.DOMString(message, 'WebSocketError', 'message') - - // 1. Set this 's name to " WebSocketError ". - // 2. Set this 's message to message . - super(message, 'WebSocketError') - - if (init === kConstruct) { - return - } else if (init !== null) { - init = webidl.converters.WebSocketCloseInfo(init) - } - - // 3. Let code be init [" closeCode "] if it exists , or null otherwise. - let code = init.closeCode ?? null + // 12. Advance position by 1. + position.position++ - // 4. Let reason be init [" reason "] if it exists , or the empty string otherwise. - const reason = init.reason ?? '' + // 13. If allowWhitespace is true, collect a sequence of code points that are HTTP tab + // or space, from data given position. + // Note from Khafra: its the same step as in #8 again lol + if (allowWhitespace) { + collectASequenceOfCodePoints( + (char) => char === '\t' || char === ' ', + data, + position + ) + } - // 5. Validate close code and reason with code and reason . - validateCloseCodeAndReason(code, reason) + // 14. Let rangeEnd be the result of collecting a sequence of code points that are + // ASCII digits, from data given position. + // Note from Khafra: you wouldn't guess it, but this is also the same step as #8 + const rangeEnd = collectASequenceOfCodePoints( + (char) => { + const code = char.charCodeAt(0) - // 6. If reason is non-empty, but code is not set, then set code to 1000 ("Normal Closure"). - if (reason.length !== 0 && code === null) { - code = 1000 - } + return code >= 0x30 && code <= 0x39 + }, + data, + position + ) - // 7. Set this 's closeCode to code . - this.#closeCode = code + // 15. Let rangeEndValue be rangeEnd, interpreted as decimal number, if rangeEnd + // is not the empty string; otherwise null. + // Note from Khafra: THE SAME STEP, AGAIN!!! + // Note: why interpret as a decimal if we only collect ascii digits? + const rangeEndValue = rangeEnd.length ? Number(rangeEnd) : null - // 8. Set this 's reason to reason . - this.#reason = reason + // 16. If position is not past the end of data, then return failure. + if (position.position < data.length) { + return 'failure' } - get closeCode () { - return this.#closeCode + // 17. If rangeEndValue and rangeStartValue are null, then return failure. + if (rangeEndValue === null && rangeStartValue === null) { + return 'failure' } - get reason () { - return this.#reason + // 18. If rangeStartValue and rangeEndValue are numbers, and rangeStartValue is + // greater than rangeEndValue, then return failure. + // Note: ... when can they not be numbers? + if (rangeStartValue > rangeEndValue) { + return 'failure' } - /** - * @param {string} message - * @param {number|null} code - * @param {string} reason - */ - static createUnvalidatedWebSocketError (message, code, reason) { - const error = new WebSocketError(message, kConstruct) - error.#closeCode = code - error.#reason = reason - return error - } + // 19. Return (rangeStartValue, rangeEndValue). + return { rangeStartValue, rangeEndValue } } -const { createUnvalidatedWebSocketError } = WebSocketError -delete WebSocketError.createUnvalidatedWebSocketError - -Object.defineProperties(WebSocketError.prototype, { - closeCode: kEnumerableProperty, - reason: kEnumerableProperty, - [Symbol.toStringTag]: { - value: 'WebSocketError', - writable: false, - enumerable: false, - configurable: true - } -}) - -webidl.is.WebSocketError = webidl.util.MakeTypeAssertion(WebSocketError) +/** + * @see https://fetch.spec.whatwg.org/#build-a-content-range + * @param {number} rangeStart + * @param {number} rangeEnd + * @param {number} fullLength + */ +function buildContentRange (rangeStart, rangeEnd, fullLength) { + // 1. Let contentRange be `bytes `. + let contentRange = 'bytes ' -module.exports = { WebSocketError, createUnvalidatedWebSocketError } + // 2. Append rangeStart, serialized and isomorphic encoded, to contentRange. + contentRange += isomorphicEncode(`${rangeStart}`) + // 3. Append 0x2D (-) to contentRange. + contentRange += '-' -/***/ }), + // 4. Append rangeEnd, serialized and isomorphic encoded to contentRange. + contentRange += isomorphicEncode(`${rangeEnd}`) -/***/ 3056: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // 5. Append 0x2F (/) to contentRange. + contentRange += '/' -"use strict"; + // 6. Append fullLength, serialized and isomorphic encoded to contentRange. + contentRange += isomorphicEncode(`${fullLength}`) + // 7. Return contentRange. + return contentRange +} -const { createDeferredPromise } = __nccwpck_require__(9797) -const { environmentSettingsObject } = __nccwpck_require__(8913) -const { states, opcodes, sentCloseFrameState } = __nccwpck_require__(163) -const { webidl } = __nccwpck_require__(2318) -const { getURLRecord, isValidSubprotocol, isEstablished, utf8Decode } = __nccwpck_require__(7484) -const { establishWebSocketConnection, failWebsocketConnection, closeWebSocketConnection } = __nccwpck_require__(9136) -const { channels } = __nccwpck_require__(6591) -const { WebsocketFrameSend } = __nccwpck_require__(2647) -const { ByteParser } = __nccwpck_require__(7713) -const { WebSocketError, createUnvalidatedWebSocketError } = __nccwpck_require__(9536) -const { kEnumerableProperty } = __nccwpck_require__(983) -const { utf8DecodeBytes } = __nccwpck_require__(9825) +// A Stream, which pipes the response to zlib.createInflate() or +// zlib.createInflateRaw() depending on the first byte of the Buffer. +// If the lower byte of the first byte is 0x08, then the stream is +// interpreted as a zlib stream, otherwise it's interpreted as a +// raw deflate stream. +class InflateStream extends Transform { + #zlibOptions -let emittedExperimentalWarning = false + /** @param {zlib.ZlibOptions} [zlibOptions] */ + constructor (zlibOptions) { + super() + this.#zlibOptions = zlibOptions + } -class WebSocketStream { - // Each WebSocketStream object has an associated url , which is a URL record . - /** @type {URL} */ - #url + _transform (chunk, encoding, callback) { + if (!this._inflateStream) { + if (chunk.length === 0) { + callback() + return + } + this._inflateStream = (chunk[0] & 0x0F) === 0x08 + ? zlib.createInflate(this.#zlibOptions) + : zlib.createInflateRaw(this.#zlibOptions) - // Each WebSocketStream object has an associated opened promise , which is a promise. - /** @type {import('../../../util/promise').DeferredPromise} */ - #openedPromise + this._inflateStream.on('data', this.push.bind(this)) + this._inflateStream.on('end', () => this.push(null)) + this._inflateStream.on('error', (err) => this.destroy(err)) + } - // Each WebSocketStream object has an associated closed promise , which is a promise. - /** @type {import('../../../util/promise').DeferredPromise} */ - #closedPromise + this._inflateStream.write(chunk, encoding, callback) + } - // Each WebSocketStream object has an associated readable stream , which is a ReadableStream . - /** @type {ReadableStream} */ - #readableStream - /** @type {ReadableStreamDefaultController} */ - #readableStreamController + _final (callback) { + if (this._inflateStream) { + this._inflateStream.end() + this._inflateStream = null + } + callback() + } +} - // Each WebSocketStream object has an associated writable stream , which is a WritableStream . - /** @type {WritableStream} */ - #writableStream +/** + * @param {zlib.ZlibOptions} [zlibOptions] + * @returns {InflateStream} + */ +function createInflate (zlibOptions) { + return new InflateStream(zlibOptions) +} - // Each WebSocketStream object has an associated boolean handshake aborted , which is initially false. - #handshakeAborted = false +/** + * @see https://fetch.spec.whatwg.org/#concept-header-extract-mime-type + * @param {import('./headers').HeadersList} headers + */ +function extractMimeType (headers) { + // 1. Let charset be null. + let charset = null - /** @type {import('../websocket').Handler} */ - #handler = { - // https://whatpr.org/websockets/48/7b748d3...d5570f3.html#feedback-to-websocket-stream-from-the-protocol - onConnectionEstablished: (response, extensions) => this.#onConnectionEstablished(response, extensions), - onMessage: (opcode, data) => this.#onMessage(opcode, data), - onParserError: (err) => failWebsocketConnection(this.#handler, null, err.message), - onParserDrain: () => this.#handler.socket.resume(), - onSocketData: (chunk) => { - if (!this.#parser.write(chunk)) { - this.#handler.socket.pause() - } - }, - onSocketError: (err) => { - this.#handler.readyState = states.CLOSING + // 2. Let essence be null. + let essence = null - if (channels.socketError.hasSubscribers) { - channels.socketError.publish(err) - } + // 3. Let mimeType be null. + let mimeType = null - this.#handler.socket.destroy() - }, - onSocketClose: () => this.#onSocketClose(), - onPing: () => {}, - onPong: () => {}, + // 4. Let values be the result of getting, decoding, and splitting `Content-Type` from headers. + const values = getDecodeSplit('content-type', headers) - readyState: states.CONNECTING, - socket: null, - closeState: new Set(), - controller: null, - wasEverConnected: false + // 5. If values is null, then return failure. + if (values === null) { + return 'failure' } - /** @type {import('../receiver').ByteParser} */ - #parser - - constructor (url, options = undefined) { - if (!emittedExperimentalWarning) { - process.emitWarning('WebSocketStream is experimental! Expect it to change at any time.', { - code: 'UNDICI-WSS' - }) - emittedExperimentalWarning = true - } - - webidl.argumentLengthCheck(arguments, 1, 'WebSocket') + // 6. For each value of values: + for (const value of values) { + // 6.1. Let temporaryMimeType be the result of parsing value. + const temporaryMimeType = parseMIMEType(value) - url = webidl.converters.USVString(url) - if (options !== null) { - options = webidl.converters.WebSocketStreamOptions(options) + // 6.2. If temporaryMimeType is failure or its essence is "*/*", then continue. + if (temporaryMimeType === 'failure' || temporaryMimeType.essence === '*/*') { + continue } - // 1. Let baseURL be this 's relevant settings object 's API base URL . - const baseURL = environmentSettingsObject.settingsObject.baseUrl - - // 2. Let urlRecord be the result of getting a URL record given url and baseURL . - const urlRecord = getURLRecord(url, baseURL) + // 6.3. Set mimeType to temporaryMimeType. + mimeType = temporaryMimeType - // 3. Let protocols be options [" protocols "] if it exists , otherwise an empty sequence. - const protocols = options.protocols + // 6.4. If mimeType’s essence is not essence, then: + if (mimeType.essence !== essence) { + // 6.4.1. Set charset to null. + charset = null - // 4. If any of the values in protocols occur more than once or otherwise fail to match the requirements for elements that comprise the value of ` Sec-WebSocket-Protocol ` fields as defined by The WebSocket Protocol , then throw a " SyntaxError " DOMException . [WSP] - if (protocols.length !== new Set(protocols.map(p => p.toLowerCase())).size) { - throw new DOMException('Invalid Sec-WebSocket-Protocol value', 'SyntaxError') - } + // 6.4.2. If mimeType’s parameters["charset"] exists, then set charset to + // mimeType’s parameters["charset"]. + if (mimeType.parameters.has('charset')) { + charset = mimeType.parameters.get('charset') + } - if (protocols.length > 0 && !protocols.every(p => isValidSubprotocol(p))) { - throw new DOMException('Invalid Sec-WebSocket-Protocol value', 'SyntaxError') + // 6.4.3. Set essence to mimeType’s essence. + essence = mimeType.essence + } else if (!mimeType.parameters.has('charset') && charset !== null) { + // 6.5. Otherwise, if mimeType’s parameters["charset"] does not exist, and + // charset is non-null, set mimeType’s parameters["charset"] to charset. + mimeType.parameters.set('charset', charset) } + } - // 5. Set this 's url to urlRecord . - this.#url = urlRecord.toString() - - // 6. Set this 's opened promise and closed promise to new promises. - this.#openedPromise = createDeferredPromise() - this.#closedPromise = createDeferredPromise() + // 7. If mimeType is null, then return failure. + if (mimeType == null) { + return 'failure' + } - // 7. Apply backpressure to the WebSocket. - // TODO + // 8. Return mimeType. + return mimeType +} - // 8. If options [" signal "] exists , - if (options.signal != null) { - // 8.1. Let signal be options [" signal "]. - const signal = options.signal - - // 8.2. If signal is aborted , then reject this 's opened promise and closed promise with signal ’s abort reason - // and return. - if (signal.aborted) { - this.#openedPromise.reject(signal.reason) - this.#closedPromise.reject(signal.reason) - return - } - - // 8.3. Add the following abort steps to signal : - signal.addEventListener('abort', () => { - // 8.3.1. If the WebSocket connection is not yet established : [WSP] - if (!isEstablished(this.#handler.readyState)) { - // 8.3.1.1. Fail the WebSocket connection . - failWebsocketConnection(this.#handler) - - // Set this 's ready state to CLOSING . - this.#handler.readyState = states.CLOSING +/** + * @see https://fetch.spec.whatwg.org/#header-value-get-decode-and-split + * @param {string|null} value + */ +function gettingDecodingSplitting (value) { + // 1. Let input be the result of isomorphic decoding value. + const input = value - // Reject this 's opened promise and closed promise with signal ’s abort reason . - this.#openedPromise.reject(signal.reason) - this.#closedPromise.reject(signal.reason) + // 2. Let position be a position variable for input, initially pointing at the start of input. + const position = { position: 0 } - // Set this 's handshake aborted to true. - this.#handshakeAborted = true - } - }, { once: true }) - } + // 3. Let values be a list of strings, initially empty. + const values = [] - // 9. Let client be this 's relevant settings object . - const client = environmentSettingsObject.settingsObject + // 4. Let temporaryValue be the empty string. + let temporaryValue = '' - // 10. Run this step in parallel : - // 10.1. Establish a WebSocket connection given urlRecord , protocols , and client . [FETCH] - this.#handler.controller = establishWebSocketConnection( - urlRecord, - protocols, - client, - this.#handler, - options + // 5. While position is not past the end of input: + while (position.position < input.length) { + // 5.1. Append the result of collecting a sequence of code points that are not U+0022 (") + // or U+002C (,) from input, given position, to temporaryValue. + temporaryValue += collectASequenceOfCodePoints( + (char) => char !== '"' && char !== ',', + input, + position ) - } - // The url getter steps are to return this 's url , serialized . - get url () { - return this.#url.toString() - } + // 5.2. If position is not past the end of input, then: + if (position.position < input.length) { + // 5.2.1. If the code point at position within input is U+0022 ("), then: + if (input.charCodeAt(position.position) === 0x22) { + // 5.2.1.1. Append the result of collecting an HTTP quoted string from input, given position, to temporaryValue. + temporaryValue += collectAnHTTPQuotedString( + input, + position + ) - // The opened getter steps are to return this 's opened promise . - get opened () { - return this.#openedPromise.promise - } + // 5.2.1.2. If position is not past the end of input, then continue. + if (position.position < input.length) { + continue + } + } else { + // 5.2.2. Otherwise: - // The closed getter steps are to return this 's closed promise . - get closed () { - return this.#closedPromise.promise - } + // 5.2.2.1. Assert: the code point at position within input is U+002C (,). + assert(input.charCodeAt(position.position) === 0x2C) - // The close( closeInfo ) method steps are: - close (closeInfo = undefined) { - if (closeInfo !== null) { - closeInfo = webidl.converters.WebSocketCloseInfo(closeInfo) + // 5.2.2.2. Advance position by 1. + position.position++ + } } - // 1. Let code be closeInfo [" closeCode "] if present, or null otherwise. - const code = closeInfo.closeCode ?? null + // 5.3. Remove all HTTP tab or space from the start and end of temporaryValue. + temporaryValue = removeChars(temporaryValue, true, true, (char) => char === 0x9 || char === 0x20) - // 2. Let reason be closeInfo [" reason "]. - const reason = closeInfo.reason + // 5.4. Append temporaryValue to values. + values.push(temporaryValue) - // 3. Close the WebSocket with this , code , and reason . - closeWebSocketConnection(this.#handler, code, reason, true) + // 5.6. Set temporaryValue to the empty string. + temporaryValue = '' } - #write (chunk) { - // See /websockets/stream/tentative/write.any.html - chunk = webidl.converters.WebSocketStreamWrite(chunk) - - // 1. Let promise be a new promise created in stream ’s relevant realm . - const promise = createDeferredPromise() + // 6. Return values. + return values +} - // 2. Let data be null. - let data = null +/** + * @see https://fetch.spec.whatwg.org/#concept-header-list-get-decode-split + * @param {string} name lowercase header name + * @param {import('./headers').HeadersList} list + */ +function getDecodeSplit (name, list) { + // 1. Let value be the result of getting name from list. + const value = list.get(name, true) - // 3. Let opcode be null. - let opcode = null + // 2. If value is null, then return null. + if (value === null) { + return null + } - // 4. If chunk is a BufferSource , - if (webidl.is.BufferSource(chunk)) { - // 4.1. Set data to a copy of the bytes given chunk . - data = new Uint8Array(ArrayBuffer.isView(chunk) ? new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength) : chunk.slice()) + // 3. Return the result of getting, decoding, and splitting value. + return gettingDecodingSplitting(value) +} - // 4.2. Set opcode to a binary frame opcode. - opcode = opcodes.BINARY - } else { - // 5. Otherwise, +function hasAuthenticationEntry (request) { + return false +} - // 5.1. Let string be the result of converting chunk to an IDL USVString . - // If this throws an exception, return a promise rejected with the exception. - let string +/** + * @see https://url.spec.whatwg.org/#include-credentials + * @param {URL} url + */ +function includesCredentials (url) { + // A URL includes credentials if its username or password is not the empty string. + return !!(url.username && url.password) +} - try { - string = webidl.converters.DOMString(chunk) - } catch (e) { - promise.reject(e) - return promise.promise - } +/** + * @see https://html.spec.whatwg.org/multipage/document-sequences.html#traversable-navigable + * @param {object|string} navigable + */ +function isTraversableNavigable (navigable) { + // TODO + return true +} - // 5.2. Set data to the result of UTF-8 encoding string . - data = new TextEncoder().encode(string) +class EnvironmentSettingsObjectBase { + get baseUrl () { + return getGlobalOrigin() + } - // 5.3. Set opcode to a text frame opcode. - opcode = opcodes.TEXT - } + get origin () { + return this.baseUrl?.origin + } - // 6. In parallel, - // 6.1. Wait until there is sufficient buffer space in stream to send the message. + policyContainer = makePolicyContainer() +} - // 6.2. If the closing handshake has not yet started , Send a WebSocket Message to stream comprised of data using opcode . - if (!this.#handler.closeState.has(sentCloseFrameState.SENT) && !this.#handler.closeState.has(sentCloseFrameState.RECEIVED)) { - const frame = new WebsocketFrameSend(data) +class EnvironmentSettingsObject { + settingsObject = new EnvironmentSettingsObjectBase() +} - this.#handler.socket.write(frame.createFrame(opcode), () => { - promise.resolve(undefined) - }) - } +const environmentSettingsObject = new EnvironmentSettingsObject() - // 6.3. Queue a global task on the WebSocket task source given stream ’s relevant global object to resolve promise with undefined. - return promise.promise - } +module.exports = { + isAborted, + isCancelled, + isValidEncodedURL, + ReadableStreamFrom, + tryUpgradeRequestToAPotentiallyTrustworthyURL, + clampAndCoarsenConnectionTimingInfo, + coarsenedSharedCurrentTime, + determineRequestsReferrer, + makePolicyContainer, + clonePolicyContainer, + appendFetchMetadata, + appendRequestOriginHeader, + TAOCheck, + corsCheck, + crossOriginResourcePolicyCheck, + createOpaqueTimingInfo, + setRequestReferrerPolicyOnRedirect, + isValidHTTPToken, + requestBadPort, + requestCurrentURL, + responseURL, + responseLocationURL, + isURLPotentiallyTrustworthy, + isValidReasonPhrase, + sameOrigin, + normalizeMethod, + iteratorMixin, + createIterator, + isValidHeaderName, + isValidHeaderValue, + isErrorLike, + fullyReadBody, + readableStreamClose, + urlIsLocal, + urlHasHttpsScheme, + urlIsHttpHttpsScheme, + readAllBytes, + simpleRangeHeaderValue, + buildContentRange, + createInflate, + extractMimeType, + getDecodeSplit, + environmentSettingsObject, + isOriginIPPotentiallyTrustworthy, + hasAuthenticationEntry, + includesCredentials, + isTraversableNavigable +} - /** @type {import('../websocket').Handler['onConnectionEstablished']} */ - #onConnectionEstablished (response, parsedExtensions) { - this.#handler.socket = response.socket - const parser = new ByteParser(this.#handler, parsedExtensions) - parser.on('drain', () => this.#handler.onParserDrain()) - parser.on('error', (err) => this.#handler.onParserError(err)) +/***/ }), - this.#parser = parser +/***/ 5074: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - // 1. Change stream ’s ready state to OPEN (1). - this.#handler.readyState = states.OPEN - // 2. Set stream ’s was ever connected to true. - // This is done in the opening handshake. - // 3. Let extensions be the extensions in use . - const extensions = parsedExtensions ?? '' +const assert = __nccwpck_require__(4589) +const { utf8DecodeBytes } = __nccwpck_require__(6546) - // 4. Let protocol be the subprotocol in use . - const protocol = response.headersList.get('sec-websocket-protocol') ?? '' +/** + * @param {(char: string) => boolean} condition + * @param {string} input + * @param {{ position: number }} position + * @returns {string} + * + * @see https://infra.spec.whatwg.org/#collect-a-sequence-of-code-points + */ +function collectASequenceOfCodePoints (condition, input, position) { + // 1. Let result be the empty string. + let result = '' - // 5. Let pullAlgorithm be an action that pulls bytes from stream . - // 6. Let cancelAlgorithm be an action that cancels stream with reason , given reason . - // 7. Let readable be a new ReadableStream . - // 8. Set up readable with pullAlgorithm and cancelAlgorithm . - const readable = new ReadableStream({ - start: (controller) => { - this.#readableStreamController = controller - }, - pull (controller) { - let chunk - while (controller.desiredSize > 0 && (chunk = response.socket.read()) !== null) { - controller.enqueue(chunk) - } - }, - cancel: (reason) => this.#cancel(reason) - }) + // 2. While position doesn’t point past the end of input and the + // code point at position within input meets the condition condition: + while (position.position < input.length && condition(input[position.position])) { + // 1. Append that code point to the end of result. + result += input[position.position] - // 9. Let writeAlgorithm be an action that writes chunk to stream , given chunk . - // 10. Let closeAlgorithm be an action that closes stream . - // 11. Let abortAlgorithm be an action that aborts stream with reason , given reason . - // 12. Let writable be a new WritableStream . - // 13. Set up writable with writeAlgorithm , closeAlgorithm , and abortAlgorithm . - const writable = new WritableStream({ - write: (chunk) => this.#write(chunk), - close: () => closeWebSocketConnection(this.#handler, null, null), - abort: (reason) => this.#closeUsingReason(reason) - }) + // 2. Advance position by 1. + position.position++ + } - // Set stream ’s readable stream to readable . - this.#readableStream = readable + // 3. Return result. + return result +} - // Set stream ’s writable stream to writable . - this.#writableStream = writable +/** + * A faster collectASequenceOfCodePoints that only works when comparing a single character. + * @param {string} char + * @param {string} input + * @param {{ position: number }} position + * @returns {string} + * + * @see https://infra.spec.whatwg.org/#collect-a-sequence-of-code-points + */ +function collectASequenceOfCodePointsFast (char, input, position) { + const idx = input.indexOf(char, position.position) + const start = position.position - // Resolve stream ’s opened promise with WebSocketOpenInfo «[ " extensions " → extensions , " protocol " → protocol , " readable " → readable , " writable " → writable ]». - this.#openedPromise.resolve({ - extensions, - protocol, - readable, - writable - }) + if (idx === -1) { + position.position = input.length + return input.slice(start) } - /** @type {import('../websocket').Handler['onMessage']} */ - #onMessage (type, data) { - // 1. If stream’s ready state is not OPEN (1), then return. - if (this.#handler.readyState !== states.OPEN) { - return - } + position.position = idx + return input.slice(start, position.position) +} - // 2. Let chunk be determined by switching on type: - // - type indicates that the data is Text - // a new DOMString containing data - // - type indicates that the data is Binary - // a new Uint8Array object, created in the relevant Realm of the - // WebSocketStream object, whose contents are data - let chunk +const ASCII_WHITESPACE_REPLACE_REGEX = /[\u0009\u000A\u000C\u000D\u0020]/g // eslint-disable-line no-control-regex - if (type === opcodes.TEXT) { - try { - chunk = utf8Decode(data) - } catch { - failWebsocketConnection(this.#handler, 'Received invalid UTF-8 in text frame.') - return +/** + * @param {string} data + * @returns {Uint8Array | 'failure'} + * + * @see https://infra.spec.whatwg.org/#forgiving-base64-decode + */ +function forgivingBase64 (data) { + // 1. Remove all ASCII whitespace from data. + data = data.replace(ASCII_WHITESPACE_REPLACE_REGEX, '') + + let dataLength = data.length + // 2. If data’s code point length divides by 4 leaving + // no remainder, then: + if (dataLength % 4 === 0) { + // 1. If data ends with one or two U+003D (=) code points, + // then remove them from data. + if (data.charCodeAt(dataLength - 1) === 0x003D) { + --dataLength + if (data.charCodeAt(dataLength - 1) === 0x003D) { + --dataLength } - } else if (type === opcodes.BINARY) { - chunk = new Uint8Array(data.buffer, data.byteOffset, data.byteLength) } + } - // 3. Enqueue chunk into stream’s readable stream. - this.#readableStreamController.enqueue(chunk) + // 3. If data’s code point length divides by 4 leaving + // a remainder of 1, then return failure. + if (dataLength % 4 === 1) { + return 'failure' + } - // 4. Apply backpressure to the WebSocket. + // 4. If data contains a code point that is not one of + // U+002B (+) + // U+002F (/) + // ASCII alphanumeric + // then return failure. + if (/[^+/0-9A-Za-z]/.test(data.length === dataLength ? data : data.substring(0, dataLength))) { + return 'failure' } - /** @type {import('../websocket').Handler['onSocketClose']} */ - #onSocketClose () { - const wasClean = - this.#handler.closeState.has(sentCloseFrameState.SENT) && - this.#handler.closeState.has(sentCloseFrameState.RECEIVED) + const buffer = Buffer.from(data, 'base64') + return new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength) +} - // 1. Change the ready state to CLOSED (3). - this.#handler.readyState = states.CLOSED +/** + * @param {number} char + * @returns {boolean} + * + * @see https://infra.spec.whatwg.org/#ascii-whitespace + */ +function isASCIIWhitespace (char) { + return ( + char === 0x09 || // \t + char === 0x0a || // \n + char === 0x0c || // \f + char === 0x0d || // \r + char === 0x20 // space + ) +} - // 2. If stream ’s handshake aborted is true, then return. - if (this.#handshakeAborted) { - return +/** + * @param {Uint8Array} input + * @returns {string} + * + * @see https://infra.spec.whatwg.org/#isomorphic-decode + */ +function isomorphicDecode (input) { + // 1. To isomorphic decode a byte sequence input, return a string whose code point + // length is equal to input’s length and whose code points have the same values + // as the values of input’s bytes, in the same order. + const length = input.length + if ((2 << 15) - 1 > length) { + return String.fromCharCode.apply(null, input) + } + let result = '' + let i = 0 + let addition = (2 << 15) - 1 + while (i < length) { + if (i + addition > length) { + addition = length - i } + result += String.fromCharCode.apply(null, input.subarray(i, i += addition)) + } + return result +} - // 3. If stream ’s was ever connected is false, then reject stream ’s opened promise with a new WebSocketError. - if (!this.#handler.wasEverConnected) { - this.#openedPromise.reject(new WebSocketError('Socket never opened')) - } +const invalidIsomorphicEncodeValueRegex = /[^\x00-\xFF]/ // eslint-disable-line no-control-regex - const result = this.#parser.closingInfo +/** + * @param {string} input + * @returns {string} + * + * @see https://infra.spec.whatwg.org/#isomorphic-encode + */ +function isomorphicEncode (input) { + // 1. Assert: input contains no code points greater than U+00FF. + assert(!invalidIsomorphicEncodeValueRegex.test(input)) - // 4. Let code be the WebSocket connection close code . - // https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.5 - // If this Close control frame contains no status code, _The WebSocket - // Connection Close Code_ is considered to be 1005. If _The WebSocket - // Connection is Closed_ and no Close control frame was received by the - // endpoint (such as could occur if the underlying transport connection - // is lost), _The WebSocket Connection Close Code_ is considered to be - // 1006. - let code = result?.code ?? 1005 + // 2. Return a byte sequence whose length is equal to input’s code + // point length and whose bytes have the same values as the + // values of input’s code points, in the same order + return input +} - if (!this.#handler.closeState.has(sentCloseFrameState.SENT) && !this.#handler.closeState.has(sentCloseFrameState.RECEIVED)) { - code = 1006 - } +/** + * @see https://infra.spec.whatwg.org/#parse-json-bytes-to-a-javascript-value + * @param {Uint8Array} bytes + */ +function parseJSONFromBytes (bytes) { + return JSON.parse(utf8DecodeBytes(bytes)) +} - // 5. Let reason be the result of applying UTF-8 decode without BOM to the WebSocket connection close reason . - const reason = result?.reason == null ? '' : utf8DecodeBytes(Buffer.from(result.reason)) +/** + * @param {string} str + * @param {boolean} [leading=true] + * @param {boolean} [trailing=true] + * @returns {string} + * + * @see https://infra.spec.whatwg.org/#strip-leading-and-trailing-ascii-whitespace + */ +function removeASCIIWhitespace (str, leading = true, trailing = true) { + return removeChars(str, leading, trailing, isASCIIWhitespace) +} - // 6. If the connection was closed cleanly , - if (wasClean) { - // 6.1. Close stream ’s readable stream . - this.#readableStreamController.close() - - // 6.2. Error stream ’s writable stream with an " InvalidStateError " DOMException indicating that a closed WebSocketStream cannot be written to. - if (!this.#writableStream.locked) { - this.#writableStream.abort(new DOMException('A closed WebSocketStream cannot be written to', 'InvalidStateError')) - } - - // 6.3. Resolve stream ’s closed promise with WebSocketCloseInfo «[ " closeCode " → code , " reason " → reason ]». - this.#closedPromise.resolve({ - closeCode: code, - reason - }) - } else { - // 7. Otherwise, - - // 7.1. Let error be a new WebSocketError whose closeCode is code and reason is reason . - const error = createUnvalidatedWebSocketError('unclean close', code, reason) - - // 7.2. Error stream ’s readable stream with error . - this.#readableStreamController.error(error) - - // 7.3. Error stream ’s writable stream with error . - this.#writableStream.abort(error) +/** + * @param {string} str + * @param {boolean} leading + * @param {boolean} trailing + * @param {(charCode: number) => boolean} predicate + * @returns {string} + */ +function removeChars (str, leading, trailing, predicate) { + let lead = 0 + let trail = str.length - 1 - // 7.4. Reject stream ’s closed promise with error . - this.#closedPromise.reject(error) - } + if (leading) { + while (lead < str.length && predicate(str.charCodeAt(lead))) lead++ } - #closeUsingReason (reason) { - // 1. Let code be null. - let code = null - - // 2. Let reasonString be the empty string. - let reasonString = '' - - // 3. If reason implements WebSocketError , - if (webidl.is.WebSocketError(reason)) { - // 3.1. Set code to reason ’s closeCode . - code = reason.closeCode - - // 3.2. Set reasonString to reason ’s reason . - reasonString = reason.reason - } - - // 4. Close the WebSocket with stream , code , and reasonString . If this throws an exception, - // discard code and reasonString and close the WebSocket with stream . - closeWebSocketConnection(this.#handler, code, reasonString) + if (trailing) { + while (trail > 0 && predicate(str.charCodeAt(trail))) trail-- } - // To cancel a WebSocketStream stream given reason , close using reason giving stream and reason . - #cancel (reason) { - this.#closeUsingReason(reason) - } + return lead === 0 && trail === str.length - 1 ? str : str.slice(lead, trail + 1) } -Object.defineProperties(WebSocketStream.prototype, { - url: kEnumerableProperty, - opened: kEnumerableProperty, - closed: kEnumerableProperty, - close: kEnumerableProperty, - [Symbol.toStringTag]: { - value: 'WebSocketStream', - writable: false, - enumerable: false, - configurable: true - } -}) - -webidl.converters.WebSocketStreamOptions = webidl.dictionaryConverter([ - { - key: 'protocols', - converter: webidl.sequenceConverter(webidl.converters.USVString), - defaultValue: () => [] - }, - { - key: 'signal', - converter: webidl.nullableConverter(webidl.converters.AbortSignal), - defaultValue: () => null - } -]) +// https://infra.spec.whatwg.org/#serialize-a-javascript-value-to-a-json-string +function serializeJavascriptValueToJSONString (value) { + // 1. Let result be ? Call(%JSON.stringify%, undefined, « value »). + const result = JSON.stringify(value) -webidl.converters.WebSocketCloseInfo = webidl.dictionaryConverter([ - { - key: 'closeCode', - converter: (V) => webidl.converters['unsigned short'](V, webidl.attributes.EnforceRange) - }, - { - key: 'reason', - converter: webidl.converters.USVString, - defaultValue: () => '' + // 2. If result is undefined, then throw a TypeError. + if (result === undefined) { + throw new TypeError('Value is not JSON serializable') } -]) -webidl.converters.WebSocketStreamWrite = function (V) { - if (typeof V === 'string') { - return webidl.converters.USVString(V) - } + // 3. Assert: result is a string. + assert(typeof result === 'string') - return webidl.converters.BufferSource(V) + // 4. Return result. + return result } -module.exports = { WebSocketStream } +module.exports = { + collectASequenceOfCodePoints, + collectASequenceOfCodePointsFast, + forgivingBase64, + isASCIIWhitespace, + isomorphicDecode, + isomorphicEncode, + parseJSONFromBytes, + removeASCIIWhitespace, + removeChars, + serializeJavascriptValueToJSONString +} /***/ }), -/***/ 7484: +/***/ 664: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -const { states, opcodes } = __nccwpck_require__(163) -const { isUtf8 } = __nccwpck_require__(4573) -const { removeHTTPWhitespace } = __nccwpck_require__(9425) -const { collectASequenceOfCodePointsFast } = __nccwpck_require__(3883) +const assert = __nccwpck_require__(4589) +const { runtimeFeatures } = __nccwpck_require__(3895) /** - * @param {number} readyState - * @returns {boolean} + * @typedef {object} Metadata + * @property {SRIHashAlgorithm} alg - The algorithm used for the hash. + * @property {string} val - The base64-encoded hash value. */ -function isConnecting (readyState) { - // If the WebSocket connection is not yet established, and the connection - // is not yet closed, then the WebSocket connection is in the CONNECTING state. - return readyState === states.CONNECTING -} /** - * @param {number} readyState - * @returns {boolean} + * @typedef {Metadata[]} MetadataList */ -function isEstablished (readyState) { - // If the server's response is validated as provided for above, it is - // said that _The WebSocket Connection is Established_ and that the - // WebSocket Connection is in the OPEN state. - return readyState === states.OPEN -} /** - * @param {number} readyState - * @returns {boolean} + * @typedef {('sha256' | 'sha384' | 'sha512')} SRIHashAlgorithm */ -function isClosing (readyState) { - // Upon either sending or receiving a Close control frame, it is said - // that _The WebSocket Closing Handshake is Started_ and that the - // WebSocket connection is in the CLOSING state. - return readyState === states.CLOSING -} /** - * @param {number} readyState - * @returns {boolean} + * @type {Map} + * + * The valid SRI hash algorithm token set is the ordered set « "sha256", + * "sha384", "sha512" » (corresponding to SHA-256, SHA-384, and SHA-512 + * respectively). The ordering of this set is meaningful, with stronger + * algorithms appearing later in the set. + * + * @see https://w3c.github.io/webappsec-subresource-integrity/#valid-sri-hash-algorithm-token-set */ -function isClosed (readyState) { - return readyState === states.CLOSED -} +const validSRIHashAlgorithmTokenSet = new Map([['sha256', 0], ['sha384', 1], ['sha512', 2]]) -/** - * @see https://dom.spec.whatwg.org/#concept-event-fire - * @param {string} e - * @param {EventTarget} target - * @param {(...args: ConstructorParameters) => Event} eventFactory - * @param {EventInit | undefined} eventInitDict - * @returns {void} - */ -function fireEvent (e, target, eventFactory = (type, init) => new Event(type, init), eventInitDict = {}) { - // 1. If eventConstructor is not given, then let eventConstructor be Event. +// https://nodejs.org/api/crypto.html#determining-if-crypto-support-is-unavailable +/** @type {import('node:crypto')} */ +let crypto - // 2. Let event be the result of creating an event given eventConstructor, - // in the relevant realm of target. - // 3. Initialize event’s type attribute to e. - const event = eventFactory(e, eventInitDict) +if (runtimeFeatures.has('crypto')) { + crypto = __nccwpck_require__(7598) + const cryptoHashes = crypto.getHashes() - // 4. Initialize any other IDL attributes of event as described in the - // invocation of this algorithm. + // If no hashes are available, we cannot support SRI. + if (cryptoHashes.length === 0) { + validSRIHashAlgorithmTokenSet.clear() + } - // 5. Return the result of dispatching event at target, with legacy target - // override flag set if set. - target.dispatchEvent(event) + for (const algorithm of validSRIHashAlgorithmTokenSet.keys()) { + // If the algorithm is not supported, remove it from the list. + if (cryptoHashes.includes(algorithm) === false) { + validSRIHashAlgorithmTokenSet.delete(algorithm) + } + } +} else { + // If crypto is not available, we cannot support SRI. + validSRIHashAlgorithmTokenSet.clear() } /** - * @see https://websockets.spec.whatwg.org/#feedback-from-the-protocol - * @param {import('./websocket').Handler} handler - * @param {number} type Opcode - * @param {Buffer} data application data - * @returns {void} + * @typedef GetSRIHashAlgorithmIndex + * @type {(algorithm: SRIHashAlgorithm) => number} + * @param {SRIHashAlgorithm} algorithm + * @returns {number} The index of the algorithm in the valid SRI hash algorithm + * token set. */ -function websocketMessageReceived (handler, type, data) { - handler.onMessage(type, data) -} + +const getSRIHashAlgorithmIndex = /** @type {GetSRIHashAlgorithmIndex} */ (Map.prototype.get.bind( + validSRIHashAlgorithmTokenSet)) /** - * @param {Buffer} buffer - * @returns {ArrayBuffer} + * @typedef IsValidSRIHashAlgorithm + * @type {(algorithm: string) => algorithm is SRIHashAlgorithm} + * @param {*} algorithm + * @returns {algorithm is SRIHashAlgorithm} */ -function toArrayBuffer (buffer) { - if (buffer.byteLength === buffer.buffer.byteLength) { - return buffer.buffer - } - return new Uint8Array(buffer).buffer -} + +const isValidSRIHashAlgorithm = /** @type {IsValidSRIHashAlgorithm} */ ( + Map.prototype.has.bind(validSRIHashAlgorithmTokenSet) +) /** - * @see https://datatracker.ietf.org/doc/html/rfc6455 - * @see https://datatracker.ietf.org/doc/html/rfc2616 - * @see https://bugs.chromium.org/p/chromium/issues/detail?id=398407 - * @param {string} protocol + * @param {Uint8Array} bytes + * @param {string} metadataList * @returns {boolean} + * + * @see https://w3c.github.io/webappsec-subresource-integrity/#does-response-match-metadatalist */ -function isValidSubprotocol (protocol) { - // If present, this value indicates one - // or more comma-separated subprotocol the client wishes to speak, - // ordered by preference. The elements that comprise this value - // MUST be non-empty strings with characters in the range U+0021 to - // U+007E not including separator characters as defined in - // [RFC2616] and MUST all be unique strings. - if (protocol.length === 0) { - return false - } +const bytesMatch = runtimeFeatures.has('crypto') === false || validSRIHashAlgorithmTokenSet.size === 0 + // If node is not built with OpenSSL support, we cannot check + // a request's integrity, so allow it by default (the spec will + // allow requests if an invalid hash is given, as precedence). + ? () => true + : (bytes, metadataList) => { + // 1. Let parsedMetadata be the result of parsing metadataList. + const parsedMetadata = parseMetadata(metadataList) - for (let i = 0; i < protocol.length; ++i) { - const code = protocol.charCodeAt(i) + // 2. If parsedMetadata is empty set, return true. + if (parsedMetadata.length === 0) { + return true + } - if ( - code < 0x21 || // CTL, contains SP (0x20) and HT (0x09) - code > 0x7E || - code === 0x22 || // " - code === 0x28 || // ( - code === 0x29 || // ) - code === 0x2C || // , - code === 0x2F || // / - code === 0x3A || // : - code === 0x3B || // ; - code === 0x3C || // < - code === 0x3D || // = - code === 0x3E || // > - code === 0x3F || // ? - code === 0x40 || // @ - code === 0x5B || // [ - code === 0x5C || // \ - code === 0x5D || // ] - code === 0x7B || // { - code === 0x7D // } - ) { - return false - } - } + // 3. Let metadata be the result of getting the strongest + // metadata from parsedMetadata. + const metadata = getStrongestMetadata(parsedMetadata) - return true -} + // 4. For each item in metadata: + for (const item of metadata) { + // 1. Let algorithm be the item["alg"]. + const algorithm = item.alg -/** - * @see https://datatracker.ietf.org/doc/html/rfc6455#section-7-4 - * @param {number} code - * @returns {boolean} - */ -function isValidStatusCode (code) { - if (code >= 1000 && code < 1015) { - return ( - code !== 1004 && // reserved - code !== 1005 && // "MUST NOT be set as a status code" - code !== 1006 // "MUST NOT be set as a status code" - ) - } + // 2. Let expectedValue be the item["val"]. + const expectedValue = item.val - return code >= 3000 && code <= 4999 -} + // See https://github.com/web-platform-tests/wpt/commit/e4c5cc7a5e48093220528dfdd1c4012dc3837a0e + // "be liberal with padding". This is annoying, and it's not even in the spec. -/** - * @see https://datatracker.ietf.org/doc/html/rfc6455#section-5.5 - * @param {number} opcode - * @returns {boolean} - */ -function isControlFrame (opcode) { - return ( - opcode === opcodes.CLOSE || - opcode === opcodes.PING || - opcode === opcodes.PONG - ) -} + // 3. Let actualValue be the result of applying algorithm to bytes . + const actualValue = applyAlgorithmToBytes(algorithm, bytes) -/** - * @param {number} opcode - * @returns {boolean} - */ -function isContinuationFrame (opcode) { - return opcode === opcodes.CONTINUATION -} + // 4. If actualValue is a case-sensitive match for expectedValue, + // return true. + if (caseSensitiveMatch(actualValue, expectedValue)) { + return true + } + } -/** - * @param {number} opcode - * @returns {boolean} - */ -function isTextBinaryFrame (opcode) { - return opcode === opcodes.TEXT || opcode === opcodes.BINARY -} + // 5. Return false. + return false + } /** - * - * @param {number} opcode - * @returns {boolean} + * @param {MetadataList} metadataList + * @returns {MetadataList} The strongest hash algorithm from the metadata list. */ -function isValidOpcode (opcode) { - return isTextBinaryFrame(opcode) || isContinuationFrame(opcode) || isControlFrame(opcode) -} +function getStrongestMetadata (metadataList) { + // 1. Let result be the empty set and strongest be the empty string. + const result = [] + /** @type {Metadata|null} */ + let strongest = null -/** - * Parses a Sec-WebSocket-Extensions header value. - * @param {string} extensions - * @returns {Map} - */ -// TODO(@Uzlopak, @KhafraDev): make compliant https://datatracker.ietf.org/doc/html/rfc6455#section-9.1 -function parseExtensions (extensions) { - const position = { position: 0 } - const extensionList = new Map() + // 2. For each item in set: + for (const item of metadataList) { + // 1. Assert: item["alg"] is a valid SRI hash algorithm token. + assert(isValidSRIHashAlgorithm(item.alg), 'Invalid SRI hash algorithm token') - while (position.position < extensions.length) { - const pair = collectASequenceOfCodePointsFast(';', extensions, position) - const [name, value = ''] = pair.split('=', 2) + // 2. If result is the empty set, then: + if (result.length === 0) { + // 1. Append item to result. + result.push(item) - extensionList.set( - removeHTTPWhitespace(name, true, false), - removeHTTPWhitespace(value, false, true) - ) + // 2. Set strongest to item. + strongest = item - position.position++ - } + // 3. Continue. + continue + } - return extensionList -} + // 3. Let currentAlgorithm be strongest["alg"], and currentAlgorithmIndex be + // the index of currentAlgorithm in the valid SRI hash algorithm token set. + const currentAlgorithm = /** @type {Metadata} */ (strongest).alg + const currentAlgorithmIndex = getSRIHashAlgorithmIndex(currentAlgorithm) -/** - * @see https://www.rfc-editor.org/rfc/rfc7692#section-7.1.2.2 - * @description "client-max-window-bits = 1*DIGIT" - * @param {string} value - * @returns {boolean} - */ -function isValidClientWindowBits (value) { - for (let i = 0; i < value.length; i++) { - const byte = value.charCodeAt(i) + // 4. Let newAlgorithm be the item["alg"], and newAlgorithmIndex be the + // index of newAlgorithm in the valid SRI hash algorithm token set. + const newAlgorithm = item.alg + const newAlgorithmIndex = getSRIHashAlgorithmIndex(newAlgorithm) - if (byte < 0x30 || byte > 0x39) { - return false + // 5. If newAlgorithmIndex is less than currentAlgorithmIndex, then continue. + if (newAlgorithmIndex < currentAlgorithmIndex) { + continue + + // 6. Otherwise, if newAlgorithmIndex is greater than + // currentAlgorithmIndex: + } else if (newAlgorithmIndex > currentAlgorithmIndex) { + // 1. Set strongest to item. + strongest = item + + // 2. Set result to « item ». + result[0] = item + result.length = 1 + + // 7. Otherwise, newAlgorithmIndex and currentAlgorithmIndex are the same + // value. Append item to result. + } else { + result.push(item) } } - return true + // 3. Return result. + return result } /** - * @see https://whatpr.org/websockets/48/7b748d3...d5570f3.html#get-a-url-record - * @param {string} url - * @param {string} [baseURL] + * @param {string} metadata + * @returns {MetadataList} + * + * @see https://w3c.github.io/webappsec-subresource-integrity/#parse-metadata */ -function getURLRecord (url, baseURL) { - // 1. Let urlRecord be the result of applying the URL parser to url with baseURL . - // 2. If urlRecord is failure, then throw a " SyntaxError " DOMException . - let urlRecord +function parseMetadata (metadata) { + // 1. Let result be the empty set. + /** @type {MetadataList} */ + const result = [] - try { - urlRecord = new URL(url, baseURL) - } catch (e) { - throw new DOMException(e, 'SyntaxError') - } + // 2. For each item returned by splitting metadata on spaces: + for (const item of metadata.split(' ')) { + // 1. Let expression-and-options be the result of splitting item on U+003F (?). + const expressionAndOptions = item.split('?', 1) - // 3. If urlRecord ’s scheme is " http ", then set urlRecord ’s scheme to " ws ". - // 4. Otherwise, if urlRecord ’s scheme is " https ", set urlRecord ’s scheme to " wss ". - if (urlRecord.protocol === 'http:') { - urlRecord.protocol = 'ws:' - } else if (urlRecord.protocol === 'https:') { - urlRecord.protocol = 'wss:' - } + // 2. Let algorithm-expression be expression-and-options[0]. + const algorithmExpression = expressionAndOptions[0] - // 5. If urlRecord ’s scheme is not " ws " or " wss ", then throw a " SyntaxError " DOMException . - if (urlRecord.protocol !== 'ws:' && urlRecord.protocol !== 'wss:') { - throw new DOMException('expected a ws: or wss: url', 'SyntaxError') - } + // 3. Let base64-value be the empty string. + let base64Value = '' - // If urlRecord ’s fragment is non-null, then throw a " SyntaxError " DOMException . - if (urlRecord.hash.length || urlRecord.href.endsWith('#')) { - throw new DOMException('hash', 'SyntaxError') - } + // 4. Let algorithm-and-value be the result of splitting algorithm-expression on U+002D (-). + const algorithmAndValue = [algorithmExpression.slice(0, 6), algorithmExpression.slice(7)] - // Return urlRecord . - return urlRecord -} + // 5. Let algorithm be algorithm-and-value[0]. + const algorithm = algorithmAndValue[0] -// https://whatpr.org/websockets/48.html#validate-close-code-and-reason -function validateCloseCodeAndReason (code, reason) { - // 1. If code is not null, but is neither an integer equal to - // 1000 nor an integer in the range 3000 to 4999, inclusive, - // throw an "InvalidAccessError" DOMException. - if (code !== null) { - if (code !== 1000 && (code < 3000 || code > 4999)) { - throw new DOMException('invalid code', 'InvalidAccessError') + // 6. If algorithm is not a valid SRI hash algorithm token, then continue. + if (!isValidSRIHashAlgorithm(algorithm)) { + continue } - } - // 2. If reason is not null, then: - if (reason !== null) { - // 2.1. Let reasonBytes be the result of UTF-8 encoding reason. - // 2.2. If reasonBytes is longer than 123 bytes, then throw a - // "SyntaxError" DOMException. - const reasonBytesLength = Buffer.byteLength(reason) + // 7. If algorithm-and-value[1] exists, set base64-value to + // algorithm-and-value[1]. + if (algorithmAndValue[1]) { + base64Value = algorithmAndValue[1] + } - if (reasonBytesLength > 123) { - throw new DOMException(`Reason must be less than 123 bytes; received ${reasonBytesLength}`, 'SyntaxError') + // 8. Let metadata be the ordered map + // «["alg" → algorithm, "val" → base64-value]». + const metadata = { + alg: algorithm, + val: base64Value } + + // 9. Append metadata to result. + result.push(metadata) } + + // 3. Return result. + return result } /** - * Converts a Buffer to utf-8, even on platforms without icu. - * @type {(buffer: Buffer) => string} + * Applies the specified hash algorithm to the given bytes + * + * @typedef {(algorithm: SRIHashAlgorithm, bytes: Uint8Array) => string} ApplyAlgorithmToBytes + * @param {SRIHashAlgorithm} algorithm + * @param {Uint8Array} bytes + * @returns {string} */ -const utf8Decode = (() => { - if (typeof process.versions.icu === 'string') { - const fatalDecoder = new TextDecoder('utf-8', { fatal: true }) - return fatalDecoder.decode.bind(fatalDecoder) +const applyAlgorithmToBytes = (algorithm, bytes) => { + return crypto.hash(algorithm, bytes, 'base64') +} + +/** + * Compares two base64 strings, allowing for base64url + * in the second string. + * + * @param {string} actualValue base64 encoded string + * @param {string} expectedValue base64 or base64url encoded string + * @returns {boolean} + */ +function caseSensitiveMatch (actualValue, expectedValue) { + // Ignore padding characters from the end of the strings by + // decreasing the length by 1 or 2 if the last characters are `=`. + let actualValueLength = actualValue.length + if (actualValueLength !== 0 && actualValue[actualValueLength - 1] === '=') { + actualValueLength -= 1 } - return function (buffer) { - if (isUtf8(buffer)) { - return buffer.toString('utf-8') + if (actualValueLength !== 0 && actualValue[actualValueLength - 1] === '=') { + actualValueLength -= 1 + } + let expectedValueLength = expectedValue.length + if (expectedValueLength !== 0 && expectedValue[expectedValueLength - 1] === '=') { + expectedValueLength -= 1 + } + if (expectedValueLength !== 0 && expectedValue[expectedValueLength - 1] === '=') { + expectedValueLength -= 1 + } + + if (actualValueLength !== expectedValueLength) { + return false + } + + for (let i = 0; i < actualValueLength; ++i) { + if ( + actualValue[i] === expectedValue[i] || + (actualValue[i] === '+' && expectedValue[i] === '-') || + (actualValue[i] === '/' && expectedValue[i] === '_') + ) { + continue } - throw new TypeError('Invalid utf-8 received.') + return false } -})() + + return true +} module.exports = { - isConnecting, - isEstablished, - isClosing, - isClosed, - fireEvent, - isValidSubprotocol, - isValidStatusCode, - websocketMessageReceived, - utf8Decode, - isControlFrame, - isContinuationFrame, - isTextBinaryFrame, - isValidOpcode, - parseExtensions, - isValidClientWindowBits, - toArrayBuffer, - getURLRecord, - validateCloseCodeAndReason + applyAlgorithmToBytes, + bytesMatch, + caseSensitiveMatch, + isValidSRIHashAlgorithm, + getStrongestMetadata, + parseMetadata } /***/ }), -/***/ 9197: +/***/ 909: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -const { isArrayBuffer } = __nccwpck_require__(3429) -const { webidl } = __nccwpck_require__(2318) -const { URLSerializer } = __nccwpck_require__(9425) -const { environmentSettingsObject } = __nccwpck_require__(8913) -const { staticPropertyDescriptors, states, sentCloseFrameState, sendHints, opcodes } = __nccwpck_require__(163) -const { - isConnecting, - isEstablished, - isClosing, - isClosed, - isValidSubprotocol, - fireEvent, - utf8Decode, - toArrayBuffer, - getURLRecord -} = __nccwpck_require__(7484) -const { establishWebSocketConnection, closeWebSocketConnection, failWebsocketConnection } = __nccwpck_require__(9136) -const { ByteParser } = __nccwpck_require__(7713) -const { kEnumerableProperty } = __nccwpck_require__(983) -const { getGlobalDispatcher } = __nccwpck_require__(4456) -const { ErrorEvent, CloseEvent, createFastMessageEvent } = __nccwpck_require__(649) -const { SendQueue } = __nccwpck_require__(1217) -const { WebsocketFrameSend } = __nccwpck_require__(2647) -const { channels } = __nccwpck_require__(6591) +const assert = __nccwpck_require__(4589) +const { types, inspect } = __nccwpck_require__(7975) +const { runtimeFeatures } = __nccwpck_require__(3895) + +const UNDEFINED = 1 +const BOOLEAN = 2 +const STRING = 3 +const SYMBOL = 4 +const NUMBER = 5 +const BIGINT = 6 +const NULL = 7 +const OBJECT = 8 // function and object + +const FunctionPrototypeSymbolHasInstance = Function.call.bind(Function.prototype[Symbol.hasInstance]) + +/** @type {import('../../../types/webidl').Webidl} */ +const webidl = { + converters: {}, + util: {}, + errors: {}, + is: {} +} /** - * @typedef {object} Handler - * @property {(response: any, extensions?: string[]) => void} onConnectionEstablished - * @property {(opcode: number, data: Buffer) => void} onMessage - * @property {(error: Error) => void} onParserError - * @property {() => void} onParserDrain - * @property {(chunk: Buffer) => void} onSocketData - * @property {(err: Error) => void} onSocketError - * @property {() => void} onSocketClose - * @property {(body: Buffer) => void} onPing - * @property {(body: Buffer) => void} onPong + * @description Instantiate an error. * - * @property {number} readyState - * @property {import('stream').Duplex} socket - * @property {Set} closeState - * @property {import('../fetch/index').Fetch} controller - * @property {boolean} [wasEverConnected=false] + * @param {Object} opts + * @param {string} opts.header + * @param {string} opts.message + * @returns {TypeError} */ +webidl.errors.exception = function (message) { + return new TypeError(`${message.header}: ${message.message}`) +} -// https://websockets.spec.whatwg.org/#interface-definition -class WebSocket extends EventTarget { - #events = { - open: null, - error: null, - close: null, - message: null - } - - #bufferedAmount = 0 - #protocol = '' - #extensions = '' +/** + * @description Instantiate an error when conversion from one type to another has failed. + * + * @param {Object} opts + * @param {string} opts.prefix + * @param {string} opts.argument + * @param {string[]} opts.types + * @returns {TypeError} + */ +webidl.errors.conversionFailed = function (opts) { + const plural = opts.types.length === 1 ? '' : ' one of' + const message = + `${opts.argument} could not be converted to` + + `${plural}: ${opts.types.join(', ')}.` - /** @type {SendQueue} */ - #sendQueue + return webidl.errors.exception({ + header: opts.prefix, + message + }) +} - /** @type {Handler} */ - #handler = { - onConnectionEstablished: (response, extensions) => this.#onConnectionEstablished(response, extensions), - onMessage: (opcode, data) => this.#onMessage(opcode, data), - onParserError: (err) => failWebsocketConnection(this.#handler, null, err.message), - onParserDrain: () => this.#onParserDrain(), - onSocketData: (chunk) => { - if (!this.#parser.write(chunk)) { - this.#handler.socket.pause() - } - }, - onSocketError: (err) => { - this.#handler.readyState = states.CLOSING +/** + * @description Instantiate an error when an invalid argument is provided + * + * @param {Object} context + * @param {string} context.prefix + * @param {string} context.value + * @param {string} context.type + * @returns {TypeError} + */ +webidl.errors.invalidArgument = function (context) { + return webidl.errors.exception({ + header: context.prefix, + message: `"${context.value}" is an invalid ${context.type}.` + }) +} - if (channels.socketError.hasSubscribers) { - channels.socketError.publish(err) - } +// https://webidl.spec.whatwg.org/#implements +webidl.brandCheck = function (V, I) { + if (!FunctionPrototypeSymbolHasInstance(I, V)) { + const err = new TypeError('Illegal invocation') + err.code = 'ERR_INVALID_THIS' // node compat. + throw err + } +} - this.#handler.socket.destroy() - }, - onSocketClose: () => this.#onSocketClose(), - onPing: (body) => { - if (channels.ping.hasSubscribers) { - channels.ping.publish({ - payload: body, - websocket: this - }) - } - }, - onPong: (body) => { - if (channels.pong.hasSubscribers) { - channels.pong.publish({ - payload: body, - websocket: this - }) - } - }, +webidl.brandCheckMultiple = function (List) { + const prototypes = List.map((c) => webidl.util.MakeTypeAssertion(c)) - readyState: states.CONNECTING, - socket: null, - closeState: new Set(), - controller: null, - wasEverConnected: false + return (V) => { + if (prototypes.every(typeCheck => !typeCheck(V))) { + const err = new TypeError('Illegal invocation') + err.code = 'ERR_INVALID_THIS' // node compat. + throw err + } } +} - #url - #binaryType - /** @type {import('./receiver').ByteParser} */ - #parser +webidl.argumentLengthCheck = function ({ length }, min, ctx) { + if (length < min) { + throw webidl.errors.exception({ + message: `${min} argument${min !== 1 ? 's' : ''} required, ` + + `but${length ? ' only' : ''} ${length} found.`, + header: ctx + }) + } +} - /** - * @param {string} url - * @param {string|string[]} protocols - */ - constructor (url, protocols = []) { - super() +webidl.illegalConstructor = function () { + throw webidl.errors.exception({ + header: 'TypeError', + message: 'Illegal constructor' + }) +} - webidl.util.markAsUncloneable(this) +webidl.util.MakeTypeAssertion = function (I) { + return (O) => FunctionPrototypeSymbolHasInstance(I, O) +} - const prefix = 'WebSocket constructor' - webidl.argumentLengthCheck(arguments, 1, prefix) +// https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values +webidl.util.Type = function (V) { + switch (typeof V) { + case 'undefined': return UNDEFINED + case 'boolean': return BOOLEAN + case 'string': return STRING + case 'symbol': return SYMBOL + case 'number': return NUMBER + case 'bigint': return BIGINT + case 'function': + case 'object': { + if (V === null) { + return NULL + } - const options = webidl.converters['DOMString or sequence or WebSocketInit'](protocols, prefix, 'options') + return OBJECT + } + } +} - url = webidl.converters.USVString(url) - protocols = options.protocols +webidl.util.Types = { + UNDEFINED, + BOOLEAN, + STRING, + SYMBOL, + NUMBER, + BIGINT, + NULL, + OBJECT +} - // 1. Let baseURL be this's relevant settings object's API base URL. - const baseURL = environmentSettingsObject.settingsObject.baseUrl +webidl.util.TypeValueToString = function (o) { + switch (webidl.util.Type(o)) { + case UNDEFINED: return 'Undefined' + case BOOLEAN: return 'Boolean' + case STRING: return 'String' + case SYMBOL: return 'Symbol' + case NUMBER: return 'Number' + case BIGINT: return 'BigInt' + case NULL: return 'Null' + case OBJECT: return 'Object' + } +} - // 2. Let urlRecord be the result of getting a URL record given url and baseURL. - const urlRecord = getURLRecord(url, baseURL) +webidl.util.markAsUncloneable = runtimeFeatures.has('markAsUncloneable') + ? (__nccwpck_require__(5919).markAsUncloneable) + : () => {} - // 3. If protocols is a string, set protocols to a sequence consisting - // of just that string. - if (typeof protocols === 'string') { - protocols = [protocols] - } +// https://webidl.spec.whatwg.org/#abstract-opdef-converttoint +webidl.util.ConvertToInt = function (V, bitLength, signedness, flags) { + let upperBound + let lowerBound - // 4. If any of the values in protocols occur more than once or otherwise - // fail to match the requirements for elements that comprise the value - // of `Sec-WebSocket-Protocol` fields as defined by The WebSocket - // protocol, then throw a "SyntaxError" DOMException. - if (protocols.length !== new Set(protocols.map(p => p.toLowerCase())).size) { - throw new DOMException('Invalid Sec-WebSocket-Protocol value', 'SyntaxError') - } + // 1. If bitLength is 64, then: + if (bitLength === 64) { + // 1. Let upperBound be 2^53 − 1. + upperBound = Math.pow(2, 53) - 1 - if (protocols.length > 0 && !protocols.every(p => isValidSubprotocol(p))) { - throw new DOMException('Invalid Sec-WebSocket-Protocol value', 'SyntaxError') + // 2. If signedness is "unsigned", then let lowerBound be 0. + if (signedness === 'unsigned') { + lowerBound = 0 + } else { + // 3. Otherwise let lowerBound be −2^53 + 1. + lowerBound = Math.pow(-2, 53) + 1 } + } else if (signedness === 'unsigned') { + // 2. Otherwise, if signedness is "unsigned", then: - // 5. Set this's url to urlRecord. - this.#url = new URL(urlRecord.href) - - // 6. Let client be this's relevant settings object. - const client = environmentSettingsObject.settingsObject + // 1. Let lowerBound be 0. + lowerBound = 0 - // 7. Run this step in parallel: - // 7.1. Establish a WebSocket connection given urlRecord, protocols, - // and client. - this.#handler.controller = establishWebSocketConnection( - urlRecord, - protocols, - client, - this.#handler, - options - ) + // 2. Let upperBound be 2^bitLength − 1. + upperBound = Math.pow(2, bitLength) - 1 + } else { + // 3. Otherwise: - // Each WebSocket object has an associated ready state, which is a - // number representing the state of the connection. Initially it must - // be CONNECTING (0). - this.#handler.readyState = WebSocket.CONNECTING + // 1. Let lowerBound be -2^bitLength − 1. + lowerBound = Math.pow(-2, bitLength) - 1 - // The extensions attribute must initially return the empty string. + // 2. Let upperBound be 2^bitLength − 1 − 1. + upperBound = Math.pow(2, bitLength - 1) - 1 + } - // The protocol attribute must initially return the empty string. + // 4. Let x be ? ToNumber(V). + let x = Number(V) - // Each WebSocket object has an associated binary type, which is a - // BinaryType. Initially it must be "blob". - this.#binaryType = 'blob' + // 5. If x is −0, then set x to +0. + if (x === 0) { + x = 0 } - /** - * @see https://websockets.spec.whatwg.org/#dom-websocket-close - * @param {number|undefined} code - * @param {string|undefined} reason - */ - close (code = undefined, reason = undefined) { - webidl.brandCheck(this, WebSocket) + // 6. If the conversion is to an IDL type associated + // with the [EnforceRange] extended attribute, then: + if (webidl.util.HasFlag(flags, webidl.attributes.EnforceRange)) { + // 1. If x is NaN, +∞, or −∞, then throw a TypeError. + if ( + Number.isNaN(x) || + x === Number.POSITIVE_INFINITY || + x === Number.NEGATIVE_INFINITY + ) { + throw webidl.errors.exception({ + header: 'Integer conversion', + message: `Could not convert ${webidl.util.Stringify(V)} to an integer.` + }) + } - const prefix = 'WebSocket.close' + // 2. Set x to IntegerPart(x). + x = webidl.util.IntegerPart(x) - if (code !== undefined) { - code = webidl.converters['unsigned short'](code, prefix, 'code', webidl.attributes.Clamp) + // 3. If x < lowerBound or x > upperBound, then + // throw a TypeError. + if (x < lowerBound || x > upperBound) { + throw webidl.errors.exception({ + header: 'Integer conversion', + message: `Value must be between ${lowerBound}-${upperBound}, got ${x}.` + }) } - if (reason !== undefined) { - reason = webidl.converters.USVString(reason) - } + // 4. Return x. + return x + } - // 1. If code is the special value "missing", then set code to null. - code ??= null + // 7. If x is not NaN and the conversion is to an IDL + // type associated with the [Clamp] extended + // attribute, then: + if (!Number.isNaN(x) && webidl.util.HasFlag(flags, webidl.attributes.Clamp)) { + // 1. Set x to min(max(x, lowerBound), upperBound). + x = Math.min(Math.max(x, lowerBound), upperBound) - // 2. If reason is the special value "missing", then set reason to the empty string. - reason ??= '' + // 2. Round x to the nearest integer, choosing the + // even integer if it lies halfway between two, + // and choosing +0 rather than −0. + if (Math.floor(x) % 2 === 0) { + x = Math.floor(x) + } else { + x = Math.ceil(x) + } - // 3. Close the WebSocket with this, code, and reason. - closeWebSocketConnection(this.#handler, code, reason, true) + // 3. Return x. + return x } - /** - * @see https://websockets.spec.whatwg.org/#dom-websocket-send - * @param {NodeJS.TypedArray|ArrayBuffer|Blob|string} data - */ - send (data) { - webidl.brandCheck(this, WebSocket) + // 8. If x is NaN, +0, +∞, or −∞, then return +0. + if ( + Number.isNaN(x) || + (x === 0 && Object.is(0, x)) || + x === Number.POSITIVE_INFINITY || + x === Number.NEGATIVE_INFINITY + ) { + return 0 + } - const prefix = 'WebSocket.send' - webidl.argumentLengthCheck(arguments, 1, prefix) + // 9. Set x to IntegerPart(x). + x = webidl.util.IntegerPart(x) - data = webidl.converters.WebSocketSendData(data, prefix, 'data') + // 10. Set x to x modulo 2^bitLength. + x = x % Math.pow(2, bitLength) - // 1. If this's ready state is CONNECTING, then throw an - // "InvalidStateError" DOMException. - if (isConnecting(this.#handler.readyState)) { - throw new DOMException('Sent before connected.', 'InvalidStateError') - } + // 11. If signedness is "signed" and x ≥ 2^bitLength − 1, + // then return x − 2^bitLength. + if (signedness === 'signed' && x >= Math.pow(2, bitLength) - 1) { + return x - Math.pow(2, bitLength) + } - // 2. Run the appropriate set of steps from the following list: - // https://datatracker.ietf.org/doc/html/rfc6455#section-6.1 - // https://datatracker.ietf.org/doc/html/rfc6455#section-5.2 + // 12. Otherwise, return x. + return x +} - if (!isEstablished(this.#handler.readyState) || isClosing(this.#handler.readyState)) { - return - } +// https://webidl.spec.whatwg.org/#abstract-opdef-integerpart +webidl.util.IntegerPart = function (n) { + // 1. Let r be floor(abs(n)). + const r = Math.floor(Math.abs(n)) - // If data is a string - if (typeof data === 'string') { - // If the WebSocket connection is established and the WebSocket - // closing handshake has not yet started, then the user agent - // must send a WebSocket Message comprised of the data argument - // using a text frame opcode; if the data cannot be sent, e.g. - // because it would need to be buffered but the buffer is full, - // the user agent must flag the WebSocket as full and then close - // the WebSocket connection. Any invocation of this method with a - // string argument that does not throw an exception must increase - // the bufferedAmount attribute by the number of bytes needed to - // express the argument as UTF-8. + // 2. If n < 0, then return -1 × r. + if (n < 0) { + return -1 * r + } - const buffer = Buffer.from(data) + // 3. Otherwise, return r. + return r +} - this.#bufferedAmount += buffer.byteLength - this.#sendQueue.add(buffer, () => { - this.#bufferedAmount -= buffer.byteLength - }, sendHints.text) - } else if (isArrayBuffer(data)) { - // If the WebSocket connection is established, and the WebSocket - // closing handshake has not yet started, then the user agent must - // send a WebSocket Message comprised of data using a binary frame - // opcode; if the data cannot be sent, e.g. because it would need - // to be buffered but the buffer is full, the user agent must flag - // the WebSocket as full and then close the WebSocket connection. - // The data to be sent is the data stored in the buffer described - // by the ArrayBuffer object. Any invocation of this method with an - // ArrayBuffer argument that does not throw an exception must - // increase the bufferedAmount attribute by the length of the - // ArrayBuffer in bytes. +webidl.util.Stringify = function (V) { + const type = webidl.util.Type(V) - this.#bufferedAmount += data.byteLength - this.#sendQueue.add(data, () => { - this.#bufferedAmount -= data.byteLength - }, sendHints.arrayBuffer) - } else if (ArrayBuffer.isView(data)) { - // If the WebSocket connection is established, and the WebSocket - // closing handshake has not yet started, then the user agent must - // send a WebSocket Message comprised of data using a binary frame - // opcode; if the data cannot be sent, e.g. because it would need to - // be buffered but the buffer is full, the user agent must flag the - // WebSocket as full and then close the WebSocket connection. The - // data to be sent is the data stored in the section of the buffer - // described by the ArrayBuffer object that data references. Any - // invocation of this method with this kind of argument that does - // not throw an exception must increase the bufferedAmount attribute - // by the length of data’s buffer in bytes. + switch (type) { + case SYMBOL: + return `Symbol(${V.description})` + case OBJECT: + return inspect(V) + case STRING: + return `"${V}"` + case BIGINT: + return `${V}n` + default: + return `${V}` + } +} - this.#bufferedAmount += data.byteLength - this.#sendQueue.add(data, () => { - this.#bufferedAmount -= data.byteLength - }, sendHints.typedArray) - } else if (webidl.is.Blob(data)) { - // If the WebSocket connection is established, and the WebSocket - // closing handshake has not yet started, then the user agent must - // send a WebSocket Message comprised of data using a binary frame - // opcode; if the data cannot be sent, e.g. because it would need to - // be buffered but the buffer is full, the user agent must flag the - // WebSocket as full and then close the WebSocket connection. The data - // to be sent is the raw data represented by the Blob object. Any - // invocation of this method with a Blob argument that does not throw - // an exception must increase the bufferedAmount attribute by the size - // of the Blob object’s raw data, in bytes. +webidl.util.IsResizableArrayBuffer = function (V) { + if (types.isArrayBuffer(V)) { + return V.resizable + } - this.#bufferedAmount += data.size - this.#sendQueue.add(data, () => { - this.#bufferedAmount -= data.size - }, sendHints.blob) - } + if (types.isSharedArrayBuffer(V)) { + return V.growable } - get readyState () { - webidl.brandCheck(this, WebSocket) + throw webidl.errors.exception({ + header: 'IsResizableArrayBuffer', + message: `"${webidl.util.Stringify(V)}" is not an array buffer.` + }) +} - // The readyState getter steps are to return this's ready state. - return this.#handler.readyState - } +webidl.util.HasFlag = function (flags, attributes) { + return typeof flags === 'number' && (flags & attributes) === attributes +} - get bufferedAmount () { - webidl.brandCheck(this, WebSocket) +// https://webidl.spec.whatwg.org/#es-sequence +webidl.sequenceConverter = function (converter) { + return (V, prefix, argument, Iterable) => { + // 1. If Type(V) is not Object, throw a TypeError. + if (webidl.util.Type(V) !== OBJECT) { + throw webidl.errors.exception({ + header: prefix, + message: `${argument} (${webidl.util.Stringify(V)}) is not iterable.` + }) + } - return this.#bufferedAmount - } + // 2. Let method be ? GetMethod(V, @@iterator). + /** @type {Generator} */ + const method = typeof Iterable === 'function' ? Iterable() : V?.[Symbol.iterator]?.() + const seq = [] + let index = 0 - get url () { - webidl.brandCheck(this, WebSocket) + // 3. If method is undefined, throw a TypeError. + if ( + method === undefined || + typeof method.next !== 'function' + ) { + throw webidl.errors.exception({ + header: prefix, + message: `${argument} is not iterable.` + }) + } - // The url getter steps are to return this's url, serialized. - return URLSerializer(this.#url) - } + // https://webidl.spec.whatwg.org/#create-sequence-from-iterable + while (true) { + const { done, value } = method.next() - get extensions () { - webidl.brandCheck(this, WebSocket) + if (done) { + break + } - return this.#extensions + seq.push(converter(value, prefix, `${argument}[${index++}]`)) + } + + return seq } +} - get protocol () { - webidl.brandCheck(this, WebSocket) +// https://webidl.spec.whatwg.org/#es-to-record +webidl.recordConverter = function (keyConverter, valueConverter) { + return (O, prefix, argument) => { + // 1. If Type(O) is not Object, throw a TypeError. + if (webidl.util.Type(O) !== OBJECT) { + throw webidl.errors.exception({ + header: prefix, + message: `${argument} ("${webidl.util.TypeValueToString(O)}") is not an Object.` + }) + } - return this.#protocol - } + // 2. Let result be a new empty instance of record. + const result = {} - get onopen () { - webidl.brandCheck(this, WebSocket) + if (!types.isProxy(O)) { + // 1. Let desc be ? O.[[GetOwnProperty]](key). + const keys = [...Object.getOwnPropertyNames(O), ...Object.getOwnPropertySymbols(O)] - return this.#events.open - } + for (const key of keys) { + const keyName = webidl.util.Stringify(key) - set onopen (fn) { - webidl.brandCheck(this, WebSocket) + // 1. Let typedKey be key converted to an IDL value of type K. + const typedKey = keyConverter(key, prefix, `Key ${keyName} in ${argument}`) - if (this.#events.open) { - this.removeEventListener('open', this.#events.open) - } + // 2. Let value be ? Get(O, key). + // 3. Let typedValue be value converted to an IDL value of type V. + const typedValue = valueConverter(O[key], prefix, `${argument}[${keyName}]`) - const listener = webidl.converters.EventHandlerNonNull(fn) + // 4. Set result[typedKey] to typedValue. + result[typedKey] = typedValue + } - if (listener !== null) { - this.addEventListener('open', listener) - this.#events.open = fn - } else { - this.#events.open = null + // 5. Return result. + return result } - } - get onerror () { - webidl.brandCheck(this, WebSocket) - - return this.#events.error - } + // 3. Let keys be ? O.[[OwnPropertyKeys]](). + const keys = Reflect.ownKeys(O) - set onerror (fn) { - webidl.brandCheck(this, WebSocket) + // 4. For each key of keys. + for (const key of keys) { + // 1. Let desc be ? O.[[GetOwnProperty]](key). + const desc = Reflect.getOwnPropertyDescriptor(O, key) - if (this.#events.error) { - this.removeEventListener('error', this.#events.error) - } + // 2. If desc is not undefined and desc.[[Enumerable]] is true: + if (desc?.enumerable) { + // 1. Let typedKey be key converted to an IDL value of type K. + const typedKey = keyConverter(key, prefix, argument) - const listener = webidl.converters.EventHandlerNonNull(fn) + // 2. Let value be ? Get(O, key). + // 3. Let typedValue be value converted to an IDL value of type V. + const typedValue = valueConverter(O[key], prefix, argument) - if (listener !== null) { - this.addEventListener('error', listener) - this.#events.error = fn - } else { - this.#events.error = null + // 4. Set result[typedKey] to typedValue. + result[typedKey] = typedValue + } } + + // 5. Return result. + return result } +} - get onclose () { - webidl.brandCheck(this, WebSocket) +webidl.interfaceConverter = function (TypeCheck, name) { + return (V, prefix, argument) => { + if (!TypeCheck(V)) { + throw webidl.errors.exception({ + header: prefix, + message: `Expected ${argument} ("${webidl.util.Stringify(V)}") to be an instance of ${name}.` + }) + } - return this.#events.close + return V } +} - set onclose (fn) { - webidl.brandCheck(this, WebSocket) +webidl.dictionaryConverter = function (converters) { + return (dictionary, prefix, argument) => { + const dict = {} - if (this.#events.close) { - this.removeEventListener('close', this.#events.close) + if (dictionary != null && webidl.util.Type(dictionary) !== OBJECT) { + throw webidl.errors.exception({ + header: prefix, + message: `Expected ${dictionary} to be one of: Null, Undefined, Object.` + }) } - const listener = webidl.converters.EventHandlerNonNull(fn) - - if (listener !== null) { - this.addEventListener('close', listener) - this.#events.close = fn - } else { - this.#events.close = null - } - } + for (const options of converters) { + const { key, defaultValue, required, converter } = options - get onmessage () { - webidl.brandCheck(this, WebSocket) + if (required === true) { + if (dictionary == null || !Object.hasOwn(dictionary, key)) { + throw webidl.errors.exception({ + header: prefix, + message: `Missing required key "${key}".` + }) + } + } - return this.#events.message - } + let value = dictionary?.[key] + const hasDefault = defaultValue !== undefined - set onmessage (fn) { - webidl.brandCheck(this, WebSocket) + // Only use defaultValue if value is undefined and + // a defaultValue options was provided. + if (hasDefault && value === undefined) { + value = defaultValue() + } - if (this.#events.message) { - this.removeEventListener('message', this.#events.message) - } + // A key can be optional and have no default value. + // When this happens, do not perform a conversion, + // and do not assign the key a value. + if (required || hasDefault || value !== undefined) { + value = converter(value, prefix, `${argument}.${key}`) - const listener = webidl.converters.EventHandlerNonNull(fn) + if ( + options.allowedValues && + !options.allowedValues.includes(value) + ) { + throw webidl.errors.exception({ + header: prefix, + message: `${value} is not an accepted type. Expected one of ${options.allowedValues.join(', ')}.` + }) + } - if (listener !== null) { - this.addEventListener('message', listener) - this.#events.message = fn - } else { - this.#events.message = null + dict[key] = value + } } + + return dict } +} - get binaryType () { - webidl.brandCheck(this, WebSocket) +webidl.nullableConverter = function (converter) { + return (V, prefix, argument) => { + if (V === null) { + return V + } - return this.#binaryType + return converter(V, prefix, argument) } +} - set binaryType (type) { - webidl.brandCheck(this, WebSocket) +/** + * @param {*} value + * @returns {boolean} + */ +webidl.is.USVString = function (value) { + return ( + typeof value === 'string' && + value.isWellFormed() + ) +} - if (type !== 'blob' && type !== 'arraybuffer') { - this.#binaryType = 'blob' - } else { - this.#binaryType = type - } - } +webidl.is.ReadableStream = webidl.util.MakeTypeAssertion(ReadableStream) +webidl.is.Blob = webidl.util.MakeTypeAssertion(Blob) +webidl.is.URLSearchParams = webidl.util.MakeTypeAssertion(URLSearchParams) +webidl.is.File = webidl.util.MakeTypeAssertion(File) +webidl.is.URL = webidl.util.MakeTypeAssertion(URL) +webidl.is.AbortSignal = webidl.util.MakeTypeAssertion(AbortSignal) +webidl.is.MessagePort = webidl.util.MakeTypeAssertion(MessagePort) - /** - * @see https://websockets.spec.whatwg.org/#feedback-from-the-protocol - */ - #onConnectionEstablished (response, parsedExtensions) { - // processResponse is called when the "response’s header list has been received and initialized." - // once this happens, the connection is open - this.#handler.socket = response.socket +webidl.is.BufferSource = function (V) { + return types.isArrayBuffer(V) || ( + ArrayBuffer.isView(V) && + types.isArrayBuffer(V.buffer) + ) +} - const parser = new ByteParser(this.#handler, parsedExtensions) - parser.on('drain', () => this.#handler.onParserDrain()) - parser.on('error', (err) => this.#handler.onParserError(err)) +// https://webidl.spec.whatwg.org/#dfn-get-buffer-source-copy +webidl.util.getCopyOfBytesHeldByBufferSource = function (bufferSource) { + // 1. Let jsBufferSource be the result of converting bufferSource to a JavaScript value. + const jsBufferSource = bufferSource - this.#parser = parser - this.#sendQueue = new SendQueue(response.socket) + // 2. Let jsArrayBuffer be jsBufferSource. + let jsArrayBuffer = jsBufferSource - // 1. Change the ready state to OPEN (1). - this.#handler.readyState = states.OPEN + // 3. Let offset be 0. + let offset = 0 - // 2. Change the extensions attribute’s value to the extensions in use, if - // it is not the null value. - // https://datatracker.ietf.org/doc/html/rfc6455#section-9.1 - const extensions = response.headersList.get('sec-websocket-extensions') + // 4. Let length be 0. + let length = 0 - if (extensions !== null) { - this.#extensions = extensions - } + // 5. If jsBufferSource has a [[ViewedArrayBuffer]] internal slot, then: + if (types.isTypedArray(jsBufferSource) || types.isDataView(jsBufferSource)) { + // 5.1. Set jsArrayBuffer to jsBufferSource.[[ViewedArrayBuffer]]. + jsArrayBuffer = jsBufferSource.buffer - // 3. Change the protocol attribute’s value to the subprotocol in use, if - // it is not the null value. - // https://datatracker.ietf.org/doc/html/rfc6455#section-1.9 - const protocol = response.headersList.get('sec-websocket-protocol') + // 5.2. Set offset to jsBufferSource.[[ByteOffset]]. + offset = jsBufferSource.byteOffset - if (protocol !== null) { - this.#protocol = protocol - } + // 5.3. Set length to jsBufferSource.[[ByteLength]]. + length = jsBufferSource.byteLength + } else { + // 6. Otherwise: - // 4. Fire an event named open at the WebSocket object. - fireEvent('open', this) + // 6.1. Assert: jsBufferSource is an ArrayBuffer or SharedArrayBuffer object. + assert(types.isAnyArrayBuffer(jsBufferSource)) - if (channels.open.hasSubscribers) { - // Convert headers to a plain object for the event - const headers = response.headersList.entries - channels.open.publish({ - address: response.socket.address(), - protocol: this.#protocol, - extensions: this.#extensions, - websocket: this, - handshakeResponse: { - status: response.status, - statusText: response.statusText, - headers - } - }) - } + // 6.2. Set length to jsBufferSource.[[ArrayBufferByteLength]]. + length = jsBufferSource.byteLength } - #onMessage (type, data) { - // 1. If ready state is not OPEN (1), then return. - if (this.#handler.readyState !== states.OPEN) { - return - } + // 7. If IsDetachedBuffer(jsArrayBuffer) is true, then return the empty byte sequence. + if (jsArrayBuffer.detached) { + return new Uint8Array(0) + } - // 2. Let dataForEvent be determined by switching on type and binary type: - let dataForEvent + // 8. Let bytes be a new byte sequence of length equal to length. + const bytes = new Uint8Array(length) - if (type === opcodes.TEXT) { - // -> type indicates that the data is Text - // a new DOMString containing data - try { - dataForEvent = utf8Decode(data) - } catch { - failWebsocketConnection(this.#handler, 1007, 'Received invalid UTF-8 in text frame.') - return - } - } else if (type === opcodes.BINARY) { - if (this.#binaryType === 'blob') { - // -> type indicates that the data is Binary and binary type is "blob" - // a new Blob object, created in the relevant Realm of the WebSocket - // object, that represents data as its raw data - dataForEvent = new Blob([data]) - } else { - // -> type indicates that the data is Binary and binary type is "arraybuffer" - // a new ArrayBuffer object, created in the relevant Realm of the - // WebSocket object, whose contents are data - dataForEvent = toArrayBuffer(data) - } - } + // 9. For i in the range offset to offset + length − 1, inclusive, + // set bytes[i − offset] to GetValueFromBuffer(jsArrayBuffer, i, Uint8, true, Unordered). + const view = new Uint8Array(jsArrayBuffer, offset, length) + bytes.set(view) - // 3. Fire an event named message at the WebSocket object, using MessageEvent, - // with the origin attribute initialized to the serialization of the WebSocket - // object’s url's origin, and the data attribute initialized to dataForEvent. - fireEvent('message', this, createFastMessageEvent, { - origin: this.#url.origin, - data: dataForEvent - }) + // 10. Return bytes. + return bytes +} + +// https://webidl.spec.whatwg.org/#es-DOMString +webidl.converters.DOMString = function (V, prefix, argument, flags) { + // 1. If V is null and the conversion is to an IDL type + // associated with the [LegacyNullToEmptyString] + // extended attribute, then return the DOMString value + // that represents the empty string. + if (V === null && webidl.util.HasFlag(flags, webidl.attributes.LegacyNullToEmptyString)) { + return '' } - #onParserDrain () { - this.#handler.socket.resume() + // 2. Let x be ? ToString(V). + if (typeof V === 'symbol') { + throw webidl.errors.exception({ + header: prefix, + message: `${argument} is a symbol, which cannot be converted to a DOMString.` + }) } - /** - * @see https://websockets.spec.whatwg.org/#feedback-from-the-protocol - * @see https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.4 - */ - #onSocketClose () { - // If the TCP connection was closed after the - // WebSocket closing handshake was completed, the WebSocket connection - // is said to have been closed _cleanly_. - const wasClean = - this.#handler.closeState.has(sentCloseFrameState.SENT) && - this.#handler.closeState.has(sentCloseFrameState.RECEIVED) + // 3. Return the IDL DOMString value that represents the + // same sequence of code units as the one the + // ECMAScript String value x represents. + return String(V) +} - let code = 1005 - let reason = '' +// https://webidl.spec.whatwg.org/#es-ByteString +webidl.converters.ByteString = function (V, prefix, argument) { + // 1. Let x be ? ToString(V). + if (typeof V === 'symbol') { + throw webidl.errors.exception({ + header: prefix, + message: `${argument} is a symbol, which cannot be converted to a ByteString.` + }) + } - const result = this.#parser?.closingInfo + const x = String(V) - if (result && !result.error) { - code = result.code ?? 1005 - reason = result.reason - } - - // 1. Change the ready state to CLOSED (3). - this.#handler.readyState = states.CLOSED - - // 2. If the user agent was required to fail the WebSocket - // connection, or if the WebSocket connection was closed - // after being flagged as full, fire an event named error - // at the WebSocket object. - if (!this.#handler.closeState.has(sentCloseFrameState.RECEIVED)) { - // If _The WebSocket - // Connection is Closed_ and no Close control frame was received by the - // endpoint (such as could occur if the underlying transport connection - // is lost), _The WebSocket Connection Close Code_ is considered to be - // 1006. - code = 1006 - - fireEvent('error', this, (type, init) => new ErrorEvent(type, init), { - error: new TypeError(reason) - }) + // 2. If the value of any element of x is greater than + // 255, then throw a TypeError. + for (let index = 0; index < x.length; index++) { + if (x.charCodeAt(index) > 255) { + throw new TypeError( + 'Cannot convert argument to a ByteString because the character at ' + + `index ${index} has a value of ${x.charCodeAt(index)} which is greater than 255.` + ) } + } - // 3. Fire an event named close at the WebSocket object, - // using CloseEvent, with the wasClean attribute - // initialized to true if the connection closed cleanly - // and false otherwise, the code attribute initialized to - // the WebSocket connection close code, and the reason - // attribute initialized to the result of applying UTF-8 - // decode without BOM to the WebSocket connection close - // reason. - // TODO: process.nextTick - fireEvent('close', this, (type, init) => new CloseEvent(type, init), { - wasClean, code, reason - }) + // 3. Return an IDL ByteString value whose length is the + // length of x, and where the value of each element is + // the value of the corresponding element of x. + return x +} - if (channels.close.hasSubscribers) { - channels.close.publish({ - websocket: this, - code, - reason - }) - } +/** + * @param {unknown} value + * @returns {string} + * @see https://webidl.spec.whatwg.org/#es-USVString + */ +webidl.converters.USVString = function (value) { + // TODO: rewrite this so we can control the errors thrown + if (typeof value === 'string') { + return value.toWellFormed() } + return `${value}`.toWellFormed() +} - /** - * @param {WebSocket} ws - * @param {Buffer|undefined} buffer - */ - static ping (ws, buffer) { - if (Buffer.isBuffer(buffer)) { - if (buffer.length > 125) { - throw new TypeError('A PING frame cannot have a body larger than 125 bytes.') - } - } else if (buffer !== undefined) { - throw new TypeError('Expected buffer payload') - } +// https://webidl.spec.whatwg.org/#es-boolean +webidl.converters.boolean = function (V) { + // 1. Let x be the result of computing ToBoolean(V). + // https://262.ecma-international.org/10.0/index.html#table-10 + const x = Boolean(V) - // An endpoint MAY send a Ping frame any time after the connection is - // established and before the connection is closed. - const readyState = ws.#handler.readyState + // 2. Return the IDL boolean value that is the one that represents + // the same truth value as the ECMAScript Boolean value x. + return x +} - if (isEstablished(readyState) && !isClosing(readyState) && !isClosed(readyState)) { - const frame = new WebsocketFrameSend(buffer) - ws.#handler.socket.write(frame.createFrame(opcodes.PING)) - } - } +// https://webidl.spec.whatwg.org/#es-any +webidl.converters.any = function (V) { + return V } -const { ping } = WebSocket -Reflect.deleteProperty(WebSocket, 'ping') +// https://webidl.spec.whatwg.org/#es-long-long +webidl.converters['long long'] = function (V, prefix, argument) { + // 1. Let x be ? ConvertToInt(V, 64, "signed"). + const x = webidl.util.ConvertToInt(V, 64, 'signed', 0, prefix, argument) -// https://websockets.spec.whatwg.org/#dom-websocket-connecting -WebSocket.CONNECTING = WebSocket.prototype.CONNECTING = states.CONNECTING -// https://websockets.spec.whatwg.org/#dom-websocket-open -WebSocket.OPEN = WebSocket.prototype.OPEN = states.OPEN -// https://websockets.spec.whatwg.org/#dom-websocket-closing -WebSocket.CLOSING = WebSocket.prototype.CLOSING = states.CLOSING -// https://websockets.spec.whatwg.org/#dom-websocket-closed -WebSocket.CLOSED = WebSocket.prototype.CLOSED = states.CLOSED + // 2. Return the IDL long long value that represents + // the same numeric value as x. + return x +} -Object.defineProperties(WebSocket.prototype, { - CONNECTING: staticPropertyDescriptors, - OPEN: staticPropertyDescriptors, - CLOSING: staticPropertyDescriptors, - CLOSED: staticPropertyDescriptors, - url: kEnumerableProperty, - readyState: kEnumerableProperty, - bufferedAmount: kEnumerableProperty, - onopen: kEnumerableProperty, - onerror: kEnumerableProperty, - onclose: kEnumerableProperty, - close: kEnumerableProperty, - onmessage: kEnumerableProperty, - binaryType: kEnumerableProperty, - send: kEnumerableProperty, - extensions: kEnumerableProperty, - protocol: kEnumerableProperty, - [Symbol.toStringTag]: { - value: 'WebSocket', - writable: false, - enumerable: false, - configurable: true - } -}) +// https://webidl.spec.whatwg.org/#es-unsigned-long-long +webidl.converters['unsigned long long'] = function (V, prefix, argument) { + // 1. Let x be ? ConvertToInt(V, 64, "unsigned"). + const x = webidl.util.ConvertToInt(V, 64, 'unsigned', 0, prefix, argument) -Object.defineProperties(WebSocket, { - CONNECTING: staticPropertyDescriptors, - OPEN: staticPropertyDescriptors, - CLOSING: staticPropertyDescriptors, - CLOSED: staticPropertyDescriptors -}) + // 2. Return the IDL unsigned long long value that + // represents the same numeric value as x. + return x +} -webidl.converters['sequence'] = webidl.sequenceConverter( - webidl.converters.DOMString -) +// https://webidl.spec.whatwg.org/#es-unsigned-long +webidl.converters['unsigned long'] = function (V, prefix, argument) { + // 1. Let x be ? ConvertToInt(V, 32, "unsigned"). + const x = webidl.util.ConvertToInt(V, 32, 'unsigned', 0, prefix, argument) -webidl.converters['DOMString or sequence'] = function (V, prefix, argument) { - if (webidl.util.Type(V) === webidl.util.Types.OBJECT && Symbol.iterator in V) { - return webidl.converters['sequence'](V) - } + // 2. Return the IDL unsigned long value that + // represents the same numeric value as x. + return x +} - return webidl.converters.DOMString(V, prefix, argument) +// https://webidl.spec.whatwg.org/#es-unsigned-short +webidl.converters['unsigned short'] = function (V, prefix, argument, flags) { + // 1. Let x be ? ConvertToInt(V, 16, "unsigned"). + const x = webidl.util.ConvertToInt(V, 16, 'unsigned', flags, prefix, argument) + + // 2. Return the IDL unsigned short value that represents + // the same numeric value as x. + return x } -// This implements the proposal made in https://github.com/whatwg/websockets/issues/42 -webidl.converters.WebSocketInit = webidl.dictionaryConverter([ - { - key: 'protocols', - converter: webidl.converters['DOMString or sequence'], - defaultValue: () => [] - }, - { - key: 'dispatcher', - converter: webidl.converters.any, - defaultValue: () => getGlobalDispatcher() - }, - { - key: 'headers', - converter: webidl.nullableConverter(webidl.converters.HeadersInit) +// https://webidl.spec.whatwg.org/#idl-ArrayBuffer +webidl.converters.ArrayBuffer = function (V, prefix, argument, flags) { + // 1. If V is not an Object, or V does not have an + // [[ArrayBufferData]] internal slot, then throw a + // TypeError. + // 2. If IsSharedArrayBuffer(V) is true, then throw a + // TypeError. + // see: https://tc39.es/ecma262/#sec-properties-of-the-arraybuffer-instances + if ( + webidl.util.Type(V) !== OBJECT || + !types.isArrayBuffer(V) + ) { + throw webidl.errors.conversionFailed({ + prefix, + argument: `${argument} ("${webidl.util.Stringify(V)}")`, + types: ['ArrayBuffer'] + }) } -]) -webidl.converters['DOMString or sequence or WebSocketInit'] = function (V) { - if (webidl.util.Type(V) === webidl.util.Types.OBJECT && !(Symbol.iterator in V)) { - return webidl.converters.WebSocketInit(V) + // 3. If the conversion is not to an IDL type associated + // with the [AllowResizable] extended attribute, and + // IsResizableArrayBuffer(V) is true, then throw a + // TypeError. + if (!webidl.util.HasFlag(flags, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V)) { + throw webidl.errors.exception({ + header: prefix, + message: `${argument} cannot be a resizable ArrayBuffer.` + }) } - return { protocols: webidl.converters['DOMString or sequence'](V) } + // 4. Return the IDL ArrayBuffer value that is a + // reference to the same object as V. + return V } -webidl.converters.WebSocketSendData = function (V) { - if (webidl.util.Type(V) === webidl.util.Types.OBJECT) { - if (webidl.is.Blob(V)) { - return V - } +// https://webidl.spec.whatwg.org/#idl-SharedArrayBuffer +webidl.converters.SharedArrayBuffer = function (V, prefix, argument, flags) { + // 1. If V is not an Object, or V does not have an + // [[ArrayBufferData]] internal slot, then throw a + // TypeError. + // 2. If IsSharedArrayBuffer(V) is false, then throw a + // TypeError. + // see: https://tc39.es/ecma262/#sec-properties-of-the-sharedarraybuffer-instances + if ( + webidl.util.Type(V) !== OBJECT || + !types.isSharedArrayBuffer(V) + ) { + throw webidl.errors.conversionFailed({ + prefix, + argument: `${argument} ("${webidl.util.Stringify(V)}")`, + types: ['SharedArrayBuffer'] + }) + } - if (webidl.is.BufferSource(V)) { - return V - } + // 3. If the conversion is not to an IDL type associated + // with the [AllowResizable] extended attribute, and + // IsResizableArrayBuffer(V) is true, then throw a + // TypeError. + if (!webidl.util.HasFlag(flags, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V)) { + throw webidl.errors.exception({ + header: prefix, + message: `${argument} cannot be a resizable SharedArrayBuffer.` + }) } - return webidl.converters.USVString(V) + // 4. Return the IDL SharedArrayBuffer value that is a + // reference to the same object as V. + return V } -module.exports = { - WebSocket, - ping -} +// https://webidl.spec.whatwg.org/#dfn-typed-array-type +webidl.converters.TypedArray = function (V, T, prefix, argument, flags) { + // 1. Let T be the IDL type V is being converted to. + // 2. If Type(V) is not Object, or V does not have a + // [[TypedArrayName]] internal slot with a value + // equal to T’s name, then throw a TypeError. + if ( + webidl.util.Type(V) !== OBJECT || + !types.isTypedArray(V) || + V.constructor.name !== T.name + ) { + throw webidl.errors.conversionFailed({ + prefix, + argument: `${argument} ("${webidl.util.Stringify(V)}")`, + types: [T.name] + }) + } -/***/ }), + // 3. If the conversion is not to an IDL type associated + // with the [AllowShared] extended attribute, and + // IsSharedArrayBuffer(V.[[ViewedArrayBuffer]]) is + // true, then throw a TypeError. + if (!webidl.util.HasFlag(flags, webidl.attributes.AllowShared) && types.isSharedArrayBuffer(V.buffer)) { + throw webidl.errors.exception({ + header: prefix, + message: `${argument} cannot be a view on a shared array buffer.` + }) + } -/***/ 4307: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // 4. If the conversion is not to an IDL type associated + // with the [AllowResizable] extended attribute, and + // IsResizableArrayBuffer(V.[[ViewedArrayBuffer]]) is + // true, then throw a TypeError. + if (!webidl.util.HasFlag(flags, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V.buffer)) { + throw webidl.errors.exception({ + header: prefix, + message: `${argument} cannot be a view on a resizable array buffer.` + }) + } -const isWindows = process.platform === 'win32' || - process.env.OSTYPE === 'cygwin' || - process.env.OSTYPE === 'msys' + // 5. Return the IDL value of type T that is a reference + // to the same object as V. + return V +} -const path = __nccwpck_require__(6928) -const COLON = isWindows ? ';' : ':' -const isexe = __nccwpck_require__(1485) +// https://webidl.spec.whatwg.org/#idl-DataView +webidl.converters.DataView = function (V, prefix, argument, flags) { + // 1. If Type(V) is not Object, or V does not have a + // [[DataView]] internal slot, then throw a TypeError. + if (webidl.util.Type(V) !== OBJECT || !types.isDataView(V)) { + throw webidl.errors.conversionFailed({ + prefix, + argument: `${argument} ("${webidl.util.Stringify(V)}")`, + types: ['DataView'] + }) + } -const getNotFoundError = (cmd) => - Object.assign(new Error(`not found: ${cmd}`), { code: 'ENOENT' }) + // 2. If the conversion is not to an IDL type associated + // with the [AllowShared] extended attribute, and + // IsSharedArrayBuffer(V.[[ViewedArrayBuffer]]) is true, + // then throw a TypeError. + if (!webidl.util.HasFlag(flags, webidl.attributes.AllowShared) && types.isSharedArrayBuffer(V.buffer)) { + throw webidl.errors.exception({ + header: prefix, + message: `${argument} cannot be a view on a shared array buffer.` + }) + } -const getPathInfo = (cmd, opt) => { - const colon = opt.colon || COLON + // 3. If the conversion is not to an IDL type associated + // with the [AllowResizable] extended attribute, and + // IsResizableArrayBuffer(V.[[ViewedArrayBuffer]]) is + // true, then throw a TypeError. + if (!webidl.util.HasFlag(flags, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V.buffer)) { + throw webidl.errors.exception({ + header: prefix, + message: `${argument} cannot be a view on a resizable array buffer.` + }) + } - // If it has a slash, then we don't bother searching the pathenv. - // just check the file itself, and that's it. - const pathEnv = cmd.match(/\//) || isWindows && cmd.match(/\\/) ? [''] - : ( - [ - // windows always checks the cwd first - ...(isWindows ? [process.cwd()] : []), - ...(opt.path || process.env.PATH || - /* istanbul ignore next: very unusual */ '').split(colon), - ] - ) - const pathExtExe = isWindows - ? opt.pathExt || process.env.PATHEXT || '.EXE;.CMD;.BAT;.COM' - : '' - const pathExt = isWindows ? pathExtExe.split(colon) : [''] + // 4. Return the IDL DataView value that is a reference + // to the same object as V. + return V +} - if (isWindows) { - if (cmd.indexOf('.') !== -1 && pathExt[0] !== '') - pathExt.unshift('') +// https://webidl.spec.whatwg.org/#ArrayBufferView +webidl.converters.ArrayBufferView = function (V, prefix, argument, flags) { + if ( + webidl.util.Type(V) !== OBJECT || + !types.isArrayBufferView(V) + ) { + throw webidl.errors.conversionFailed({ + prefix, + argument: `${argument} ("${webidl.util.Stringify(V)}")`, + types: ['ArrayBufferView'] + }) } - return { - pathEnv, - pathExt, - pathExtExe, + if (!webidl.util.HasFlag(flags, webidl.attributes.AllowShared) && types.isSharedArrayBuffer(V.buffer)) { + throw webidl.errors.exception({ + header: prefix, + message: `${argument} cannot be a view on a shared array buffer.` + }) } -} -const which = (cmd, opt, cb) => { - if (typeof opt === 'function') { - cb = opt - opt = {} + if (!webidl.util.HasFlag(flags, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V.buffer)) { + throw webidl.errors.exception({ + header: prefix, + message: `${argument} cannot be a view on a resizable array buffer.` + }) } - if (!opt) - opt = {} - const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt) - const found = [] - - const step = i => new Promise((resolve, reject) => { - if (i === pathEnv.length) - return opt.all && found.length ? resolve(found) - : reject(getNotFoundError(cmd)) + return V +} - const ppRaw = pathEnv[i] - const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw +// https://webidl.spec.whatwg.org/#BufferSource +webidl.converters.BufferSource = function (V, prefix, argument, flags) { + if (types.isArrayBuffer(V)) { + return webidl.converters.ArrayBuffer(V, prefix, argument, flags) + } - const pCmd = path.join(pathPart, cmd) - const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd - : pCmd + if (types.isArrayBufferView(V)) { + flags &= ~webidl.attributes.AllowShared - resolve(subStep(p, i, 0)) - }) + return webidl.converters.ArrayBufferView(V, prefix, argument, flags) + } - const subStep = (p, i, ii) => new Promise((resolve, reject) => { - if (ii === pathExt.length) - return resolve(step(i + 1)) - const ext = pathExt[ii] - isexe(p + ext, { pathExt: pathExtExe }, (er, is) => { - if (!er && is) { - if (opt.all) - found.push(p + ext) - else - return resolve(p + ext) - } - return resolve(subStep(p, i, ii + 1)) + // Make this explicit for easier debugging + if (types.isSharedArrayBuffer(V)) { + throw webidl.errors.exception({ + header: prefix, + message: `${argument} cannot be a SharedArrayBuffer.` }) - }) + } - return cb ? step(0).then(res => cb(null, res), cb) : step(0) + throw webidl.errors.conversionFailed({ + prefix, + argument: `${argument} ("${webidl.util.Stringify(V)}")`, + types: ['ArrayBuffer', 'ArrayBufferView'] + }) } -const whichSync = (cmd, opt) => { - opt = opt || {} - - const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt) - const found = [] - - for (let i = 0; i < pathEnv.length; i ++) { - const ppRaw = pathEnv[i] - const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw - - const pCmd = path.join(pathPart, cmd) - const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd - : pCmd - - for (let j = 0; j < pathExt.length; j ++) { - const cur = p + pathExt[j] - try { - const is = isexe.sync(cur, { pathExt: pathExtExe }) - if (is) { - if (opt.all) - found.push(cur) - else - return cur - } - } catch (ex) {} - } +// https://webidl.spec.whatwg.org/#AllowSharedBufferSource +webidl.converters.AllowSharedBufferSource = function (V, prefix, argument, flags) { + if (types.isArrayBuffer(V)) { + return webidl.converters.ArrayBuffer(V, prefix, argument, flags) } - if (opt.all && found.length) - return found + if (types.isSharedArrayBuffer(V)) { + return webidl.converters.SharedArrayBuffer(V, prefix, argument, flags) + } - if (opt.nothrow) - return null + if (types.isArrayBufferView(V)) { + flags |= webidl.attributes.AllowShared + return webidl.converters.ArrayBufferView(V, prefix, argument, flags) + } - throw getNotFoundError(cmd) + throw webidl.errors.conversionFailed({ + prefix, + argument: `${argument} ("${webidl.util.Stringify(V)}")`, + types: ['ArrayBuffer', 'SharedArrayBuffer', 'ArrayBufferView'] + }) } -module.exports = which -which.sync = whichSync - +webidl.converters['sequence'] = webidl.sequenceConverter( + webidl.converters.ByteString +) -/***/ }), +webidl.converters['sequence>'] = webidl.sequenceConverter( + webidl.converters['sequence'] +) -/***/ 5074: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { - -"use strict"; - -/** - * Author: hustcer - * Created: 2022/04/28 18:50:20 - */ -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; - }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; - }; -})(); -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -const shelljs_1 = __importDefault(__nccwpck_require__(8007)); -const semver_1 = __importDefault(__nccwpck_require__(388)); -const core = __importStar(__nccwpck_require__(9239)); -const setup = __importStar(__nccwpck_require__(671)); -const plugins_1 = __nccwpck_require__(2850); -function main() { - return __awaiter(this, void 0, void 0, function* () { - try { - const versionSpec = core.getInput('version'); - console.log(`versionSpec: ${versionSpec}`); - const checkLatest = (core.getInput('check-latest') || 'false').toUpperCase() === 'TRUE'; - const enablePlugins = (core.getInput('enable-plugins') || 'false').toLowerCase(); - const rawFeatures = (core.getInput('features') || 'default').toLowerCase(); - if (rawFeatures !== 'default' && rawFeatures !== 'full') { - throw new Error(`Invalid features input: ${rawFeatures}`); - } - const features = rawFeatures; - const githubToken = core.getInput('github-token'); - const version = ['*', 'nightly'].includes(versionSpec) ? versionSpec : semver_1.default.valid(semver_1.default.coerce(versionSpec)); - console.log(`coerce version: ${version}`); - const ver = version === null ? undefined : version; - if (!ver) { - throw new Error(`Invalid version input: ${versionSpec}`); - } - const tool = yield setup.checkOrInstallTool({ - checkLatest, - githubToken, - enablePlugins, - bin: 'nu', - owner: 'nushell', - versionSpec: ver, - features: features, - name: version === 'nightly' ? 'nightly' : 'nushell', - }); - core.addPath(tool.dir); - // version: * --> 0.95.0; nightly --> nightly-56ed69a; 0.95 --> 0.95.0 - core.info(`Successfully setup Nu ${tool.version}, with ${features} features.`); - // Change to workspace directory (fallback to current dir for local runs). - const workspaceDir = process.env.GITHUB_WORKSPACE || process.cwd(); - shelljs_1.default.cd(workspaceDir); - console.log(`Current directory: ${process.cwd()}`); - yield (0, plugins_1.registerPlugins)(enablePlugins, tool.version); - } - catch (err) { - core.setFailed(err instanceof Error ? err.message : String(err)); - } - }); -} -main(); - - -/***/ }), +webidl.converters['record'] = webidl.recordConverter( + webidl.converters.ByteString, + webidl.converters.ByteString +) -/***/ 2850: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { +webidl.converters.Blob = webidl.interfaceConverter(webidl.is.Blob, 'Blob') -"use strict"; +webidl.converters.AbortSignal = webidl.interfaceConverter( + webidl.is.AbortSignal, + 'AbortSignal' +) -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.registerPlugins = registerPlugins; -const shelljs_1 = __importDefault(__nccwpck_require__(8007)); -const semver_1 = __importDefault(__nccwpck_require__(388)); -const node_fs_1 = __nccwpck_require__(3024); -/** - * Validates enablePlugins input to prevent command injection. - * Allows: 'true', 'false', or comma-separated plugin names (alphanumeric, underscore only). - */ -function validatePluginInput(input) { - // Allow 'true', 'false', or comma-separated identifiers (word characters only) - if (!/^(true|false|[\w]+(,[\w]+)*)$/i.test(input)) { - throw new Error(`Invalid enable-plugins input: "${input}". Only alphanumeric characters, underscores, and commas are allowed.`); - } -} /** - * Validates version string to prevent command injection. - * Allows: alphanumeric, dots, hyphens (e.g., "0.95.0", "nightly-56ed69a"). + * [LegacyTreatNonObjectAsNull] + * callback EventHandlerNonNull = any (Event event); + * typedef EventHandlerNonNull? EventHandler; + * @param {*} V */ -function validateVersion(version) { - if (!/^[\w.-]+$/.test(version)) { - throw new Error(`Invalid version format: "${version}". Only alphanumeric characters, dots, and hyphens are allowed.`); - } -} -const nu = String.raw; -const pluginRegisterScript = nu ` -#!/usr/bin/env nu - -# REF -# 1. https://github.com/actions/runner-images/blob/main/images/win/Windows2022-Readme.md - -# Config files are needed to avoid plugin register failure. -# The following lines were used to fix "× Plugin failed to load: No such file or directory (os error 2)" - -def main [ - enablePlugins: string, # Whether to enable or disable plugins. - version: string, # The tag name or version of the release to use. - --debug, # Whether to enable debug mode. - --is-legacy, # Whether to use the legacy plugin registration command for Nu 0.92.3 and below. -] { - - let useRegister = if $is_legacy { true } else { false } - let nuDir = $nu.current-exe | path dirname - print $'enablePlugins: ($enablePlugins) of Nu version: ($version)' - - if $debug { - print 'Output of ($nu.current-exe):'; print $nu.current-exe - print 'Directory contents:'; ls $nuDir | print +webidl.converters.EventHandlerNonNull = function (V) { + if (webidl.util.Type(V) !== OBJECT) { + return null } - # print $nu - # Create Nu config directory if it does not exist - if not ($nu.default-config-dir | path exists) { mkdir $nu.default-config-dir } - config env --default | save -f $nu.env-path - config nu --default | save -f $nu.config-path - # print (ls $nu.default-config-dir) - - let allPlugins = ls $nuDir | where name =~ nu_plugin - let filteredPlugins = if $enablePlugins == "'true'" or $enablePlugins == 'true' { - $allPlugins - } else { - $allPlugins | reduce -f [] {|it, acc| - # "split row . | first" used to handle binary with .exe extension - if $enablePlugins =~ ($it.name | path basename | split row . | first) { - $acc | append $it - } else { - $acc - } - } - } - - if $debug { - print $'Filtered plugins:'; print $filteredPlugins + // [I]f the value is not an object, it will be converted to null, and if the value is not callable, + // it will be converted to a callback function value that does nothing when called. + if (typeof V === 'function') { + return V } - $filteredPlugins | each {|plugin| - let p = $plugin.name | str replace -a \ / - if $useRegister { - echo ([('print "' + $'Registering ($p)' + '"') $'register ($p)'] | str join "\n") - } else { - echo ([('print "' + $'Registering ($p)' + '"') $'plugin add ($p)'] | str join "\n") - } - } - | str join "\n" - | save -rf do-register.nu + return () => {} } -`; -function registerPlugins(enablePlugins, version) { - return __awaiter(this, void 0, void 0, function* () { - if (enablePlugins === '' || enablePlugins === 'false') { - return; - } - // Validate inputs to prevent command injection - validatePluginInput(enablePlugins); - validateVersion(version); - const LEGACY_VERSION = '0.92.3'; - const script = 'register-plugins.nu'; - const isLegacyVersion = !version.includes('nightly') && semver_1.default.lte(version, LEGACY_VERSION); - const execOrThrow = (command) => { - const result = shelljs_1.default.exec(command); - if (result.code !== 0) { - throw new Error(`Command failed (${command}): ${result.stderr || result.stdout}`); - } - }; - yield node_fs_1.promises.writeFile(script, pluginRegisterScript); - try { - yield node_fs_1.promises.access(script, node_fs_1.constants.X_OK); - } - catch (_a) { - yield node_fs_1.promises.chmod(script, '755'); - console.log(`Fixed file permissions (-> 0o755) for ${script}`); - } - const registerCommand = isLegacyVersion - ? `nu ${script} "'${enablePlugins}'" ${version} --is-legacy` - : `nu ${script} "'${enablePlugins}'" ${version}`; - execOrThrow(registerCommand); - // console.log('Contents of `do-register.nu`:\n'); - // const content = shell.cat('do-register.nu'); - // console.log(content.toString()); - console.log('\nRegistering plugins...\n'); - execOrThrow('nu do-register.nu'); - console.log(`Plugins registered successfully for Nu ${version}.`); - }); +webidl.attributes = { + Clamp: 1 << 0, + EnforceRange: 1 << 1, + AllowShared: 1 << 2, + AllowResizable: 1 << 3, + LegacyNullToEmptyString: 1 << 4 } - -/***/ }), - -/***/ 671: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { - -"use strict"; - -/** - * Author: hustcer - * Created: 2022/04/28 18:50:20 - */ -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; - }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; - }; -})(); -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __asyncValues = (this && this.__asyncValues) || function (o) { - if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); - var m = o[Symbol.asyncIterator], i; - return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); - function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } - function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.checkOrInstallTool = checkOrInstallTool; -const globby_1 = __nccwpck_require__(6875); -const semver = __importStar(__nccwpck_require__(388)); -const path = __importStar(__nccwpck_require__(4379)); -const core = __importStar(__nccwpck_require__(9239)); -const tc = __importStar(__nccwpck_require__(0)); -const rest_1 = __nccwpck_require__(3918); -const undici_1 = __nccwpck_require__(7767); -const node_fs_1 = __nccwpck_require__(3024); -const PLATFORM_DEFAULT_MAP = { - darwin_x64: ['x86_64-apple-darwin', 'macOS.zip'], - darwin_arm64: ['aarch64-apple-darwin', 'macOS.zip'], - win32_x64: ['x86_64-pc-windows-msvc.zip', 'windows.zip'], - win32_arm64: ['aarch64-pc-windows-msvc.zip'], - linux_riscv64: ['riscv64gc-unknown-linux-gnu'], - linux_loong64: ['loongarch64-unknown-linux-gnu'], - linux_arm64: ['aarch64-unknown-linux-musl', 'aarch64-unknown-linux-gnu'], - linux_x64: ['x86_64-unknown-linux-musl', 'x86_64-unknown-linux-gnu', 'linux.tar.gz'], -}; -const PLATFORM_FULL_MAP = { - darwin_x64: ['x86_64-darwin-full'], - darwin_arm64: ['aarch64-darwin-full'], - win32_x64: ['x86_64-windows-msvc-full.zip'], - win32_arm64: ['aarch64-windows-msvc-full.zip'], - linux_arm64: ['aarch64-linux-gnu-full'], - linux_riscv64: ['riscv64gc-unknown-linux-gnu-full'], - linux_loong64: ['loongarch64-unknown-linux-gnu-full'], - linux_x64: ['x86_64-linux-musl-full', 'x86_64-linux-gnu-full'], -}; -// Singleton to ensure efficient use of connection pooling, resources, etc. -const proxyAgent = new undici_1.EnvHttpProxyAgent(); -/** - * @returns {string[]} possible nushell target specifiers for the current platform. - */ -function getTargets(features) { - const { arch, platform } = process; - const selector = `${platform}_${arch}`; - core.info(`Try to get assets for Nu: arch = ${arch}, platform = ${platform}, feature = ${features}`); - const platformMap = features === 'default' ? PLATFORM_DEFAULT_MAP : PLATFORM_FULL_MAP; - const targets = platformMap[selector]; - if (!targets) { - throw new Error(`Unsupported Nu target combination: arch = ${arch}, platform = ${platform}, feature = ${features}`); - } - return targets; -} -/** - * Filter the matching release for the given tool with the specified versionSpec. - * - * @param response the response to filter a release from with the given versionSpec. - * @returns {Release[]} a single GitHub release. - */ -// biome-ignore lint: Ignore -function filterMatch(response, versionSpec, features) { - const targets = getTargets(features); - return (response.data - // biome-ignore lint: Ignore - .map((rel) => { - const asset = rel.assets.find((ass) => targets.some((target) => ass.name.includes(target))); - if (asset) { - return { - version: rel.tag_name.replace(/^v/, ''), - downloadUrl: asset.browser_download_url, - }; - } - }) - .filter((rel) => rel && versionSpec ? semver.satisfies(rel.version, versionSpec) : true)); -} -/** - * Filter the latest matching release for the given tool. - * - * @param response the response to filter a latest release from. - * @returns {Release[]} a single GitHub release. - */ -// biome-ignore lint: Ignore -function filterLatest(response, features) { - const targets = getTargets(features); - const versions = response.data.map((r) => r.tag_name); - const latest = semver.rsort(versions)[0]; - return (response.data - .filter((rel) => rel && rel.tag_name === latest) - // biome-ignore lint: Ignore - .map((rel) => { - const asset = rel.assets.find((ass) => targets.some((target) => ass.name.includes(target))); - if (asset) { - return { - version: rel.tag_name.replace(/^v/, ''), - downloadUrl: asset.browser_download_url, - }; - } - })); -} -/** - * Filter the latest matching release for the given tool. - * - * @param response the response to filter a latest release from. - * @returns {Release[]} a single GitHub release. - */ -// biome-ignore lint: Ignore -function filterLatestNightly(response, features) { - const targets = getTargets(features); - const publishedAt = response.data.map((r) => r.published_at); - const sortedDates = publishedAt.sort((a, b) => new Date(b).getTime() - new Date(a).getTime()); - const latest = sortedDates[0]; - core.info(`Try to get latest nightly version published at: ${latest}`); - return (response.data - .filter((rel) => rel && rel.published_at === latest) - // biome-ignore lint: Ignore - .map((rel) => { - const asset = rel.assets.find((ass) => targets.some((target) => ass.name.includes(target))); - if (asset) { - return { - version: rel.tag_name.replace(/^v/, ''), - downloadUrl: asset.browser_download_url, - }; - } - })); -} -/** - * Fetch the latest matching release for the given tool. - * - * @param tool the tool to fetch a release for. - * - * @returns {Promise} a single GitHub release. - */ -function getRelease(tool) { - return __awaiter(this, void 0, void 0, function* () { - const { owner, name, versionSpec, checkLatest = false, features = 'default' } = tool; - const isNightly = versionSpec === 'nightly'; - const octokit = new rest_1.Octokit({ - auth: tool.githubToken, - // Use public GitHub API for Nushell assets query, make it work for GitHub Enterprise - baseUrl: 'https://api.github.com', - request: { fetch: proxyFetch }, - }); - return octokit - .paginate(octokit.repos.listReleases, { owner, repo: name }, (response, done) => { - const nightlyReleases = isNightly ? filterLatestNightly(response, features) : []; - const officialReleases = checkLatest - ? filterLatest(response, features) - : filterMatch(response, versionSpec, features); - const releases = isNightly ? nightlyReleases : officialReleases; - if (releases) { - done(); - } - return releases; - }) - .then((releases) => { - const release = releases.find((release) => release != null); - if (release === undefined) { - if (features === 'full') { - core.warning('The "full" feature was removed for Nu after v0.93.1, try to use "default" feature instead.'); - } - throw new Error(`No release for Nushell matching version specifier ${versionSpec} of ${features} feature.`); - } - return release; - }); - }); -} -function proxyFetch(url, opts) { - return (0, undici_1.fetch)(url, Object.assign(Object.assign({}, opts), { dispatcher: proxyAgent })); -} -function handleBadBinaryPermissions(tool, dir) { - return __awaiter(this, void 0, void 0, function* () { - const { name, bin } = tool; - if (process.platform !== 'win32') { - const findBin = () => __awaiter(this, void 0, void 0, function* () { - var _a, e_1, _b, _c; - const files = yield node_fs_1.promises.readdir(dir); - try { - for (var _d = true, files_1 = __asyncValues(files), files_1_1; files_1_1 = yield files_1.next(), _a = files_1_1.done, !_a; _d = true) { - _c = files_1_1.value; - _d = false; - const file = _c; - if (file.toLowerCase() === name.toLowerCase()) { - return file; - } - } - } - catch (e_1_1) { e_1 = { error: e_1_1 }; } - finally { - try { - if (!_d && !_a && (_b = files_1.return)) yield _b.call(files_1); - } - finally { if (e_1) throw e_1.error; } - } - return name; - }); - const binary = path.join(dir, bin ? bin : yield findBin()); - try { - yield node_fs_1.promises.access(binary, node_fs_1.constants.X_OK); - } - catch (_a) { - yield node_fs_1.promises.chmod(binary, '755'); - core.debug(`Fixed file permissions (-> 0o755) for ${binary}`); - } - } - }); -} -/** - * Checks the tool cache for the tool, and if it is missing - * fetches it from GitHub releases. - * - * @param tool the tool to check or install. - * - * @returns the directory containing the tool binary. - */ -function checkOrInstallTool(tool) { - return __awaiter(this, void 0, void 0, function* () { - const { name, versionSpec } = tool; - // first check if we have previously downloaded the tool - let dir = tc.find(name, versionSpec || '*'); - if (!dir) { - // find the latest release by querying GitHub API - const { version, downloadUrl } = yield getRelease(tool); - // download, extract, and cache the tool - const artifact = yield tc.downloadTool(downloadUrl); - core.debug(`Successfully downloaded ${name} v${version}`); - let extractDir; - if (downloadUrl.endsWith('.zip')) { - extractDir = yield tc.extractZip(artifact); - } - else { - extractDir = yield tc.extractTar(artifact); - } - core.debug(`Successfully extracted archive for ${name} v${version}`); - const paths = yield (0, globby_1.globby)([ - `${extractDir}/**/nu_plugin_*`, - // For nu v0.61~0.63 on Windows OS - path - .join(extractDir, '**', 'nu_plugin_*') - .replace(/\\/g, '/'), - ], { - unique: true, - absolute: true, - }); - const cacheSource = paths.length > 0 ? path.dirname(paths[0]) : extractDir; - if (paths.length === 0) { - core.warning('No nu_plugin_* binaries found; caching extracted directory instead.'); - } - dir = yield tc.cacheDir(cacheSource, name, version); - // handle bad binary permissions, the binary needs to be executable! - yield handleBadBinaryPermissions(tool, dir); - } - // is there a better way to get the version? - const version = path.basename(path.dirname(dir)); - return Object.assign({ version, dir }, tool); - }); +module.exports = { + webidl } /***/ }), -/***/ 2613: -/***/ ((module) => { - -"use strict"; -module.exports = require("assert"); - -/***/ }), +/***/ 7823: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -/***/ 290: -/***/ ((module) => { -"use strict"; -module.exports = require("async_hooks"); -/***/ }), +const { uid, states, sentCloseFrameState, emptyBuffer, opcodes } = __nccwpck_require__(1078) +const { parseExtensions, isClosed, isClosing, isEstablished, isConnecting, validateCloseCodeAndReason } = __nccwpck_require__(6667) +const { makeRequest } = __nccwpck_require__(4517) +const { fetching } = __nccwpck_require__(5288) +const { Headers, getHeadersList } = __nccwpck_require__(7754) +const { getDecodeSplit } = __nccwpck_require__(3106) +const { WebsocketFrameSend } = __nccwpck_require__(2222) +const assert = __nccwpck_require__(4589) +const { runtimeFeatures } = __nccwpck_require__(3895) -/***/ 181: -/***/ ((module) => { +const crypto = runtimeFeatures.has('crypto') + ? __nccwpck_require__(7598) + : null -"use strict"; -module.exports = require("buffer"); +let warningEmitted = false -/***/ }), +/** + * @see https://websockets.spec.whatwg.org/#concept-websocket-establish + * @param {URL} url + * @param {string|string[]} protocols + * @param {import('./websocket').Handler} handler + * @param {Partial} options + */ +function establishWebSocketConnection (url, protocols, client, handler, options) { + // 1. Let requestURL be a copy of url, with its scheme set to "http", if url’s + // scheme is "ws", and to "https" otherwise. + const requestURL = url -/***/ 5317: -/***/ ((module) => { + requestURL.protocol = url.protocol === 'ws:' ? 'http:' : 'https:' -"use strict"; -module.exports = require("child_process"); + // 2. Let request be a new request, whose URL is requestURL, client is client, + // service-workers mode is "none", referrer is "no-referrer", mode is + // "websocket", credentials mode is "include", cache mode is "no-store" , + // redirect mode is "error", and use-URL-credentials flag is set. + const request = makeRequest({ + urlList: [requestURL], + client, + serviceWorkers: 'none', + referrer: 'no-referrer', + mode: 'websocket', + credentials: 'include', + cache: 'no-store', + redirect: 'error', + useURLCredentials: true + }) -/***/ }), + // Note: undici extension, allow setting custom headers. + if (options.headers) { + const headersList = getHeadersList(new Headers(options.headers)) -/***/ 4236: -/***/ ((module) => { + request.headersList = headersList + } -"use strict"; -module.exports = require("console"); + // 3. Append (`Upgrade`, `websocket`) to request’s header list. + // 4. Append (`Connection`, `Upgrade`) to request’s header list. + // Note: both of these are handled by undici currently. + // https://github.com/nodejs/undici/blob/68c269c4144c446f3f1220951338daef4a6b5ec4/lib/client.js#L1397 -/***/ }), + // 5. Let keyValue be a nonce consisting of a randomly selected + // 16-byte value that has been forgiving-base64-encoded and + // isomorphic encoded. + const keyValue = crypto.randomBytes(16).toString('base64') -/***/ 6982: -/***/ ((module) => { + // 6. Append (`Sec-WebSocket-Key`, keyValue) to request’s + // header list. + request.headersList.append('sec-websocket-key', keyValue, true) -"use strict"; -module.exports = require("crypto"); + // 7. Append (`Sec-WebSocket-Version`, `13`) to request’s + // header list. + request.headersList.append('sec-websocket-version', '13', true) -/***/ }), + // 8. For each protocol in protocols, combine + // (`Sec-WebSocket-Protocol`, protocol) in request’s header + // list. + for (const protocol of protocols) { + request.headersList.append('sec-websocket-protocol', protocol, true) + } -/***/ 1637: -/***/ ((module) => { + // 9. Let permessageDeflate be a user-agent defined + // "permessage-deflate" extension header value. + // https://github.com/mozilla/gecko-dev/blob/ce78234f5e653a5d3916813ff990f053510227bc/netwerk/protocol/websocket/WebSocketChannel.cpp#L2673 + const permessageDeflate = 'permessage-deflate; client_max_window_bits' -"use strict"; -module.exports = require("diagnostics_channel"); + // 10. Append (`Sec-WebSocket-Extensions`, permessageDeflate) to + // request’s header list. + request.headersList.append('sec-websocket-extensions', permessageDeflate, true) -/***/ }), + // 11. Fetch request with useParallelQueue set to true, and + // processResponse given response being these steps: + const controller = fetching({ + request, + useParallelQueue: true, + dispatcher: options.dispatcher, + processResponse (response) { + // 1. If response is a network error or its status is not 101, + // fail the WebSocket connection. + // if (response.type === 'error' || ((response.socket?.session != null && response.status !== 200) && response.status !== 101)) { + if (response.type === 'error' || response.status !== 101) { + // The presence of a session property on the socket indicates HTTP2 + // HTTP1 + if (response.socket?.session == null) { + failWebsocketConnection(handler, 1002, 'Received network error or non-101 status code.', response.error) + return + } -/***/ 4434: -/***/ ((module) => { + // HTTP2 + if (response.status !== 200) { + failWebsocketConnection(handler, 1002, 'Received network error or non-200 status code.', response.error) + return + } + } -"use strict"; -module.exports = require("events"); + if (warningEmitted === false && response.socket?.session != null) { + process.emitWarning('WebSocket over HTTP2 is experimental, and subject to change.', 'ExperimentalWarning') + warningEmitted = true + } -/***/ }), + // 2. If protocols is not the empty list and extracting header + // list values given `Sec-WebSocket-Protocol` and response’s + // header list results in null, failure, or the empty byte + // sequence, then fail the WebSocket connection. + if (protocols.length !== 0 && !response.headersList.get('Sec-WebSocket-Protocol')) { + failWebsocketConnection(handler, 1002, 'Server did not respond with sent protocols.') + return + } -/***/ 9896: -/***/ ((module) => { + // 3. Follow the requirements stated step 2 to step 6, inclusive, + // of the last set of steps in section 4.1 of The WebSocket + // Protocol to validate response. This either results in fail + // the WebSocket connection or the WebSocket connection is + // established. -"use strict"; -module.exports = require("fs"); + // 2. If the response lacks an |Upgrade| header field or the |Upgrade| + // header field contains a value that is not an ASCII case- + // insensitive match for the value "websocket", the client MUST + // _Fail the WebSocket Connection_. + // For H2, no upgrade header is expected. + if (response.socket.session == null && response.headersList.get('Upgrade')?.toLowerCase() !== 'websocket') { + failWebsocketConnection(handler, 1002, 'Server did not set Upgrade header to "websocket".') + return + } -/***/ }), + // 3. If the response lacks a |Connection| header field or the + // |Connection| header field doesn't contain a token that is an + // ASCII case-insensitive match for the value "Upgrade", the client + // MUST _Fail the WebSocket Connection_. + // For H2, no connection header is expected. + if (response.socket.session == null && response.headersList.get('Connection')?.toLowerCase() !== 'upgrade') { + failWebsocketConnection(handler, 1002, 'Server did not set Connection header to "upgrade".') + return + } -/***/ 8611: -/***/ ((module) => { + // 4. If the response lacks a |Sec-WebSocket-Accept| header field or + // the |Sec-WebSocket-Accept| contains a value other than the + // base64-encoded SHA-1 of the concatenation of the |Sec-WebSocket- + // Key| (as a string, not base64-decoded) with the string "258EAFA5- + // E914-47DA-95CA-C5AB0DC85B11" but ignoring any leading and + // trailing whitespace, the client MUST _Fail the WebSocket + // Connection_. + const secWSAccept = response.headersList.get('Sec-WebSocket-Accept') + const digest = crypto.hash('sha1', keyValue + uid, 'base64') + if (secWSAccept !== digest) { + failWebsocketConnection(handler, 1002, 'Incorrect hash received in Sec-WebSocket-Accept header.') + return + } -"use strict"; -module.exports = require("http"); + // 5. If the response includes a |Sec-WebSocket-Extensions| header + // field and this header field indicates the use of an extension + // that was not present in the client's handshake (the server has + // indicated an extension not requested by the client), the client + // MUST _Fail the WebSocket Connection_. (The parsing of this + // header field to determine which extensions are requested is + // discussed in Section 9.1.) + const secExtension = response.headersList.get('Sec-WebSocket-Extensions') + let extensions -/***/ }), + if (secExtension !== null) { + extensions = parseExtensions(secExtension) -/***/ 5675: -/***/ ((module) => { - -"use strict"; -module.exports = require("http2"); - -/***/ }), - -/***/ 5692: -/***/ ((module) => { - -"use strict"; -module.exports = require("https"); - -/***/ }), + if (!extensions.has('permessage-deflate')) { + failWebsocketConnection(handler, 1002, 'Sec-WebSocket-Extensions header does not match.') + return + } + } -/***/ 9278: -/***/ ((module) => { + // 6. If the response includes a |Sec-WebSocket-Protocol| header field + // and this header field indicates the use of a subprotocol that was + // not present in the client's handshake (the server has indicated a + // subprotocol not requested by the client), the client MUST _Fail + // the WebSocket Connection_. + const secProtocol = response.headersList.get('Sec-WebSocket-Protocol') -"use strict"; -module.exports = require("net"); + if (secProtocol !== null) { + const requestProtocols = getDecodeSplit('sec-websocket-protocol', request.headersList) -/***/ }), + // The client can request that the server use a specific subprotocol by + // including the |Sec-WebSocket-Protocol| field in its handshake. If it + // is specified, the server needs to include the same field and one of + // the selected subprotocol values in its response for the connection to + // be established. + if (!requestProtocols.includes(secProtocol)) { + failWebsocketConnection(handler, 1002, 'Protocol was not set in the opening handshake.') + return + } + } -/***/ 4589: -/***/ ((module) => { + response.socket.on('data', handler.onSocketData) + response.socket.on('close', handler.onSocketClose) + response.socket.on('error', handler.onSocketError) -"use strict"; -module.exports = require("node:assert"); + handler.wasEverConnected = true + handler.onConnectionEstablished(response, extensions) + } + }) -/***/ }), + return controller +} -/***/ 6698: -/***/ ((module) => { +/** + * @see https://whatpr.org/websockets/48.html#close-the-websocket + * @param {import('./websocket').Handler} object + * @param {number} [code=null] + * @param {string} [reason=''] + */ +function closeWebSocketConnection (object, code, reason, validate = false) { + // 1. If code was not supplied, let code be null. + code ??= null -"use strict"; -module.exports = require("node:async_hooks"); + // 2. If reason was not supplied, let reason be the empty string. + reason ??= '' -/***/ }), + // 3. Validate close code and reason with code and reason. + if (validate) validateCloseCodeAndReason(code, reason) -/***/ 4573: -/***/ ((module) => { + // 4. Run the first matching steps from the following list: + // - If object’s ready state is CLOSING (2) or CLOSED (3) + // - If the WebSocket connection is not yet established [WSP] + // - If the WebSocket closing handshake has not yet been started [WSP] + // - Otherwise + if (isClosed(object.readyState) || isClosing(object.readyState)) { + // Do nothing. + } else if (!isEstablished(object.readyState)) { + // Fail the WebSocket connection and set object’s ready state to CLOSING (2). [WSP] + failWebsocketConnection(object) + object.readyState = states.CLOSING + } else if (!object.closeState.has(sentCloseFrameState.SENT) && !object.closeState.has(sentCloseFrameState.RECEIVED)) { + // Upon either sending or receiving a Close control frame, it is said + // that _The WebSocket Closing Handshake is Started_ and that the + // WebSocket connection is in the CLOSING state. -"use strict"; -module.exports = require("node:buffer"); + const frame = new WebsocketFrameSend() -/***/ }), + // If neither code nor reason is present, the WebSocket Close + // message must not have a body. -/***/ 7540: -/***/ ((module) => { + // If code is present, then the status code to use in the + // WebSocket Close message must be the integer given by code. + // If code is null and reason is the empty string, the WebSocket Close frame must not have a body. + // If reason is non-empty but code is null, then set code to 1000 ("Normal Closure"). + if (reason.length !== 0 && code === null) { + code = 1000 + } -"use strict"; -module.exports = require("node:console"); + // If code is set, then the status code to use in the WebSocket Close frame must be the integer given by code. + assert(code === null || Number.isInteger(code)) -/***/ }), + if (code === null && reason.length === 0) { + frame.frameData = emptyBuffer + } else if (code !== null && reason === null) { + frame.frameData = Buffer.allocUnsafe(2) + frame.frameData.writeUInt16BE(code, 0) + } else if (code !== null && reason !== null) { + // If reason is also present, then reasonBytes must be + // provided in the Close message after the status code. + frame.frameData = Buffer.allocUnsafe(2 + Buffer.byteLength(reason)) + frame.frameData.writeUInt16BE(code, 0) + // the body MAY contain UTF-8-encoded data with value /reason/ + frame.frameData.write(reason, 2, 'utf-8') + } else { + frame.frameData = emptyBuffer + } -/***/ 7598: -/***/ ((module) => { + object.socket.write(frame.createFrame(opcodes.CLOSE)) -"use strict"; -module.exports = require("node:crypto"); + object.closeState.add(sentCloseFrameState.SENT) -/***/ }), + // Upon either sending or receiving a Close control frame, it is said + // that _The WebSocket Closing Handshake is Started_ and that the + // WebSocket connection is in the CLOSING state. + object.readyState = states.CLOSING + } else { + // Set object’s ready state to CLOSING (2). + object.readyState = states.CLOSING + } +} -/***/ 3053: -/***/ ((module) => { +/** + * @param {import('./websocket').Handler} handler + * @param {number} code + * @param {string|undefined} reason + * @param {unknown} cause + * @returns {void} + */ +function failWebsocketConnection (handler, code, reason, cause) { + // If _The WebSocket Connection is Established_ prior to the point where + // the endpoint is required to _Fail the WebSocket Connection_, the + // endpoint SHOULD send a Close frame with an appropriate status code + // (Section 7.4) before proceeding to _Close the WebSocket Connection_. + if (isEstablished(handler.readyState)) { + closeWebSocketConnection(handler, code, reason, false) + } -"use strict"; -module.exports = require("node:diagnostics_channel"); + handler.controller.abort() -/***/ }), + if (isConnecting(handler.readyState)) { + // If the connection was not established, we must still emit an 'error' and 'close' events + handler.onSocketClose() + } else if (handler.socket?.destroyed === false) { + handler.socket.destroy() + } +} -/***/ 610: -/***/ ((module) => { +module.exports = { + establishWebSocketConnection, + failWebsocketConnection, + closeWebSocketConnection +} -"use strict"; -module.exports = require("node:dns"); /***/ }), -/***/ 8474: +/***/ 1078: /***/ ((module) => { -"use strict"; -module.exports = require("node:events"); -/***/ }), -/***/ 3024: -/***/ ((module) => { +/** + * This is a Globally Unique Identifier unique used to validate that the + * endpoint accepts websocket connections. + * @see https://www.rfc-editor.org/rfc/rfc6455.html#section-1.3 + * @type {'258EAFA5-E914-47DA-95CA-C5AB0DC85B11'} + */ +const uid = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11' -"use strict"; -module.exports = require("node:fs"); +/** + * @type {PropertyDescriptor} + */ +const staticPropertyDescriptors = { + enumerable: true, + writable: false, + configurable: false +} -/***/ }), +/** + * The states of the WebSocket connection. + * + * @readonly + * @enum + * @property {0} CONNECTING + * @property {1} OPEN + * @property {2} CLOSING + * @property {3} CLOSED + */ +const states = { + CONNECTING: 0, + OPEN: 1, + CLOSING: 2, + CLOSED: 3 +} -/***/ 1455: -/***/ ((module) => { +/** + * @readonly + * @enum + * @property {0} NOT_SENT + * @property {1} PROCESSING + * @property {2} SENT + */ +const sentCloseFrameState = { + SENT: 1, + RECEIVED: 2 +} -"use strict"; -module.exports = require("node:fs/promises"); +/** + * The WebSocket opcodes. + * + * @readonly + * @enum + * @property {0x0} CONTINUATION + * @property {0x1} TEXT + * @property {0x2} BINARY + * @property {0x8} CLOSE + * @property {0x9} PING + * @property {0xA} PONG + * @see https://datatracker.ietf.org/doc/html/rfc6455#section-5.2 + */ +const opcodes = { + CONTINUATION: 0x0, + TEXT: 0x1, + BINARY: 0x2, + CLOSE: 0x8, + PING: 0x9, + PONG: 0xA +} -/***/ }), +/** + * The maximum value for an unsigned 16-bit integer. + * + * @type {65535} 2 ** 16 - 1 + */ +const maxUnsigned16Bit = 65535 -/***/ 7067: -/***/ ((module) => { +/** + * The states of the parser. + * + * @readonly + * @enum + * @property {0} INFO + * @property {2} PAYLOADLENGTH_16 + * @property {3} PAYLOADLENGTH_64 + * @property {4} READ_DATA + */ +const parserStates = { + INFO: 0, + PAYLOADLENGTH_16: 2, + PAYLOADLENGTH_64: 3, + READ_DATA: 4 +} -"use strict"; -module.exports = require("node:http"); +/** + * An empty buffer. + * + * @type {Buffer} + */ +const emptyBuffer = Buffer.allocUnsafe(0) -/***/ }), +/** + * @readonly + * @property {1} text + * @property {2} typedArray + * @property {3} arrayBuffer + * @property {4} blob + */ +const sendHints = { + text: 1, + typedArray: 2, + arrayBuffer: 3, + blob: 4 +} -/***/ 2467: -/***/ ((module) => { +module.exports = { + uid, + sentCloseFrameState, + staticPropertyDescriptors, + states, + opcodes, + maxUnsigned16Bit, + parserStates, + emptyBuffer, + sendHints +} -"use strict"; -module.exports = require("node:http2"); /***/ }), -/***/ 7030: -/***/ ((module) => { - -"use strict"; -module.exports = require("node:net"); - -/***/ }), +/***/ 1954: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -/***/ 4379: -/***/ ((module) => { -"use strict"; -module.exports = require("node:path"); -/***/ }), +const { webidl } = __nccwpck_require__(909) +const { kEnumerableProperty } = __nccwpck_require__(2550) +const { kConstruct } = __nccwpck_require__(8261) -/***/ 643: -/***/ ((module) => { +/** + * @see https://html.spec.whatwg.org/multipage/comms.html#messageevent + */ +class MessageEvent extends Event { + #eventInit -"use strict"; -module.exports = require("node:perf_hooks"); + constructor (type, eventInitDict = {}) { + if (type === kConstruct) { + super(arguments[1], arguments[2]) + webidl.util.markAsUncloneable(this) + return + } -/***/ }), + const prefix = 'MessageEvent constructor' + webidl.argumentLengthCheck(arguments, 1, prefix) -/***/ 1792: -/***/ ((module) => { + type = webidl.converters.DOMString(type, prefix, 'type') + eventInitDict = webidl.converters.MessageEventInit(eventInitDict, prefix, 'eventInitDict') -"use strict"; -module.exports = require("node:querystring"); + super(type, eventInitDict) -/***/ }), + this.#eventInit = eventInitDict + webidl.util.markAsUncloneable(this) + } -/***/ 99: -/***/ ((module) => { + get data () { + webidl.brandCheck(this, MessageEvent) -"use strict"; -module.exports = require("node:sqlite"); + return this.#eventInit.data + } -/***/ }), + get origin () { + webidl.brandCheck(this, MessageEvent) -/***/ 7075: -/***/ ((module) => { + return this.#eventInit.origin + } -"use strict"; -module.exports = require("node:stream"); + get lastEventId () { + webidl.brandCheck(this, MessageEvent) -/***/ }), + return this.#eventInit.lastEventId + } -/***/ 7997: -/***/ ((module) => { + get source () { + webidl.brandCheck(this, MessageEvent) -"use strict"; -module.exports = require("node:timers"); + return this.#eventInit.source + } -/***/ }), + get ports () { + webidl.brandCheck(this, MessageEvent) -/***/ 1692: -/***/ ((module) => { + if (!Object.isFrozen(this.#eventInit.ports)) { + Object.freeze(this.#eventInit.ports) + } -"use strict"; -module.exports = require("node:tls"); + return this.#eventInit.ports + } -/***/ }), + initMessageEvent ( + type, + bubbles = false, + cancelable = false, + data = null, + origin = '', + lastEventId = '', + source = null, + ports = [] + ) { + webidl.brandCheck(this, MessageEvent) -/***/ 7975: -/***/ ((module) => { + webidl.argumentLengthCheck(arguments, 1, 'MessageEvent.initMessageEvent') -"use strict"; -module.exports = require("node:util"); + return new MessageEvent(type, { + bubbles, cancelable, data, origin, lastEventId, source, ports + }) + } -/***/ }), + static createFastMessageEvent (type, init) { + const messageEvent = new MessageEvent(kConstruct, type, init) + messageEvent.#eventInit = init + messageEvent.#eventInit.data ??= null + messageEvent.#eventInit.origin ??= '' + messageEvent.#eventInit.lastEventId ??= '' + messageEvent.#eventInit.source ??= null + messageEvent.#eventInit.ports ??= [] + return messageEvent + } +} -/***/ 3429: -/***/ ((module) => { +const { createFastMessageEvent } = MessageEvent +delete MessageEvent.createFastMessageEvent -"use strict"; -module.exports = require("node:util/types"); +/** + * @see https://websockets.spec.whatwg.org/#the-closeevent-interface + */ +class CloseEvent extends Event { + #eventInit -/***/ }), + constructor (type, eventInitDict = {}) { + const prefix = 'CloseEvent constructor' + webidl.argumentLengthCheck(arguments, 1, prefix) -/***/ 5919: -/***/ ((module) => { + type = webidl.converters.DOMString(type, prefix, 'type') + eventInitDict = webidl.converters.CloseEventInit(eventInitDict) -"use strict"; -module.exports = require("node:worker_threads"); + super(type, eventInitDict) -/***/ }), + this.#eventInit = eventInitDict + webidl.util.markAsUncloneable(this) + } -/***/ 8522: -/***/ ((module) => { + get wasClean () { + webidl.brandCheck(this, CloseEvent) -"use strict"; -module.exports = require("node:zlib"); + return this.#eventInit.wasClean + } -/***/ }), + get code () { + webidl.brandCheck(this, CloseEvent) -/***/ 857: -/***/ ((module) => { + return this.#eventInit.code + } -"use strict"; -module.exports = require("os"); + get reason () { + webidl.brandCheck(this, CloseEvent) -/***/ }), + return this.#eventInit.reason + } +} -/***/ 6928: -/***/ ((module) => { +// https://html.spec.whatwg.org/multipage/webappapis.html#the-errorevent-interface +class ErrorEvent extends Event { + #eventInit -"use strict"; -module.exports = require("path"); + constructor (type, eventInitDict) { + const prefix = 'ErrorEvent constructor' + webidl.argumentLengthCheck(arguments, 1, prefix) -/***/ }), + super(type, eventInitDict) + webidl.util.markAsUncloneable(this) -/***/ 2987: -/***/ ((module) => { + type = webidl.converters.DOMString(type, prefix, 'type') + eventInitDict = webidl.converters.ErrorEventInit(eventInitDict ?? {}) -"use strict"; -module.exports = require("perf_hooks"); + this.#eventInit = eventInitDict + } -/***/ }), + get message () { + webidl.brandCheck(this, ErrorEvent) -/***/ 3480: -/***/ ((module) => { + return this.#eventInit.message + } -"use strict"; -module.exports = require("querystring"); + get filename () { + webidl.brandCheck(this, ErrorEvent) -/***/ }), + return this.#eventInit.filename + } -/***/ 2203: -/***/ ((module) => { + get lineno () { + webidl.brandCheck(this, ErrorEvent) -"use strict"; -module.exports = require("stream"); + return this.#eventInit.lineno + } -/***/ }), + get colno () { + webidl.brandCheck(this, ErrorEvent) -/***/ 3774: -/***/ ((module) => { + return this.#eventInit.colno + } -"use strict"; -module.exports = require("stream/web"); + get error () { + webidl.brandCheck(this, ErrorEvent) -/***/ }), + return this.#eventInit.error + } +} -/***/ 3193: -/***/ ((module) => { +Object.defineProperties(MessageEvent.prototype, { + [Symbol.toStringTag]: { + value: 'MessageEvent', + configurable: true + }, + data: kEnumerableProperty, + origin: kEnumerableProperty, + lastEventId: kEnumerableProperty, + source: kEnumerableProperty, + ports: kEnumerableProperty, + initMessageEvent: kEnumerableProperty +}) -"use strict"; -module.exports = require("string_decoder"); +Object.defineProperties(CloseEvent.prototype, { + [Symbol.toStringTag]: { + value: 'CloseEvent', + configurable: true + }, + reason: kEnumerableProperty, + code: kEnumerableProperty, + wasClean: kEnumerableProperty +}) -/***/ }), +Object.defineProperties(ErrorEvent.prototype, { + [Symbol.toStringTag]: { + value: 'ErrorEvent', + configurable: true + }, + message: kEnumerableProperty, + filename: kEnumerableProperty, + lineno: kEnumerableProperty, + colno: kEnumerableProperty, + error: kEnumerableProperty +}) -/***/ 3557: -/***/ ((module) => { +webidl.converters.MessagePort = webidl.interfaceConverter( + webidl.is.MessagePort, + 'MessagePort' +) -"use strict"; -module.exports = require("timers"); +webidl.converters['sequence'] = webidl.sequenceConverter( + webidl.converters.MessagePort +) -/***/ }), - -/***/ 4756: -/***/ ((module) => { - -"use strict"; -module.exports = require("tls"); - -/***/ }), - -/***/ 7016: -/***/ ((module) => { - -"use strict"; -module.exports = require("url"); - -/***/ }), - -/***/ 9023: -/***/ ((module) => { - -"use strict"; -module.exports = require("util"); - -/***/ }), +const eventInit = [ + { + key: 'bubbles', + converter: webidl.converters.boolean, + defaultValue: () => false + }, + { + key: 'cancelable', + converter: webidl.converters.boolean, + defaultValue: () => false + }, + { + key: 'composed', + converter: webidl.converters.boolean, + defaultValue: () => false + } +] -/***/ 8253: -/***/ ((module) => { +webidl.converters.MessageEventInit = webidl.dictionaryConverter([ + ...eventInit, + { + key: 'data', + converter: webidl.converters.any, + defaultValue: () => null + }, + { + key: 'origin', + converter: webidl.converters.USVString, + defaultValue: () => '' + }, + { + key: 'lastEventId', + converter: webidl.converters.DOMString, + defaultValue: () => '' + }, + { + key: 'source', + // Node doesn't implement WindowProxy or ServiceWorker, so the only + // valid value for source is a MessagePort. + converter: webidl.nullableConverter(webidl.converters.MessagePort), + defaultValue: () => null + }, + { + key: 'ports', + converter: webidl.converters['sequence'], + defaultValue: () => [] + } +]) -"use strict"; -module.exports = require("util/types"); +webidl.converters.CloseEventInit = webidl.dictionaryConverter([ + ...eventInit, + { + key: 'wasClean', + converter: webidl.converters.boolean, + defaultValue: () => false + }, + { + key: 'code', + converter: webidl.converters['unsigned short'], + defaultValue: () => 0 + }, + { + key: 'reason', + converter: webidl.converters.USVString, + defaultValue: () => '' + } +]) -/***/ }), +webidl.converters.ErrorEventInit = webidl.dictionaryConverter([ + ...eventInit, + { + key: 'message', + converter: webidl.converters.DOMString, + defaultValue: () => '' + }, + { + key: 'filename', + converter: webidl.converters.USVString, + defaultValue: () => '' + }, + { + key: 'lineno', + converter: webidl.converters['unsigned long'], + defaultValue: () => 0 + }, + { + key: 'colno', + converter: webidl.converters['unsigned long'], + defaultValue: () => 0 + }, + { + key: 'error', + converter: webidl.converters.any + } +]) -/***/ 8167: -/***/ ((module) => { +module.exports = { + MessageEvent, + CloseEvent, + ErrorEvent, + createFastMessageEvent +} -"use strict"; -module.exports = require("worker_threads"); /***/ }), -/***/ 3106: -/***/ ((module) => { +/***/ 2222: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -module.exports = require("zlib"); -/***/ }), -/***/ 7988: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +const { runtimeFeatures } = __nccwpck_require__(3895) +const { maxUnsigned16Bit, opcodes } = __nccwpck_require__(1078) -"use strict"; +const BUFFER_SIZE = 8 * 1024 +let buffer = null +let bufIdx = BUFFER_SIZE -const WritableStream = (__nccwpck_require__(7075).Writable) -const inherits = (__nccwpck_require__(7975).inherits) +const randomFillSync = runtimeFeatures.has('crypto') + ? (__nccwpck_require__(7598).randomFillSync) + // not full compatibility, but minimum. + : function randomFillSync (buffer, _offset, _size) { + for (let i = 0; i < buffer.length; ++i) { + buffer[i] = Math.random() * 255 | 0 + } + return buffer + } -const StreamSearch = __nccwpck_require__(5202) +function generateMask () { + if (bufIdx === BUFFER_SIZE) { + bufIdx = 0 + randomFillSync((buffer ??= Buffer.allocUnsafeSlow(BUFFER_SIZE)), 0, BUFFER_SIZE) + } + return [buffer[bufIdx++], buffer[bufIdx++], buffer[bufIdx++], buffer[bufIdx++]] +} -const PartStream = __nccwpck_require__(6050) -const HeaderParser = __nccwpck_require__(7497) +class WebsocketFrameSend { + /** + * @param {Buffer|undefined} data + */ + constructor (data) { + this.frameData = data + } -const DASH = 45 -const B_ONEDASH = Buffer.from('-') -const B_CRLF = Buffer.from('\r\n') -const EMPTY_FN = function () {} + createFrame (opcode) { + const frameData = this.frameData + const maskKey = generateMask() + const bodyLength = frameData?.byteLength ?? 0 -function Dicer (cfg) { - if (!(this instanceof Dicer)) { return new Dicer(cfg) } - WritableStream.call(this, cfg) + /** @type {number} */ + let payloadLength = bodyLength // 0-125 + let offset = 6 - if (!cfg || (!cfg.headerFirst && typeof cfg.boundary !== 'string')) { throw new TypeError('Boundary required') } + if (bodyLength > maxUnsigned16Bit) { + offset += 8 // payload length is next 8 bytes + payloadLength = 127 + } else if (bodyLength > 125) { + offset += 2 // payload length is next 2 bytes + payloadLength = 126 + } - if (typeof cfg.boundary === 'string') { this.setBoundary(cfg.boundary) } else { this._bparser = undefined } + const buffer = Buffer.allocUnsafe(bodyLength + offset) - this._headerFirst = cfg.headerFirst + // Clear first 2 bytes, everything else is overwritten + buffer[0] = buffer[1] = 0 + buffer[0] |= 0x80 // FIN + buffer[0] = (buffer[0] & 0xF0) + opcode // opcode - this._dashes = 0 - this._parts = 0 - this._finished = false - this._realFinish = false - this._isPreamble = true - this._justMatched = false - this._firstWrite = true - this._inHeader = true - this._part = undefined - this._cb = undefined - this._ignoreData = false - this._partOpts = { highWaterMark: cfg.partHwm } - this._pause = false + /*! ws. MIT License. Einar Otto Stangvik */ + buffer[offset - 4] = maskKey[0] + buffer[offset - 3] = maskKey[1] + buffer[offset - 2] = maskKey[2] + buffer[offset - 1] = maskKey[3] - const self = this - this._hparser = new HeaderParser(cfg) - this._hparser.on('header', function (header) { - self._inHeader = false - self._part.emit('header', header) - }) -} -inherits(Dicer, WritableStream) + buffer[1] = payloadLength -Dicer.prototype.emit = function (ev) { - if (ev === 'finish' && !this._realFinish) { - if (!this._finished) { - const self = this - process.nextTick(function () { - self.emit('error', new Error('Unexpected end of multipart data')) - if (self._part && !self._ignoreData) { - const type = (self._isPreamble ? 'Preamble' : 'Part') - self._part.emit('error', new Error(type + ' terminated early due to unexpected end of multipart data')) - self._part.push(null) - process.nextTick(function () { - self._realFinish = true - self.emit('finish') - self._realFinish = false - }) - return - } - self._realFinish = true - self.emit('finish') - self._realFinish = false - }) + if (payloadLength === 126) { + buffer.writeUInt16BE(bodyLength, 2) + } else if (payloadLength === 127) { + // Clear extended payload length + buffer[2] = buffer[3] = 0 + buffer.writeUIntBE(bodyLength, 4, 6) } - } else { WritableStream.prototype.emit.apply(this, arguments) } -} -Dicer.prototype._write = function (data, encoding, cb) { - // ignore unexpected data (e.g. extra trailer data after finished) - if (!this._hparser && !this._bparser) { return cb() } + buffer[1] |= 0x80 // MASK - if (this._headerFirst && this._isPreamble) { - if (!this._part) { - this._part = new PartStream(this._partOpts) - if (this.listenerCount('preamble') !== 0) { this.emit('preamble', this._part) } else { this._ignore() } + // mask body + for (let i = 0; i < bodyLength; ++i) { + buffer[offset + i] = frameData[i] ^ maskKey[i & 3] } - const r = this._hparser.push(data) - if (!this._inHeader && r !== undefined && r < data.length) { data = data.slice(r) } else { return cb() } - } - // allows for "easier" testing - if (this._firstWrite) { - this._bparser.push(B_CRLF) - this._firstWrite = false + return buffer } - this._bparser.push(data) + /** + * @param {Uint8Array} buffer + */ + static createFastTextFrame (buffer) { + const maskKey = generateMask() - if (this._pause) { this._cb = cb } else { cb() } -} + const bodyLength = buffer.length -Dicer.prototype.reset = function () { - this._part = undefined - this._bparser = undefined - this._hparser = undefined -} + // mask body + for (let i = 0; i < bodyLength; ++i) { + buffer[i] ^= maskKey[i & 3] + } -Dicer.prototype.setBoundary = function (boundary) { - const self = this - this._bparser = new StreamSearch('\r\n--' + boundary) - this._bparser.on('info', function (isMatch, data, start, end) { - self._oninfo(isMatch, data, start, end) - }) -} + let payloadLength = bodyLength + let offset = 6 -Dicer.prototype._ignore = function () { - if (this._part && !this._ignoreData) { - this._ignoreData = true - this._part.on('error', EMPTY_FN) - // we must perform some kind of read on the stream even though we are - // ignoring the data, otherwise node's Readable stream will not emit 'end' - // after pushing null to the stream - this._part.resume() - } -} + if (bodyLength > maxUnsigned16Bit) { + offset += 8 // payload length is next 8 bytes + payloadLength = 127 + } else if (bodyLength > 125) { + offset += 2 // payload length is next 2 bytes + payloadLength = 126 + } + const head = Buffer.allocUnsafeSlow(offset) -Dicer.prototype._oninfo = function (isMatch, data, start, end) { - let buf; const self = this; let i = 0; let r; let shouldWriteMore = true + head[0] = 0x80 /* FIN */ | opcodes.TEXT /* opcode TEXT */ + head[1] = payloadLength | 0x80 /* MASK */ + head[offset - 4] = maskKey[0] + head[offset - 3] = maskKey[1] + head[offset - 2] = maskKey[2] + head[offset - 1] = maskKey[3] - if (!this._part && this._justMatched && data) { - while (this._dashes < 2 && (start + i) < end) { - if (data[start + i] === DASH) { - ++i - ++this._dashes - } else { - if (this._dashes) { buf = B_ONEDASH } - this._dashes = 0 - break - } - } - if (this._dashes === 2) { - if ((start + i) < end && this.listenerCount('trailer') !== 0) { this.emit('trailer', data.slice(start + i, end)) } - this.reset() - this._finished = true - // no more parts will be added - if (self._parts === 0) { - self._realFinish = true - self.emit('finish') - self._realFinish = false - } - } - if (this._dashes) { return } - } - if (this._justMatched) { this._justMatched = false } - if (!this._part) { - this._part = new PartStream(this._partOpts) - this._part._read = function (n) { - self._unpause() - } - if (this._isPreamble && this.listenerCount('preamble') !== 0) { - this.emit('preamble', this._part) - } else if (this._isPreamble !== true && this.listenerCount('part') !== 0) { - this.emit('part', this._part) - } else { - this._ignore() - } - if (!this._isPreamble) { this._inHeader = true } - } - if (data && start < end && !this._ignoreData) { - if (this._isPreamble || !this._inHeader) { - if (buf) { shouldWriteMore = this._part.push(buf) } - shouldWriteMore = this._part.push(data.slice(start, end)) - if (!shouldWriteMore) { this._pause = true } - } else if (!this._isPreamble && this._inHeader) { - if (buf) { this._hparser.push(buf) } - r = this._hparser.push(data.slice(start, end)) - if (!this._inHeader && r !== undefined && r < end) { this._oninfo(false, data, start + r, end) } - } - } - if (isMatch) { - this._hparser.reset() - if (this._isPreamble) { this._isPreamble = false } else { - if (start !== end) { - ++this._parts - this._part.on('end', function () { - if (--self._parts === 0) { - if (self._finished) { - self._realFinish = true - self.emit('finish') - self._realFinish = false - } else { - self._unpause() - } - } - }) - } + if (payloadLength === 126) { + head.writeUInt16BE(bodyLength, 2) + } else if (payloadLength === 127) { + head[2] = head[3] = 0 + head.writeUIntBE(bodyLength, 4, 6) } - this._part.push(null) - this._part = undefined - this._ignoreData = false - this._justMatched = true - this._dashes = 0 - } -} - -Dicer.prototype._unpause = function () { - if (!this._pause) { return } - this._pause = false - if (this._cb) { - const cb = this._cb - this._cb = undefined - cb() + return [head, buffer] } } -module.exports = Dicer +module.exports = { + WebsocketFrameSend, + generateMask // for benchmark +} /***/ }), -/***/ 7497: +/***/ 4395: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -const EventEmitter = (__nccwpck_require__(8474).EventEmitter) -const inherits = (__nccwpck_require__(7975).inherits) -const getLimit = __nccwpck_require__(375) +const { createInflateRaw, Z_DEFAULT_WINDOWBITS } = __nccwpck_require__(8522) +const { isValidClientWindowBits } = __nccwpck_require__(6667) -const StreamSearch = __nccwpck_require__(5202) +const tail = Buffer.from([0x00, 0x00, 0xff, 0xff]) +const kBuffer = Symbol('kBuffer') +const kLength = Symbol('kLength') -const B_DCRLF = Buffer.from('\r\n\r\n') -const RE_CRLF = /\r\n/g -const RE_HDR = /^([^:]+):[ \t]?([\x00-\xFF]+)?$/ // eslint-disable-line no-control-regex +class PerMessageDeflate { + /** @type {import('node:zlib').InflateRaw} */ + #inflate -function HeaderParser (cfg) { - EventEmitter.call(this) + #options = {} - cfg = cfg || {} - const self = this - this.nread = 0 - this.maxed = false - this.npairs = 0 - this.maxHeaderPairs = getLimit(cfg, 'maxHeaderPairs', 2000) - this.maxHeaderSize = getLimit(cfg, 'maxHeaderSize', 80 * 1024) - this.buffer = '' - this.header = {} - this.finished = false - this.ss = new StreamSearch(B_DCRLF) - this.ss.on('info', function (isMatch, data, start, end) { - if (data && !self.maxed) { - if (self.nread + end - start >= self.maxHeaderSize) { - end = self.maxHeaderSize - self.nread + start - self.nread = self.maxHeaderSize - self.maxed = true - } else { self.nread += (end - start) } + constructor (extensions) { + this.#options.serverNoContextTakeover = extensions.has('server_no_context_takeover') + this.#options.serverMaxWindowBits = extensions.get('server_max_window_bits') + } - self.buffer += data.toString('binary', start, end) - } - if (isMatch) { self._finish() } - }) -} -inherits(HeaderParser, EventEmitter) + decompress (chunk, fin, callback) { + // An endpoint uses the following algorithm to decompress a message. + // 1. Append 4 octets of 0x00 0x00 0xff 0xff to the tail end of the + // payload of the message. + // 2. Decompress the resulting data using DEFLATE. -HeaderParser.prototype.push = function (data) { - const r = this.ss.push(data) - if (this.finished) { return r } -} + if (!this.#inflate) { + let windowBits = Z_DEFAULT_WINDOWBITS -HeaderParser.prototype.reset = function () { - this.finished = false - this.buffer = '' - this.header = {} - this.ss.reset() -} + if (this.#options.serverMaxWindowBits) { // empty values default to Z_DEFAULT_WINDOWBITS + if (!isValidClientWindowBits(this.#options.serverMaxWindowBits)) { + callback(new Error('Invalid server_max_window_bits')) + return + } -HeaderParser.prototype._finish = function () { - if (this.buffer) { this._parseHeader() } - this.ss.matches = this.ss.maxMatches - const header = this.header - this.header = {} - this.buffer = '' - this.finished = true - this.nread = this.npairs = 0 - this.maxed = false - this.emit('header', header) -} + windowBits = Number.parseInt(this.#options.serverMaxWindowBits) + } -HeaderParser.prototype._parseHeader = function () { - if (this.npairs === this.maxHeaderPairs) { return } + this.#inflate = createInflateRaw({ windowBits }) + this.#inflate[kBuffer] = [] + this.#inflate[kLength] = 0 - const lines = this.buffer.split(RE_CRLF) - const len = lines.length - let m, h + this.#inflate.on('data', (data) => { + this.#inflate[kBuffer].push(data) + this.#inflate[kLength] += data.length + }) - for (var i = 0; i < len; ++i) { // eslint-disable-line no-var - if (lines[i].length === 0) { continue } - if (lines[i][0] === '\t' || lines[i][0] === ' ') { - // folded header content - // RFC2822 says to just remove the CRLF and not the whitespace following - // it, so we follow the RFC and include the leading whitespace ... - if (h) { - this.header[h][this.header[h].length - 1] += lines[i] - continue - } + this.#inflate.on('error', (err) => { + this.#inflate = null + callback(err) + }) } - const posColon = lines[i].indexOf(':') - if ( - posColon === -1 || - posColon === 0 - ) { - return + this.#inflate.write(chunk) + if (fin) { + this.#inflate.write(tail) } - m = RE_HDR.exec(lines[i]) - h = m[1].toLowerCase() - this.header[h] = this.header[h] || [] - this.header[h].push((m[2] || '')) - if (++this.npairs === this.maxHeaderPairs) { break } + + this.#inflate.flush(() => { + const full = Buffer.concat(this.#inflate[kBuffer], this.#inflate[kLength]) + + this.#inflate[kBuffer].length = 0 + this.#inflate[kLength] = 0 + + callback(null, full) + }) } } -module.exports = HeaderParser +module.exports = { PerMessageDeflate } /***/ }), -/***/ 6050: +/***/ 2094: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -const inherits = (__nccwpck_require__(7975).inherits) -const ReadableStream = (__nccwpck_require__(7075).Readable) - -function PartStream (opts) { - ReadableStream.call(this, opts) -} -inherits(PartStream, ReadableStream) +const { Writable } = __nccwpck_require__(7075) +const assert = __nccwpck_require__(4589) +const { parserStates, opcodes, states, emptyBuffer, sentCloseFrameState } = __nccwpck_require__(1078) +const { + isValidStatusCode, + isValidOpcode, + websocketMessageReceived, + utf8Decode, + isControlFrame, + isTextBinaryFrame, + isContinuationFrame +} = __nccwpck_require__(6667) +const { failWebsocketConnection } = __nccwpck_require__(7823) +const { WebsocketFrameSend } = __nccwpck_require__(2222) +const { PerMessageDeflate } = __nccwpck_require__(4395) -PartStream.prototype._read = function (n) {} +// This code was influenced by ws released under the MIT license. +// Copyright (c) 2011 Einar Otto Stangvik +// Copyright (c) 2013 Arnout Kazemier and contributors +// Copyright (c) 2016 Luigi Pinca and contributors -module.exports = PartStream +class ByteParser extends Writable { + #buffers = [] + #fragmentsBytes = 0 + #byteOffset = 0 + #loop = false + #state = parserStates.INFO -/***/ }), + #info = {} + #fragments = [] -/***/ 5202: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + /** @type {Map} */ + #extensions -"use strict"; + /** @type {import('./websocket').Handler} */ + #handler + constructor (handler, extensions) { + super() -/** - * Copyright Brian White. All rights reserved. - * - * @see https://github.com/mscdex/streamsearch - * - * 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. - * - * Based heavily on the Streaming Boyer-Moore-Horspool C++ implementation - * by Hongli Lai at: https://github.com/FooBarWidget/boyer-moore-horspool - */ -const EventEmitter = (__nccwpck_require__(8474).EventEmitter) -const inherits = (__nccwpck_require__(7975).inherits) + this.#handler = handler + this.#extensions = extensions == null ? new Map() : extensions -function SBMH (needle) { - if (typeof needle === 'string') { - needle = Buffer.from(needle) + if (this.#extensions.has('permessage-deflate')) { + this.#extensions.set('permessage-deflate', new PerMessageDeflate(extensions)) + } } - if (!Buffer.isBuffer(needle)) { - throw new TypeError('The needle has to be a String or a Buffer.') + /** + * @param {Buffer} chunk + * @param {() => void} callback + */ + _write (chunk, _, callback) { + this.#buffers.push(chunk) + this.#byteOffset += chunk.length + this.#loop = true + + this.run(callback) } - const needleLength = needle.length + /** + * Runs whenever a new chunk is received. + * Callback is called whenever there are no more chunks buffering, + * or not enough bytes are buffered to parse. + */ + run (callback) { + while (this.#loop) { + if (this.#state === parserStates.INFO) { + // If there aren't enough bytes to parse the payload length, etc. + if (this.#byteOffset < 2) { + return callback() + } - if (needleLength === 0) { - throw new Error('The needle cannot be an empty String/Buffer.') - } + const buffer = this.consume(2) + const fin = (buffer[0] & 0x80) !== 0 + const opcode = buffer[0] & 0x0F + const masked = (buffer[1] & 0x80) === 0x80 - if (needleLength > 256) { - throw new Error('The needle cannot have a length bigger than 256.') - } + const fragmented = !fin && opcode !== opcodes.CONTINUATION + const payloadLength = buffer[1] & 0x7F - this.maxMatches = Infinity - this.matches = 0 + const rsv1 = buffer[0] & 0x40 + const rsv2 = buffer[0] & 0x20 + const rsv3 = buffer[0] & 0x10 - this._occ = new Array(256) - .fill(needleLength) // Initialize occurrence table. - this._lookbehind_size = 0 - this._needle = needle - this._bufpos = 0 + if (!isValidOpcode(opcode)) { + failWebsocketConnection(this.#handler, 1002, 'Invalid opcode received') + return callback() + } - this._lookbehind = Buffer.alloc(needleLength) + if (masked) { + failWebsocketConnection(this.#handler, 1002, 'Frame cannot be masked') + return callback() + } - // Populate occurrence table with analysis of the needle, - // ignoring last letter. - for (var i = 0; i < needleLength - 1; ++i) { // eslint-disable-line no-var - this._occ[needle[i]] = needleLength - 1 - i - } -} -inherits(SBMH, EventEmitter) + // MUST be 0 unless an extension is negotiated that defines meanings + // for non-zero values. If a nonzero value is received and none of + // the negotiated extensions defines the meaning of such a nonzero + // value, the receiving endpoint MUST _Fail the WebSocket + // Connection_. + // This document allocates the RSV1 bit of the WebSocket header for + // PMCEs and calls the bit the "Per-Message Compressed" bit. On a + // WebSocket connection where a PMCE is in use, this bit indicates + // whether a message is compressed or not. + if (rsv1 !== 0 && !this.#extensions.has('permessage-deflate')) { + failWebsocketConnection(this.#handler, 1002, 'Expected RSV1 to be clear.') + return + } -SBMH.prototype.reset = function () { - this._lookbehind_size = 0 - this.matches = 0 - this._bufpos = 0 -} + if (rsv2 !== 0 || rsv3 !== 0) { + failWebsocketConnection(this.#handler, 1002, 'RSV1, RSV2, RSV3 must be clear') + return + } -SBMH.prototype.push = function (chunk, pos) { - if (!Buffer.isBuffer(chunk)) { - chunk = Buffer.from(chunk, 'binary') - } - const chlen = chunk.length - this._bufpos = pos || 0 - let r - while (r !== chlen && this.matches < this.maxMatches) { r = this._sbmh_feed(chunk) } - return r -} + if (fragmented && !isTextBinaryFrame(opcode)) { + // Only text and binary frames can be fragmented + failWebsocketConnection(this.#handler, 1002, 'Invalid frame type was fragmented.') + return + } -SBMH.prototype._sbmh_feed = function (data) { - const len = data.length - const needle = this._needle - const needleLength = needle.length - const lastNeedleChar = needle[needleLength - 1] + // If we are already parsing a text/binary frame and do not receive either + // a continuation frame or close frame, fail the connection. + if (isTextBinaryFrame(opcode) && this.#fragments.length > 0) { + failWebsocketConnection(this.#handler, 1002, 'Expected continuation frame') + return + } - // Positive: points to a position in `data` - // pos == 3 points to data[3] - // Negative: points to a position in the lookbehind buffer - // pos == -2 points to lookbehind[lookbehind_size - 2] - let pos = -this._lookbehind_size - let ch + if (this.#info.fragmented && fragmented) { + // A fragmented frame can't be fragmented itself + failWebsocketConnection(this.#handler, 1002, 'Fragmented frame exceeded 125 bytes.') + return + } - if (pos < 0) { - // Lookbehind buffer is not empty. Perform Boyer-Moore-Horspool - // search with character lookup code that considers both the - // lookbehind buffer and the current round's haystack data. - // - // Loop until - // there is a match. - // or until - // we've moved past the position that requires the - // lookbehind buffer. In this case we switch to the - // optimized loop. - // or until - // the character to look at lies outside the haystack. - while (pos < 0 && pos <= len - needleLength) { - ch = this._sbmh_lookup_char(data, pos + needleLength - 1) + // "All control frames MUST have a payload length of 125 bytes or less + // and MUST NOT be fragmented." + if ((payloadLength > 125 || fragmented) && isControlFrame(opcode)) { + failWebsocketConnection(this.#handler, 1002, 'Control frame either too large or fragmented') + return + } - if ( - ch === lastNeedleChar && - this._sbmh_memcmp(data, pos, needleLength - 1) - ) { - this._lookbehind_size = 0 - ++this.matches - this.emit('info', true) + if (isContinuationFrame(opcode) && this.#fragments.length === 0 && !this.#info.compressed) { + failWebsocketConnection(this.#handler, 1002, 'Unexpected continuation frame') + return + } - return (this._bufpos = pos + needleLength) - } - pos += this._occ[ch] - } + if (payloadLength <= 125) { + this.#info.payloadLength = payloadLength + this.#state = parserStates.READ_DATA + } else if (payloadLength === 126) { + this.#state = parserStates.PAYLOADLENGTH_16 + } else if (payloadLength === 127) { + this.#state = parserStates.PAYLOADLENGTH_64 + } - // No match. + if (isTextBinaryFrame(opcode)) { + this.#info.binaryType = opcode + this.#info.compressed = rsv1 !== 0 + } - if (pos < 0) { - // There's too few data for Boyer-Moore-Horspool to run, - // so let's use a different algorithm to skip as much as - // we can. - // Forward pos until - // the trailing part of lookbehind + data - // looks like the beginning of the needle - // or until - // pos == 0 - while (pos < 0 && !this._sbmh_memcmp(data, pos, len - pos)) { ++pos } - } + this.#info.opcode = opcode + this.#info.masked = masked + this.#info.fin = fin + this.#info.fragmented = fragmented + } else if (this.#state === parserStates.PAYLOADLENGTH_16) { + if (this.#byteOffset < 2) { + return callback() + } - if (pos >= 0) { - // Discard lookbehind buffer. - this.emit('info', false, this._lookbehind, 0, this._lookbehind_size) - this._lookbehind_size = 0 - } else { - // Cut off part of the lookbehind buffer that has - // been processed and append the entire haystack - // into it. - const bytesToCutOff = this._lookbehind_size + pos - if (bytesToCutOff > 0) { - // The cut off data is guaranteed not to contain the needle. - this.emit('info', false, this._lookbehind, 0, bytesToCutOff) - } + const buffer = this.consume(2) - this._lookbehind.copy(this._lookbehind, 0, bytesToCutOff, - this._lookbehind_size - bytesToCutOff) - this._lookbehind_size -= bytesToCutOff + this.#info.payloadLength = buffer.readUInt16BE(0) + this.#state = parserStates.READ_DATA + } else if (this.#state === parserStates.PAYLOADLENGTH_64) { + if (this.#byteOffset < 8) { + return callback() + } - data.copy(this._lookbehind, this._lookbehind_size) - this._lookbehind_size += len + const buffer = this.consume(8) + const upper = buffer.readUInt32BE(0) - this._bufpos = len - return len - } - } + // 2^31 is the maximum bytes an arraybuffer can contain + // on 32-bit systems. Although, on 64-bit systems, this is + // 2^53-1 bytes. + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Invalid_array_length + // https://source.chromium.org/chromium/chromium/src/+/main:v8/src/common/globals.h;drc=1946212ac0100668f14eb9e2843bdd846e510a1e;bpv=1;bpt=1;l=1275 + // https://source.chromium.org/chromium/chromium/src/+/main:v8/src/objects/js-array-buffer.h;l=34;drc=1946212ac0100668f14eb9e2843bdd846e510a1e + if (upper > 2 ** 31 - 1) { + failWebsocketConnection(this.#handler, 1009, 'Received payload length > 2^31 bytes.') + return + } - pos += (pos >= 0) * this._bufpos + const lower = buffer.readUInt32BE(4) - // Lookbehind buffer is now empty. We only need to check if the - // needle is in the haystack. - if (data.indexOf(needle, pos) !== -1) { - pos = data.indexOf(needle, pos) - ++this.matches - if (pos > 0) { this.emit('info', true, data, this._bufpos, pos) } else { this.emit('info', true) } + this.#info.payloadLength = (upper << 8) + lower + this.#state = parserStates.READ_DATA + } else if (this.#state === parserStates.READ_DATA) { + if (this.#byteOffset < this.#info.payloadLength) { + return callback() + } - return (this._bufpos = pos + needleLength) - } else { - pos = len - needleLength - } + const body = this.consume(this.#info.payloadLength) - // There was no match. If there's trailing haystack data that we cannot - // match yet using the Boyer-Moore-Horspool algorithm (because the trailing - // data is less than the needle size) then match using a modified - // algorithm that starts matching from the beginning instead of the end. - // Whatever trailing data is left after running this algorithm is added to - // the lookbehind buffer. - while ( - pos < len && - ( - data[pos] !== needle[0] || - ( - (Buffer.compare( - data.subarray(pos, pos + len - pos), - needle.subarray(0, len - pos) - ) !== 0) - ) - ) - ) { - ++pos - } - if (pos < len) { - data.copy(this._lookbehind, 0, pos, pos + (len - pos)) - this._lookbehind_size = len - pos - } - - // Everything until pos is guaranteed not to contain needle data. - if (pos > 0) { this.emit('info', false, data, this._bufpos, pos < len ? pos : len) } - - this._bufpos = len - return len -} - -SBMH.prototype._sbmh_lookup_char = function (data, pos) { - return (pos < 0) - ? this._lookbehind[this._lookbehind_size + pos] - : data[pos] -} - -SBMH.prototype._sbmh_memcmp = function (data, pos, len) { - for (var i = 0; i < len; ++i) { // eslint-disable-line no-var - if (this._sbmh_lookup_char(data, pos + i) !== this._needle[i]) { return false } - } - return true -} - -module.exports = SBMH - - -/***/ }), + if (isControlFrame(this.#info.opcode)) { + this.#loop = this.parseControlFrame(body) + this.#state = parserStates.INFO + } else { + if (!this.#info.compressed) { + this.writeFragments(body) -/***/ 7483: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + // If the frame is not fragmented, a message has been received. + // If the frame is fragmented, it will terminate with a fin bit set + // and an opcode of 0 (continuation), therefore we handle that when + // parsing continuation frames, not here. + if (!this.#info.fragmented && this.#info.fin) { + websocketMessageReceived(this.#handler, this.#info.binaryType, this.consumeFragments()) + } -"use strict"; + this.#state = parserStates.INFO + } else { + this.#extensions.get('permessage-deflate').decompress(body, this.#info.fin, (error, data) => { + if (error) { + failWebsocketConnection(this.#handler, 1007, error.message) + return + } + this.writeFragments(data) -const WritableStream = (__nccwpck_require__(7075).Writable) -const { inherits } = __nccwpck_require__(7975) -const Dicer = __nccwpck_require__(7988) + if (!this.#info.fin) { + this.#state = parserStates.INFO + this.#loop = true + this.run(callback) + return + } -const MultipartParser = __nccwpck_require__(114) -const UrlencodedParser = __nccwpck_require__(5929) -const parseParams = __nccwpck_require__(1831) + websocketMessageReceived(this.#handler, this.#info.binaryType, this.consumeFragments()) -function Busboy (opts) { - if (!(this instanceof Busboy)) { return new Busboy(opts) } + this.#loop = true + this.#state = parserStates.INFO + this.run(callback) + }) - if (typeof opts !== 'object') { - throw new TypeError('Busboy expected an options-Object.') - } - if (typeof opts.headers !== 'object') { - throw new TypeError('Busboy expected an options-Object with headers-attribute.') - } - if (typeof opts.headers['content-type'] !== 'string') { - throw new TypeError('Missing Content-Type-header.') + this.#loop = false + break + } + } + } + } } - const { - headers, - ...streamOptions - } = opts + /** + * Take n bytes from the buffered Buffers + * @param {number} n + * @returns {Buffer} + */ + consume (n) { + if (n > this.#byteOffset) { + throw new Error('Called consume() before buffers satiated.') + } else if (n === 0) { + return emptyBuffer + } - this.opts = { - autoDestroy: false, - ...streamOptions - } - WritableStream.call(this, this.opts) + this.#byteOffset -= n - this._done = false - this._parser = this.getParserByHeaders(headers) - this._finished = false -} -inherits(Busboy, WritableStream) + const first = this.#buffers[0] -Busboy.prototype.emit = function (ev) { - if (ev === 'finish') { - if (!this._done) { - this._parser?.end() - return - } else if (this._finished) { - return - } - this._finished = true - } - WritableStream.prototype.emit.apply(this, arguments) -} + if (first.length > n) { + // replace with remaining buffer + this.#buffers[0] = first.subarray(n, first.length) + return first.subarray(0, n) + } else if (first.length === n) { + // prefect match + return this.#buffers.shift() + } else { + let offset = 0 + // If Buffer.allocUnsafe is used, extra copies will be made because the offset is non-zero. + const buffer = Buffer.allocUnsafeSlow(n) + while (offset !== n) { + const next = this.#buffers[0] + const length = next.length -Busboy.prototype.getParserByHeaders = function (headers) { - const parsed = parseParams(headers['content-type']) + if (length + offset === n) { + buffer.set(this.#buffers.shift(), offset) + break + } else if (length + offset > n) { + buffer.set(next.subarray(0, n - offset), offset) + this.#buffers[0] = next.subarray(n - offset) + break + } else { + buffer.set(this.#buffers.shift(), offset) + offset += length + } + } - const cfg = { - defCharset: this.opts.defCharset, - fileHwm: this.opts.fileHwm, - headers, - highWaterMark: this.opts.highWaterMark, - isPartAFile: this.opts.isPartAFile, - limits: this.opts.limits, - parsedConType: parsed, - preservePath: this.opts.preservePath + return buffer + } } - if (MultipartParser.detect.test(parsed[0])) { - return new MultipartParser(this, cfg) - } - if (UrlencodedParser.detect.test(parsed[0])) { - return new UrlencodedParser(this, cfg) + writeFragments (fragment) { + this.#fragmentsBytes += fragment.length + this.#fragments.push(fragment) } - throw new Error('Unsupported Content-Type.') -} -Busboy.prototype._write = function (chunk, encoding, cb) { - this._parser.write(chunk, cb) -} - -module.exports = Busboy -module.exports["default"] = Busboy -module.exports.Busboy = Busboy + consumeFragments () { + const fragments = this.#fragments -module.exports.Dicer = Dicer + if (fragments.length === 1) { + // single fragment + this.#fragmentsBytes = 0 + return fragments.shift() + } + let offset = 0 + // If Buffer.allocUnsafe is used, extra copies will be made because the offset is non-zero. + const output = Buffer.allocUnsafeSlow(this.#fragmentsBytes) -/***/ }), + for (let i = 0; i < fragments.length; ++i) { + const buffer = fragments[i] + output.set(buffer, offset) + offset += buffer.length + } -/***/ 114: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + this.#fragments = [] + this.#fragmentsBytes = 0 -"use strict"; + return output + } + parseCloseBody (data) { + assert(data.length !== 1) -// TODO: -// * support 1 nested multipart level -// (see second multipart example here: -// http://www.w3.org/TR/html401/interact/forms.html#didx-multipartform-data) -// * support limits.fieldNameSize -// -- this will require modifications to utils.parseParams + // https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.5 + /** @type {number|undefined} */ + let code -const { Readable } = __nccwpck_require__(7075) -const { inherits } = __nccwpck_require__(7975) - -const Dicer = __nccwpck_require__(7988) - -const parseParams = __nccwpck_require__(1831) -const decodeText = __nccwpck_require__(4845) -const basename = __nccwpck_require__(8498) -const getLimit = __nccwpck_require__(375) - -const RE_BOUNDARY = /^boundary$/i -const RE_FIELD = /^form-data$/i -const RE_CHARSET = /^charset$/i -const RE_FILENAME = /^filename$/i -const RE_NAME = /^name$/i - -Multipart.detect = /^multipart\/form-data/i -function Multipart (boy, cfg) { - let i - let len - const self = this - let boundary - const limits = cfg.limits - const isPartAFile = cfg.isPartAFile || ((fieldName, contentType, fileName) => (contentType === 'application/octet-stream' || fileName !== undefined)) - const parsedConType = cfg.parsedConType || [] - const defCharset = cfg.defCharset || 'utf8' - const preservePath = cfg.preservePath - const fileOpts = { highWaterMark: cfg.fileHwm } - - for (i = 0, len = parsedConType.length; i < len; ++i) { - if (Array.isArray(parsedConType[i]) && - RE_BOUNDARY.test(parsedConType[i][0])) { - boundary = parsedConType[i][1] - break + if (data.length >= 2) { + // _The WebSocket Connection Close Code_ is + // defined as the status code (Section 7.4) contained in the first Close + // control frame received by the application + code = data.readUInt16BE(0) } - } - function checkFinished () { - if (nends === 0 && finished && !boy._done) { - finished = false - self.end() + if (code !== undefined && !isValidStatusCode(code)) { + return { code: 1002, reason: 'Invalid status code', error: true } } - } - - if (typeof boundary !== 'string') { throw new Error('Multipart: Boundary not found') } - const fieldSizeLimit = getLimit(limits, 'fieldSize', 1 * 1024 * 1024) - const fileSizeLimit = getLimit(limits, 'fileSize', Infinity) - const filesLimit = getLimit(limits, 'files', Infinity) - const fieldsLimit = getLimit(limits, 'fields', Infinity) - const partsLimit = getLimit(limits, 'parts', Infinity) - const headerPairsLimit = getLimit(limits, 'headerPairs', 2000) - const headerSizeLimit = getLimit(limits, 'headerSize', 80 * 1024) - - let nfiles = 0 - let nfields = 0 - let nends = 0 - let curFile - let curField - let finished = false + // https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.6 + /** @type {Buffer} */ + let reason = data.subarray(2) - this._needDrain = false - this._pause = false - this._cb = undefined - this._nparts = 0 - this._boy = boy - - const parserCfg = { - boundary, - maxHeaderPairs: headerPairsLimit, - maxHeaderSize: headerSizeLimit, - partHwm: fileOpts.highWaterMark, - highWaterMark: cfg.highWaterMark - } - - this.parser = new Dicer(parserCfg) - this.parser.on('drain', function () { - self._needDrain = false - if (self._cb && !self._pause) { - const cb = self._cb - self._cb = undefined - cb() + // Remove BOM + if (reason[0] === 0xEF && reason[1] === 0xBB && reason[2] === 0xBF) { + reason = reason.subarray(3) } - }).on('part', function onPart (part) { - if (++self._nparts > partsLimit) { - self.parser.removeListener('part', onPart) - self.parser.on('part', skipPart) - boy.hitPartsLimit = true - boy.emit('partsLimit') - return skipPart(part) - } - - // hack because streams2 _always_ doesn't emit 'end' until nextTick, so let - // us emit 'end' early since we know the part has ended if we are already - // seeing the next part - if (curField) { - const field = curField - field.emit('end') - field.removeAllListeners('end') - } - - part.on('header', function (header) { - let contype - let fieldname - let parsed - let charset - let encoding - let filename - let nsize = 0 - - if (header['content-type']) { - parsed = parseParams(header['content-type'][0]) - if (parsed[0]) { - contype = parsed[0].toLowerCase() - for (i = 0, len = parsed.length; i < len; ++i) { - if (RE_CHARSET.test(parsed[i][0])) { - charset = parsed[i][1].toLowerCase() - break - } - } - } - } - if (contype === undefined) { contype = 'text/plain' } - if (charset === undefined) { charset = defCharset } + try { + reason = utf8Decode(reason) + } catch { + return { code: 1007, reason: 'Invalid UTF-8', error: true } + } - if (header['content-disposition']) { - parsed = parseParams(header['content-disposition'][0]) - if (!RE_FIELD.test(parsed[0])) { return skipPart(part) } - for (i = 0, len = parsed.length; i < len; ++i) { - if (RE_NAME.test(parsed[i][0])) { - fieldname = parsed[i][1] - } else if (RE_FILENAME.test(parsed[i][0])) { - filename = parsed[i][1] - if (!preservePath) { filename = basename(filename) } - } - } - } else { return skipPart(part) } + return { code, reason, error: false } + } - if (header['content-transfer-encoding']) { encoding = header['content-transfer-encoding'][0].toLowerCase() } else { encoding = '7bit' } + /** + * Parses control frames. + * @param {Buffer} body + */ + parseControlFrame (body) { + const { opcode, payloadLength } = this.#info - let onData, - onEnd + if (opcode === opcodes.CLOSE) { + if (payloadLength === 1) { + failWebsocketConnection(this.#handler, 1002, 'Received close frame with a 1-byte body.') + return false + } - if (isPartAFile(fieldname, contype, filename)) { - // file/binary field - if (nfiles === filesLimit) { - if (!boy.hitFilesLimit) { - boy.hitFilesLimit = true - boy.emit('filesLimit') - } - return skipPart(part) - } + this.#info.closeInfo = this.parseCloseBody(body) - ++nfiles + if (this.#info.closeInfo.error) { + const { code, reason } = this.#info.closeInfo - if (boy.listenerCount('file') === 0) { - self.parser._ignore() - return - } + failWebsocketConnection(this.#handler, code, reason) + return false + } - ++nends - const file = new FileStream(fileOpts) - curFile = file - file.on('end', function () { - --nends - self._pause = false - checkFinished() - if (self._cb && !self._needDrain) { - const cb = self._cb - self._cb = undefined - cb() - } - }) - file._read = function (n) { - if (!self._pause) { return } - self._pause = false - if (self._cb && !self._needDrain) { - const cb = self._cb - self._cb = undefined - cb() - } + // Upon receiving such a frame, the other peer sends a + // Close frame in response, if it hasn't already sent one. + if (!this.#handler.closeState.has(sentCloseFrameState.SENT) && !this.#handler.closeState.has(sentCloseFrameState.RECEIVED)) { + // If an endpoint receives a Close frame and did not previously send a + // Close frame, the endpoint MUST send a Close frame in response. (When + // sending a Close frame in response, the endpoint typically echos the + // status code it received.) + let body = emptyBuffer + if (this.#info.closeInfo.code) { + body = Buffer.allocUnsafe(2) + body.writeUInt16BE(this.#info.closeInfo.code, 0) } - boy.emit('file', fieldname, file, filename, encoding, contype) + const closeFrame = new WebsocketFrameSend(body) - onData = function (data) { - if ((nsize += data.length) > fileSizeLimit) { - const extralen = fileSizeLimit - nsize + data.length - if (extralen > 0) { file.push(data.slice(0, extralen)) } - file.truncated = true - file.bytesRead = fileSizeLimit - part.removeAllListeners('data') - file.emit('limit') - return - } else if (!file.push(data)) { self._pause = true } + this.#handler.socket.write(closeFrame.createFrame(opcodes.CLOSE)) + this.#handler.closeState.add(sentCloseFrameState.SENT) + } - file.bytesRead = nsize - } + // Upon either sending or receiving a Close control frame, it is said + // that _The WebSocket Closing Handshake is Started_ and that the + // WebSocket connection is in the CLOSING state. + this.#handler.readyState = states.CLOSING + this.#handler.closeState.add(sentCloseFrameState.RECEIVED) - onEnd = function () { - curFile = undefined - file.push(null) - } - } else { - // non-file field - if (nfields === fieldsLimit) { - if (!boy.hitFieldsLimit) { - boy.hitFieldsLimit = true - boy.emit('fieldsLimit') - } - return skipPart(part) - } + return false + } else if (opcode === opcodes.PING) { + // Upon receipt of a Ping frame, an endpoint MUST send a Pong frame in + // response, unless it already received a Close frame. + // A Pong frame sent in response to a Ping frame must have identical + // "Application data" - ++nfields - ++nends - let buffer = '' - let truncated = false - curField = part + if (!this.#handler.closeState.has(sentCloseFrameState.RECEIVED)) { + const frame = new WebsocketFrameSend(body) - onData = function (data) { - if ((nsize += data.length) > fieldSizeLimit) { - const extralen = (fieldSizeLimit - (nsize - data.length)) - buffer += data.toString('binary', 0, extralen) - truncated = true - part.removeAllListeners('data') - } else { buffer += data.toString('binary') } - } + this.#handler.socket.write(frame.createFrame(opcodes.PONG)) - onEnd = function () { - curField = undefined - if (buffer.length) { buffer = decodeText(buffer, 'binary', charset) } - boy.emit('field', fieldname, buffer, false, truncated, encoding, contype) - --nends - checkFinished() - } + this.#handler.onPing(body) } + } else if (opcode === opcodes.PONG) { + // A Pong frame MAY be sent unsolicited. This serves as a + // unidirectional heartbeat. A response to an unsolicited Pong frame is + // not expected. + this.#handler.onPong(body) + } - /* As of node@2efe4ab761666 (v0.10.29+/v0.11.14+), busboy had become - broken. Streams2/streams3 is a huge black box of confusion, but - somehow overriding the sync state seems to fix things again (and still - seems to work for previous node versions). - */ - part._readableState.sync = false - - part.on('data', onData) - part.on('end', onEnd) - }).on('error', function (err) { - if (curFile) { curFile.emit('error', err) } - }) - }).on('error', function (err) { - boy.emit('error', err) - }).on('finish', function () { - finished = true - checkFinished() - }) -} - -Multipart.prototype.write = function (chunk, cb) { - const r = this.parser.write(chunk) - if (r && !this._pause) { - cb() - } else { - this._needDrain = !r - this._cb = cb + return true } -} - -Multipart.prototype.end = function () { - const self = this - if (self.parser.writable) { - self.parser.end() - } else if (!self._boy._done) { - process.nextTick(function () { - self._boy._done = true - self._boy.emit('finish') - }) + get closingInfo () { + return this.#info.closeInfo } } -function skipPart (part) { - part.resume() -} - -function FileStream (opts) { - Readable.call(this, opts) - - this.bytesRead = 0 - - this.truncated = false +module.exports = { + ByteParser } -inherits(FileStream, Readable) - -FileStream.prototype._read = function (n) {} - -module.exports = Multipart - /***/ }), -/***/ 5929: +/***/ 4738: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -"use strict"; -const Decoder = __nccwpck_require__(9162) -const decodeText = __nccwpck_require__(4845) -const getLimit = __nccwpck_require__(375) +const { WebsocketFrameSend } = __nccwpck_require__(2222) +const { opcodes, sendHints } = __nccwpck_require__(1078) +const FixedQueue = __nccwpck_require__(1506) -const RE_CHARSET = /^charset$/i +/** + * @typedef {object} SendQueueNode + * @property {Promise | null} promise + * @property {((...args: any[]) => any)} callback + * @property {Buffer | null} frame + */ -UrlEncoded.detect = /^application\/x-www-form-urlencoded/i -function UrlEncoded (boy, cfg) { - const limits = cfg.limits - const parsedConType = cfg.parsedConType - this.boy = boy +class SendQueue { + /** + * @type {FixedQueue} + */ + #queue = new FixedQueue() - this.fieldSizeLimit = getLimit(limits, 'fieldSize', 1 * 1024 * 1024) - this.fieldNameSizeLimit = getLimit(limits, 'fieldNameSize', 100) - this.fieldsLimit = getLimit(limits, 'fields', Infinity) + /** + * @type {boolean} + */ + #running = false - let charset - for (var i = 0, len = parsedConType.length; i < len; ++i) { // eslint-disable-line no-var - if (Array.isArray(parsedConType[i]) && - RE_CHARSET.test(parsedConType[i][0])) { - charset = parsedConType[i][1].toLowerCase() - break - } + /** @type {import('node:net').Socket} */ + #socket + + constructor (socket) { + this.#socket = socket } - if (charset === undefined) { charset = cfg.defCharset || 'utf8' } + add (item, cb, hint) { + if (hint !== sendHints.blob) { + if (!this.#running) { + // TODO(@tsctx): support fast-path for string on running + if (hint === sendHints.text) { + // special fast-path for string + const { 0: head, 1: body } = WebsocketFrameSend.createFastTextFrame(item) + this.#socket.cork() + this.#socket.write(head) + this.#socket.write(body, cb) + this.#socket.uncork() + } else { + // direct writing + this.#socket.write(createFrame(item, hint), cb) + } + } else { + /** @type {SendQueueNode} */ + const node = { + promise: null, + callback: cb, + frame: createFrame(item, hint) + } + this.#queue.push(node) + } + return + } - this.decoder = new Decoder() - this.charset = charset - this._fields = 0 - this._state = 'key' - this._checkingBytes = true - this._bytesKey = 0 - this._bytesVal = 0 - this._key = '' - this._val = '' - this._keyTrunc = false - this._valTrunc = false - this._hitLimit = false -} + /** @type {SendQueueNode} */ + const node = { + promise: item.arrayBuffer().then((ab) => { + node.promise = null + node.frame = createFrame(ab, hint) + }), + callback: cb, + frame: null + } -UrlEncoded.prototype.write = function (data, cb) { - if (this._fields === this.fieldsLimit) { - if (!this.boy.hitFieldsLimit) { - this.boy.hitFieldsLimit = true - this.boy.emit('fieldsLimit') + this.#queue.push(node) + + if (!this.#running) { + this.#run() } - return cb() } - let idxeq; let idxamp; let i; let p = 0; const len = data.length - - while (p < len) { - if (this._state === 'key') { - idxeq = idxamp = undefined - for (i = p; i < len; ++i) { - if (!this._checkingBytes) { ++p } - if (data[i] === 0x3D/* = */) { - idxeq = i - break - } else if (data[i] === 0x26/* & */) { - idxamp = i - break - } - if (this._checkingBytes && this._bytesKey === this.fieldNameSizeLimit) { - this._hitLimit = true - break - } else if (this._checkingBytes) { ++this._bytesKey } - } - - if (idxeq !== undefined) { - // key with assignment - if (idxeq > p) { this._key += this.decoder.write(data.toString('binary', p, idxeq)) } - this._state = 'val' - - this._hitLimit = false - this._checkingBytes = true - this._val = '' - this._bytesVal = 0 - this._valTrunc = false - this.decoder.reset() - - p = idxeq + 1 - } else if (idxamp !== undefined) { - // key with no assignment - ++this._fields - let key; const keyTrunc = this._keyTrunc - if (idxamp > p) { key = (this._key += this.decoder.write(data.toString('binary', p, idxamp))) } else { key = this._key } - - this._hitLimit = false - this._checkingBytes = true - this._key = '' - this._bytesKey = 0 - this._keyTrunc = false - this.decoder.reset() - - if (key.length) { - this.boy.emit('field', decodeText(key, 'binary', this.charset), - '', - keyTrunc, - false) - } - - p = idxamp + 1 - if (this._fields === this.fieldsLimit) { return cb() } - } else if (this._hitLimit) { - // we may not have hit the actual limit if there are encoded bytes... - if (i > p) { this._key += this.decoder.write(data.toString('binary', p, i)) } - p = i - if ((this._bytesKey = this._key.length) === this.fieldNameSizeLimit) { - // yep, we actually did hit the limit - this._checkingBytes = false - this._keyTrunc = true - } - } else { - if (p < len) { this._key += this.decoder.write(data.toString('binary', p)) } - p = len - } - } else { - idxamp = undefined - for (i = p; i < len; ++i) { - if (!this._checkingBytes) { ++p } - if (data[i] === 0x26/* & */) { - idxamp = i - break - } - if (this._checkingBytes && this._bytesVal === this.fieldSizeLimit) { - this._hitLimit = true - break - } else if (this._checkingBytes) { ++this._bytesVal } - } - - if (idxamp !== undefined) { - ++this._fields - if (idxamp > p) { this._val += this.decoder.write(data.toString('binary', p, idxamp)) } - this.boy.emit('field', decodeText(this._key, 'binary', this.charset), - decodeText(this._val, 'binary', this.charset), - this._keyTrunc, - this._valTrunc) - this._state = 'key' - - this._hitLimit = false - this._checkingBytes = true - this._key = '' - this._bytesKey = 0 - this._keyTrunc = false - this.decoder.reset() - - p = idxamp + 1 - if (this._fields === this.fieldsLimit) { return cb() } - } else if (this._hitLimit) { - // we may not have hit the actual limit if there are encoded bytes... - if (i > p) { this._val += this.decoder.write(data.toString('binary', p, i)) } - p = i - if ((this._val === '' && this.fieldSizeLimit === 0) || - (this._bytesVal = this._val.length) === this.fieldSizeLimit) { - // yep, we actually did hit the limit - this._checkingBytes = false - this._valTrunc = true - } - } else { - if (p < len) { this._val += this.decoder.write(data.toString('binary', p)) } - p = len + async #run () { + this.#running = true + const queue = this.#queue + while (!queue.isEmpty()) { + const node = queue.shift() + // wait pending promise + if (node.promise !== null) { + await node.promise } + // write + this.#socket.write(node.frame, node.callback) + // cleanup + node.callback = node.frame = null } + this.#running = false } - cb() } -UrlEncoded.prototype.end = function () { - if (this.boy._done) { return } +function createFrame (data, hint) { + return new WebsocketFrameSend(toBuffer(data, hint)).createFrame(hint === sendHints.text ? opcodes.TEXT : opcodes.BINARY) +} - if (this._state === 'key' && this._key.length > 0) { - this.boy.emit('field', decodeText(this._key, 'binary', this.charset), - '', - this._keyTrunc, - false) - } else if (this._state === 'val') { - this.boy.emit('field', decodeText(this._key, 'binary', this.charset), - decodeText(this._val, 'binary', this.charset), - this._keyTrunc, - this._valTrunc) +function toBuffer (data, hint) { + switch (hint) { + case sendHints.text: + case sendHints.typedArray: + return new Uint8Array(data.buffer, data.byteOffset, data.byteLength) + case sendHints.arrayBuffer: + case sendHints.blob: + return new Uint8Array(data) } - this.boy._done = true - this.boy.emit('finish') } -module.exports = UrlEncoded +module.exports = { SendQueue } /***/ }), -/***/ 9162: -/***/ ((module) => { - -"use strict"; +/***/ 7145: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -const RE_PLUS = /\+/g -const HEX = [ - 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, - 0, 1, 1, 1, 1, 1, 1, 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, 1, 1, 1, 1, 1, 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 -] +const { webidl } = __nccwpck_require__(909) +const { validateCloseCodeAndReason } = __nccwpck_require__(6667) +const { kConstruct } = __nccwpck_require__(8261) +const { kEnumerableProperty } = __nccwpck_require__(2550) -function Decoder () { - this.buffer = undefined -} -Decoder.prototype.write = function (str) { - // Replace '+' with ' ' before decoding - str = str.replace(RE_PLUS, ' ') - let res = '' - let i = 0; let p = 0; const len = str.length - for (; i < len; ++i) { - if (this.buffer !== undefined) { - if (!HEX[str.charCodeAt(i)]) { - res += '%' + this.buffer - this.buffer = undefined - --i // retry character - } else { - this.buffer += str[i] - ++p - if (this.buffer.length === 2) { - res += String.fromCharCode(parseInt(this.buffer, 16)) - this.buffer = undefined - } - } - } else if (str[i] === '%') { - if (i > p) { - res += str.substring(p, i) - p = i - } - this.buffer = '' - ++p +function createInheritableDOMException () { + // https://github.com/nodejs/node/issues/59677 + class Test extends DOMException { + get reason () { + return '' } } - if (p < len && this.buffer === undefined) { res += str.substring(p) } - return res -} -Decoder.prototype.reset = function () { - this.buffer = undefined -} - -module.exports = Decoder - - -/***/ }), - -/***/ 8498: -/***/ ((module) => { - -"use strict"; + if (new Test().reason !== undefined) { + return DOMException + } -module.exports = function basename (path) { - if (typeof path !== 'string') { return '' } - for (var i = path.length - 1; i >= 0; --i) { // eslint-disable-line no-var - switch (path.charCodeAt(i)) { - case 0x2F: // '/' - case 0x5C: // '\' - path = path.slice(i + 1) - return (path === '..' || path === '.' ? '' : path) + return new Proxy(DOMException, { + construct (target, args, newTarget) { + const instance = Reflect.construct(target, args, target) + Object.setPrototypeOf(instance, newTarget.prototype) + return instance } - } - return (path === '..' || path === '.' ? '' : path) + }) } +class WebSocketError extends createInheritableDOMException() { + #closeCode + #reason -/***/ }), - -/***/ 4845: -/***/ (function(module) { + constructor (message = '', init = undefined) { + message = webidl.converters.DOMString(message, 'WebSocketError', 'message') -"use strict"; + // 1. Set this 's name to " WebSocketError ". + // 2. Set this 's message to message . + super(message, 'WebSocketError') + if (init === kConstruct) { + return + } else if (init !== null) { + init = webidl.converters.WebSocketCloseInfo(init) + } -// Node has always utf-8 -const utf8Decoder = new TextDecoder('utf-8') -const textDecoders = new Map([ - ['utf-8', utf8Decoder], - ['utf8', utf8Decoder] -]) + // 3. Let code be init [" closeCode "] if it exists , or null otherwise. + let code = init.closeCode ?? null -function getDecoder (charset) { - let lc - while (true) { - switch (charset) { - case 'utf-8': - case 'utf8': - return decoders.utf8 - case 'latin1': - case 'ascii': // TODO: Make these a separate, strict decoder? - case 'us-ascii': - case 'iso-8859-1': - case 'iso8859-1': - case 'iso88591': - case 'iso_8859-1': - case 'windows-1252': - case 'iso_8859-1:1987': - case 'cp1252': - case 'x-cp1252': - return decoders.latin1 - case 'utf16le': - case 'utf-16le': - case 'ucs2': - case 'ucs-2': - return decoders.utf16le - case 'base64': - return decoders.base64 - default: - if (lc === undefined) { - lc = true - charset = charset.toLowerCase() - continue - } - return decoders.other.bind(charset) - } - } -} + // 4. Let reason be init [" reason "] if it exists , or the empty string otherwise. + const reason = init.reason ?? '' -const decoders = { - utf8: (data, sourceEncoding) => { - if (data.length === 0) { - return '' - } - if (typeof data === 'string') { - data = Buffer.from(data, sourceEncoding) - } - return data.utf8Slice(0, data.length) - }, + // 5. Validate close code and reason with code and reason . + validateCloseCodeAndReason(code, reason) - latin1: (data, sourceEncoding) => { - if (data.length === 0) { - return '' - } - if (typeof data === 'string') { - return data + // 6. If reason is non-empty, but code is not set, then set code to 1000 ("Normal Closure"). + if (reason.length !== 0 && code === null) { + code = 1000 } - return data.latin1Slice(0, data.length) - }, - utf16le: (data, sourceEncoding) => { - if (data.length === 0) { - return '' - } - if (typeof data === 'string') { - data = Buffer.from(data, sourceEncoding) - } - return data.ucs2Slice(0, data.length) - }, + // 7. Set this 's closeCode to code . + this.#closeCode = code - base64: (data, sourceEncoding) => { - if (data.length === 0) { - return '' - } - if (typeof data === 'string') { - data = Buffer.from(data, sourceEncoding) - } - return data.base64Slice(0, data.length) - }, + // 8. Set this 's reason to reason . + this.#reason = reason + } - other: (data, sourceEncoding) => { - if (data.length === 0) { - return '' - } - if (typeof data === 'string') { - data = Buffer.from(data, sourceEncoding) - } + get closeCode () { + return this.#closeCode + } - if (textDecoders.has(this.toString())) { - try { - return textDecoders.get(this).decode(data) - } catch {} - } - return typeof data === 'string' - ? data - : data.toString() + get reason () { + return this.#reason } -} -function decodeText (text, sourceEncoding, destEncoding) { - if (text) { - return getDecoder(destEncoding)(text, sourceEncoding) + /** + * @param {string} message + * @param {number|null} code + * @param {string} reason + */ + static createUnvalidatedWebSocketError (message, code, reason) { + const error = new WebSocketError(message, kConstruct) + error.#closeCode = code + error.#reason = reason + return error } - return text } -module.exports = decodeText +const { createUnvalidatedWebSocketError } = WebSocketError +delete WebSocketError.createUnvalidatedWebSocketError +Object.defineProperties(WebSocketError.prototype, { + closeCode: kEnumerableProperty, + reason: kEnumerableProperty, + [Symbol.toStringTag]: { + value: 'WebSocketError', + writable: false, + enumerable: false, + configurable: true + } +}) -/***/ }), +webidl.is.WebSocketError = webidl.util.MakeTypeAssertion(WebSocketError) -/***/ 375: -/***/ ((module) => { +module.exports = { WebSocketError, createUnvalidatedWebSocketError } -"use strict"; +/***/ }), -module.exports = function getLimit (limits, name, defaultLimit) { - if ( - !limits || - limits[name] === undefined || - limits[name] === null - ) { return defaultLimit } +/***/ 6519: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - if ( - typeof limits[name] !== 'number' || - isNaN(limits[name]) - ) { throw new TypeError('Limit ' + name + ' is not a valid number') } - return limits[name] -} +const { createDeferredPromise } = __nccwpck_require__(3022) +const { environmentSettingsObject } = __nccwpck_require__(3106) +const { states, opcodes, sentCloseFrameState } = __nccwpck_require__(1078) +const { webidl } = __nccwpck_require__(909) +const { getURLRecord, isValidSubprotocol, isEstablished, utf8Decode } = __nccwpck_require__(6667) +const { establishWebSocketConnection, failWebsocketConnection, closeWebSocketConnection } = __nccwpck_require__(7823) +const { channels } = __nccwpck_require__(2248) +const { WebsocketFrameSend } = __nccwpck_require__(2222) +const { ByteParser } = __nccwpck_require__(2094) +const { WebSocketError, createUnvalidatedWebSocketError } = __nccwpck_require__(7145) +const { kEnumerableProperty } = __nccwpck_require__(2550) +const { utf8DecodeBytes } = __nccwpck_require__(6546) -/***/ }), +let emittedExperimentalWarning = false -/***/ 1831: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +class WebSocketStream { + // Each WebSocketStream object has an associated url , which is a URL record . + /** @type {URL} */ + #url -"use strict"; -/* eslint-disable object-property-newline */ - - -const decodeText = __nccwpck_require__(4845) - -const RE_ENCODED = /%[a-fA-F0-9][a-fA-F0-9]/g - -const EncodedLookup = { - '%00': '\x00', '%01': '\x01', '%02': '\x02', '%03': '\x03', '%04': '\x04', - '%05': '\x05', '%06': '\x06', '%07': '\x07', '%08': '\x08', '%09': '\x09', - '%0a': '\x0a', '%0A': '\x0a', '%0b': '\x0b', '%0B': '\x0b', '%0c': '\x0c', - '%0C': '\x0c', '%0d': '\x0d', '%0D': '\x0d', '%0e': '\x0e', '%0E': '\x0e', - '%0f': '\x0f', '%0F': '\x0f', '%10': '\x10', '%11': '\x11', '%12': '\x12', - '%13': '\x13', '%14': '\x14', '%15': '\x15', '%16': '\x16', '%17': '\x17', - '%18': '\x18', '%19': '\x19', '%1a': '\x1a', '%1A': '\x1a', '%1b': '\x1b', - '%1B': '\x1b', '%1c': '\x1c', '%1C': '\x1c', '%1d': '\x1d', '%1D': '\x1d', - '%1e': '\x1e', '%1E': '\x1e', '%1f': '\x1f', '%1F': '\x1f', '%20': '\x20', - '%21': '\x21', '%22': '\x22', '%23': '\x23', '%24': '\x24', '%25': '\x25', - '%26': '\x26', '%27': '\x27', '%28': '\x28', '%29': '\x29', '%2a': '\x2a', - '%2A': '\x2a', '%2b': '\x2b', '%2B': '\x2b', '%2c': '\x2c', '%2C': '\x2c', - '%2d': '\x2d', '%2D': '\x2d', '%2e': '\x2e', '%2E': '\x2e', '%2f': '\x2f', - '%2F': '\x2f', '%30': '\x30', '%31': '\x31', '%32': '\x32', '%33': '\x33', - '%34': '\x34', '%35': '\x35', '%36': '\x36', '%37': '\x37', '%38': '\x38', - '%39': '\x39', '%3a': '\x3a', '%3A': '\x3a', '%3b': '\x3b', '%3B': '\x3b', - '%3c': '\x3c', '%3C': '\x3c', '%3d': '\x3d', '%3D': '\x3d', '%3e': '\x3e', - '%3E': '\x3e', '%3f': '\x3f', '%3F': '\x3f', '%40': '\x40', '%41': '\x41', - '%42': '\x42', '%43': '\x43', '%44': '\x44', '%45': '\x45', '%46': '\x46', - '%47': '\x47', '%48': '\x48', '%49': '\x49', '%4a': '\x4a', '%4A': '\x4a', - '%4b': '\x4b', '%4B': '\x4b', '%4c': '\x4c', '%4C': '\x4c', '%4d': '\x4d', - '%4D': '\x4d', '%4e': '\x4e', '%4E': '\x4e', '%4f': '\x4f', '%4F': '\x4f', - '%50': '\x50', '%51': '\x51', '%52': '\x52', '%53': '\x53', '%54': '\x54', - '%55': '\x55', '%56': '\x56', '%57': '\x57', '%58': '\x58', '%59': '\x59', - '%5a': '\x5a', '%5A': '\x5a', '%5b': '\x5b', '%5B': '\x5b', '%5c': '\x5c', - '%5C': '\x5c', '%5d': '\x5d', '%5D': '\x5d', '%5e': '\x5e', '%5E': '\x5e', - '%5f': '\x5f', '%5F': '\x5f', '%60': '\x60', '%61': '\x61', '%62': '\x62', - '%63': '\x63', '%64': '\x64', '%65': '\x65', '%66': '\x66', '%67': '\x67', - '%68': '\x68', '%69': '\x69', '%6a': '\x6a', '%6A': '\x6a', '%6b': '\x6b', - '%6B': '\x6b', '%6c': '\x6c', '%6C': '\x6c', '%6d': '\x6d', '%6D': '\x6d', - '%6e': '\x6e', '%6E': '\x6e', '%6f': '\x6f', '%6F': '\x6f', '%70': '\x70', - '%71': '\x71', '%72': '\x72', '%73': '\x73', '%74': '\x74', '%75': '\x75', - '%76': '\x76', '%77': '\x77', '%78': '\x78', '%79': '\x79', '%7a': '\x7a', - '%7A': '\x7a', '%7b': '\x7b', '%7B': '\x7b', '%7c': '\x7c', '%7C': '\x7c', - '%7d': '\x7d', '%7D': '\x7d', '%7e': '\x7e', '%7E': '\x7e', '%7f': '\x7f', - '%7F': '\x7f', '%80': '\x80', '%81': '\x81', '%82': '\x82', '%83': '\x83', - '%84': '\x84', '%85': '\x85', '%86': '\x86', '%87': '\x87', '%88': '\x88', - '%89': '\x89', '%8a': '\x8a', '%8A': '\x8a', '%8b': '\x8b', '%8B': '\x8b', - '%8c': '\x8c', '%8C': '\x8c', '%8d': '\x8d', '%8D': '\x8d', '%8e': '\x8e', - '%8E': '\x8e', '%8f': '\x8f', '%8F': '\x8f', '%90': '\x90', '%91': '\x91', - '%92': '\x92', '%93': '\x93', '%94': '\x94', '%95': '\x95', '%96': '\x96', - '%97': '\x97', '%98': '\x98', '%99': '\x99', '%9a': '\x9a', '%9A': '\x9a', - '%9b': '\x9b', '%9B': '\x9b', '%9c': '\x9c', '%9C': '\x9c', '%9d': '\x9d', - '%9D': '\x9d', '%9e': '\x9e', '%9E': '\x9e', '%9f': '\x9f', '%9F': '\x9f', - '%a0': '\xa0', '%A0': '\xa0', '%a1': '\xa1', '%A1': '\xa1', '%a2': '\xa2', - '%A2': '\xa2', '%a3': '\xa3', '%A3': '\xa3', '%a4': '\xa4', '%A4': '\xa4', - '%a5': '\xa5', '%A5': '\xa5', '%a6': '\xa6', '%A6': '\xa6', '%a7': '\xa7', - '%A7': '\xa7', '%a8': '\xa8', '%A8': '\xa8', '%a9': '\xa9', '%A9': '\xa9', - '%aa': '\xaa', '%Aa': '\xaa', '%aA': '\xaa', '%AA': '\xaa', '%ab': '\xab', - '%Ab': '\xab', '%aB': '\xab', '%AB': '\xab', '%ac': '\xac', '%Ac': '\xac', - '%aC': '\xac', '%AC': '\xac', '%ad': '\xad', '%Ad': '\xad', '%aD': '\xad', - '%AD': '\xad', '%ae': '\xae', '%Ae': '\xae', '%aE': '\xae', '%AE': '\xae', - '%af': '\xaf', '%Af': '\xaf', '%aF': '\xaf', '%AF': '\xaf', '%b0': '\xb0', - '%B0': '\xb0', '%b1': '\xb1', '%B1': '\xb1', '%b2': '\xb2', '%B2': '\xb2', - '%b3': '\xb3', '%B3': '\xb3', '%b4': '\xb4', '%B4': '\xb4', '%b5': '\xb5', - '%B5': '\xb5', '%b6': '\xb6', '%B6': '\xb6', '%b7': '\xb7', '%B7': '\xb7', - '%b8': '\xb8', '%B8': '\xb8', '%b9': '\xb9', '%B9': '\xb9', '%ba': '\xba', - '%Ba': '\xba', '%bA': '\xba', '%BA': '\xba', '%bb': '\xbb', '%Bb': '\xbb', - '%bB': '\xbb', '%BB': '\xbb', '%bc': '\xbc', '%Bc': '\xbc', '%bC': '\xbc', - '%BC': '\xbc', '%bd': '\xbd', '%Bd': '\xbd', '%bD': '\xbd', '%BD': '\xbd', - '%be': '\xbe', '%Be': '\xbe', '%bE': '\xbe', '%BE': '\xbe', '%bf': '\xbf', - '%Bf': '\xbf', '%bF': '\xbf', '%BF': '\xbf', '%c0': '\xc0', '%C0': '\xc0', - '%c1': '\xc1', '%C1': '\xc1', '%c2': '\xc2', '%C2': '\xc2', '%c3': '\xc3', - '%C3': '\xc3', '%c4': '\xc4', '%C4': '\xc4', '%c5': '\xc5', '%C5': '\xc5', - '%c6': '\xc6', '%C6': '\xc6', '%c7': '\xc7', '%C7': '\xc7', '%c8': '\xc8', - '%C8': '\xc8', '%c9': '\xc9', '%C9': '\xc9', '%ca': '\xca', '%Ca': '\xca', - '%cA': '\xca', '%CA': '\xca', '%cb': '\xcb', '%Cb': '\xcb', '%cB': '\xcb', - '%CB': '\xcb', '%cc': '\xcc', '%Cc': '\xcc', '%cC': '\xcc', '%CC': '\xcc', - '%cd': '\xcd', '%Cd': '\xcd', '%cD': '\xcd', '%CD': '\xcd', '%ce': '\xce', - '%Ce': '\xce', '%cE': '\xce', '%CE': '\xce', '%cf': '\xcf', '%Cf': '\xcf', - '%cF': '\xcf', '%CF': '\xcf', '%d0': '\xd0', '%D0': '\xd0', '%d1': '\xd1', - '%D1': '\xd1', '%d2': '\xd2', '%D2': '\xd2', '%d3': '\xd3', '%D3': '\xd3', - '%d4': '\xd4', '%D4': '\xd4', '%d5': '\xd5', '%D5': '\xd5', '%d6': '\xd6', - '%D6': '\xd6', '%d7': '\xd7', '%D7': '\xd7', '%d8': '\xd8', '%D8': '\xd8', - '%d9': '\xd9', '%D9': '\xd9', '%da': '\xda', '%Da': '\xda', '%dA': '\xda', - '%DA': '\xda', '%db': '\xdb', '%Db': '\xdb', '%dB': '\xdb', '%DB': '\xdb', - '%dc': '\xdc', '%Dc': '\xdc', '%dC': '\xdc', '%DC': '\xdc', '%dd': '\xdd', - '%Dd': '\xdd', '%dD': '\xdd', '%DD': '\xdd', '%de': '\xde', '%De': '\xde', - '%dE': '\xde', '%DE': '\xde', '%df': '\xdf', '%Df': '\xdf', '%dF': '\xdf', - '%DF': '\xdf', '%e0': '\xe0', '%E0': '\xe0', '%e1': '\xe1', '%E1': '\xe1', - '%e2': '\xe2', '%E2': '\xe2', '%e3': '\xe3', '%E3': '\xe3', '%e4': '\xe4', - '%E4': '\xe4', '%e5': '\xe5', '%E5': '\xe5', '%e6': '\xe6', '%E6': '\xe6', - '%e7': '\xe7', '%E7': '\xe7', '%e8': '\xe8', '%E8': '\xe8', '%e9': '\xe9', - '%E9': '\xe9', '%ea': '\xea', '%Ea': '\xea', '%eA': '\xea', '%EA': '\xea', - '%eb': '\xeb', '%Eb': '\xeb', '%eB': '\xeb', '%EB': '\xeb', '%ec': '\xec', - '%Ec': '\xec', '%eC': '\xec', '%EC': '\xec', '%ed': '\xed', '%Ed': '\xed', - '%eD': '\xed', '%ED': '\xed', '%ee': '\xee', '%Ee': '\xee', '%eE': '\xee', - '%EE': '\xee', '%ef': '\xef', '%Ef': '\xef', '%eF': '\xef', '%EF': '\xef', - '%f0': '\xf0', '%F0': '\xf0', '%f1': '\xf1', '%F1': '\xf1', '%f2': '\xf2', - '%F2': '\xf2', '%f3': '\xf3', '%F3': '\xf3', '%f4': '\xf4', '%F4': '\xf4', - '%f5': '\xf5', '%F5': '\xf5', '%f6': '\xf6', '%F6': '\xf6', '%f7': '\xf7', - '%F7': '\xf7', '%f8': '\xf8', '%F8': '\xf8', '%f9': '\xf9', '%F9': '\xf9', - '%fa': '\xfa', '%Fa': '\xfa', '%fA': '\xfa', '%FA': '\xfa', '%fb': '\xfb', - '%Fb': '\xfb', '%fB': '\xfb', '%FB': '\xfb', '%fc': '\xfc', '%Fc': '\xfc', - '%fC': '\xfc', '%FC': '\xfc', '%fd': '\xfd', '%Fd': '\xfd', '%fD': '\xfd', - '%FD': '\xfd', '%fe': '\xfe', '%Fe': '\xfe', '%fE': '\xfe', '%FE': '\xfe', - '%ff': '\xff', '%Ff': '\xff', '%fF': '\xff', '%FF': '\xff' -} - -function encodedReplacer (match) { - return EncodedLookup[match] -} - -const STATE_KEY = 0 -const STATE_VALUE = 1 -const STATE_CHARSET = 2 -const STATE_LANG = 3 - -function parseParams (str) { - const res = [] - let state = STATE_KEY - let charset = '' - let inquote = false - let escaping = false - let p = 0 - let tmp = '' - const len = str.length - - for (var i = 0; i < len; ++i) { // eslint-disable-line no-var - const char = str[i] - if (char === '\\' && inquote) { - if (escaping) { escaping = false } else { - escaping = true - continue - } - } else if (char === '"') { - if (!escaping) { - if (inquote) { - inquote = false - state = STATE_KEY - } else { inquote = true } - continue - } else { escaping = false } - } else { - if (escaping && inquote) { tmp += '\\' } - escaping = false - if ((state === STATE_CHARSET || state === STATE_LANG) && char === "'") { - if (state === STATE_CHARSET) { - state = STATE_LANG - charset = tmp.substring(1) - } else { state = STATE_VALUE } - tmp = '' - continue - } else if (state === STATE_KEY && - (char === '*' || char === '=') && - res.length) { - state = char === '*' - ? STATE_CHARSET - : STATE_VALUE - res[p] = [tmp, undefined] - tmp = '' - continue - } else if (!inquote && char === ';') { - state = STATE_KEY - if (charset) { - if (tmp.length) { - tmp = decodeText(tmp.replace(RE_ENCODED, encodedReplacer), - 'binary', - charset) - } - charset = '' - } else if (tmp.length) { - tmp = decodeText(tmp, 'binary', 'utf8') - } - if (res[p] === undefined) { res[p] = tmp } else { res[p][1] = tmp } - tmp = '' - ++p - continue - } else if (!inquote && (char === ' ' || char === '\t')) { continue } - } - tmp += char - } - if (charset && tmp.length) { - tmp = decodeText(tmp.replace(RE_ENCODED, encodedReplacer), - 'binary', - charset) - } else if (tmp) { - tmp = decodeText(tmp, 'binary', 'utf8') - } + // Each WebSocketStream object has an associated opened promise , which is a promise. + /** @type {import('../../../util/promise').DeferredPromise} */ + #openedPromise - if (res[p] === undefined) { - if (tmp) { res[p] = tmp } - } else { res[p][1] = tmp } + // Each WebSocketStream object has an associated closed promise , which is a promise. + /** @type {import('../../../util/promise').DeferredPromise} */ + #closedPromise - return res -} + // Each WebSocketStream object has an associated readable stream , which is a ReadableStream . + /** @type {ReadableStream} */ + #readableStream + /** @type {ReadableStreamDefaultController} */ + #readableStreamController -module.exports = parseParams + // Each WebSocketStream object has an associated writable stream , which is a WritableStream . + /** @type {WritableStream} */ + #writableStream + // Each WebSocketStream object has an associated boolean handshake aborted , which is initially false. + #handshakeAborted = false -/***/ }), + /** @type {import('../websocket').Handler} */ + #handler = { + // https://whatpr.org/websockets/48/7b748d3...d5570f3.html#feedback-to-websocket-stream-from-the-protocol + onConnectionEstablished: (response, extensions) => this.#onConnectionEstablished(response, extensions), + onMessage: (opcode, data) => this.#onMessage(opcode, data), + onParserError: (err) => failWebsocketConnection(this.#handler, null, err.message), + onParserDrain: () => this.#handler.socket.resume(), + onSocketData: (chunk) => { + if (!this.#parser.write(chunk)) { + this.#handler.socket.pause() + } + }, + onSocketError: (err) => { + this.#handler.readyState = states.CLOSING -/***/ 271: -/***/ ((module) => { + if (channels.socketError.hasSubscribers) { + channels.socketError.publish(err) + } -"use strict"; -var __webpack_unused_export__; + this.#handler.socket.destroy() + }, + onSocketClose: () => this.#onSocketClose(), + onPing: () => {}, + onPong: () => {}, + readyState: states.CONNECTING, + socket: null, + closeState: new Set(), + controller: null, + wasEverConnected: false + } -const NullObject = function NullObject () { } -NullObject.prototype = Object.create(null) + /** @type {import('../receiver').ByteParser} */ + #parser -/** - * RegExp to match *( ";" parameter ) in RFC 7231 sec 3.1.1.1 - * - * parameter = token "=" ( token / quoted-string ) - * token = 1*tchar - * tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" - * / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~" - * / DIGIT / ALPHA - * ; any VCHAR, except delimiters - * quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE - * qdtext = HTAB / SP / %x21 / %x23-5B / %x5D-7E / obs-text - * obs-text = %x80-FF - * quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text ) - */ -const paramRE = /; *([!#$%&'*+.^\w`|~-]+)=("(?:[\v\u0020\u0021\u0023-\u005b\u005d-\u007e\u0080-\u00ff]|\\[\v\u0020-\u00ff])*"|[!#$%&'*+.^\w`|~-]+) */gu + constructor (url, options = undefined) { + if (!emittedExperimentalWarning) { + process.emitWarning('WebSocketStream is experimental! Expect it to change at any time.', { + code: 'UNDICI-WSS' + }) + emittedExperimentalWarning = true + } -/** - * RegExp to match quoted-pair in RFC 7230 sec 3.2.6 - * - * quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text ) - * obs-text = %x80-FF - */ -const quotedPairRE = /\\([\v\u0020-\u00ff])/gu + webidl.argumentLengthCheck(arguments, 1, 'WebSocket') -/** - * RegExp to match type in RFC 7231 sec 3.1.1.1 - * - * media-type = type "/" subtype - * type = token - * subtype = token - */ -const mediaTypeRE = /^[!#$%&'*+.^\w|~-]+\/[!#$%&'*+.^\w|~-]+$/u + url = webidl.converters.USVString(url) + if (options !== null) { + options = webidl.converters.WebSocketStreamOptions(options) + } -// default ContentType to prevent repeated object creation -const defaultContentType = { type: '', parameters: new NullObject() } -Object.freeze(defaultContentType.parameters) -Object.freeze(defaultContentType) + // 1. Let baseURL be this 's relevant settings object 's API base URL . + const baseURL = environmentSettingsObject.settingsObject.baseUrl -/** - * Parse media type to object. - * - * @param {string|object} header - * @return {Object} - * @public - */ + // 2. Let urlRecord be the result of getting a URL record given url and baseURL . + const urlRecord = getURLRecord(url, baseURL) -function parse (header) { - if (typeof header !== 'string') { - throw new TypeError('argument header is required and must be a string') - } + // 3. Let protocols be options [" protocols "] if it exists , otherwise an empty sequence. + const protocols = options.protocols - let index = header.indexOf(';') - const type = index !== -1 - ? header.slice(0, index).trim() - : header.trim() + // 4. If any of the values in protocols occur more than once or otherwise fail to match the requirements for elements that comprise the value of ` Sec-WebSocket-Protocol ` fields as defined by The WebSocket Protocol , then throw a " SyntaxError " DOMException . [WSP] + if (protocols.length !== new Set(protocols.map(p => p.toLowerCase())).size) { + throw new DOMException('Invalid Sec-WebSocket-Protocol value', 'SyntaxError') + } - if (mediaTypeRE.test(type) === false) { - throw new TypeError('invalid media type') - } + if (protocols.length > 0 && !protocols.every(p => isValidSubprotocol(p))) { + throw new DOMException('Invalid Sec-WebSocket-Protocol value', 'SyntaxError') + } - const result = { - type: type.toLowerCase(), - parameters: new NullObject() - } + // 5. Set this 's url to urlRecord . + this.#url = urlRecord.toString() - // parse parameters - if (index === -1) { - return result - } + // 6. Set this 's opened promise and closed promise to new promises. + this.#openedPromise = createDeferredPromise() + this.#closedPromise = createDeferredPromise() - let key - let match - let value + // 7. Apply backpressure to the WebSocket. + // TODO - paramRE.lastIndex = index + // 8. If options [" signal "] exists , + if (options.signal != null) { + // 8.1. Let signal be options [" signal "]. + const signal = options.signal - while ((match = paramRE.exec(header))) { - if (match.index !== index) { - throw new TypeError('invalid parameter format') - } + // 8.2. If signal is aborted , then reject this 's opened promise and closed promise with signal ’s abort reason + // and return. + if (signal.aborted) { + this.#openedPromise.reject(signal.reason) + this.#closedPromise.reject(signal.reason) + return + } - index += match[0].length - key = match[1].toLowerCase() - value = match[2] + // 8.3. Add the following abort steps to signal : + signal.addEventListener('abort', () => { + // 8.3.1. If the WebSocket connection is not yet established : [WSP] + if (!isEstablished(this.#handler.readyState)) { + // 8.3.1.1. Fail the WebSocket connection . + failWebsocketConnection(this.#handler) - if (value[0] === '"') { - // remove quotes and escapes - value = value - .slice(1, value.length - 1) + // Set this 's ready state to CLOSING . + this.#handler.readyState = states.CLOSING - quotedPairRE.test(value) && (value = value.replace(quotedPairRE, '$1')) + // Reject this 's opened promise and closed promise with signal ’s abort reason . + this.#openedPromise.reject(signal.reason) + this.#closedPromise.reject(signal.reason) + + // Set this 's handshake aborted to true. + this.#handshakeAborted = true + } + }, { once: true }) } - result.parameters[key] = value - } + // 9. Let client be this 's relevant settings object . + const client = environmentSettingsObject.settingsObject - if (index !== header.length) { - throw new TypeError('invalid parameter format') + // 10. Run this step in parallel : + // 10.1. Establish a WebSocket connection given urlRecord , protocols , and client . [FETCH] + this.#handler.controller = establishWebSocketConnection( + urlRecord, + protocols, + client, + this.#handler, + options + ) } - return result -} - -function safeParse (header) { - if (typeof header !== 'string') { - return defaultContentType + // The url getter steps are to return this 's url , serialized . + get url () { + return this.#url.toString() } - let index = header.indexOf(';') - const type = index !== -1 - ? header.slice(0, index).trim() - : header.trim() - - if (mediaTypeRE.test(type) === false) { - return defaultContentType + // The opened getter steps are to return this 's opened promise . + get opened () { + return this.#openedPromise.promise } - const result = { - type: type.toLowerCase(), - parameters: new NullObject() + // The closed getter steps are to return this 's closed promise . + get closed () { + return this.#closedPromise.promise } - // parse parameters - if (index === -1) { - return result - } + // The close( closeInfo ) method steps are: + close (closeInfo = undefined) { + if (closeInfo !== null) { + closeInfo = webidl.converters.WebSocketCloseInfo(closeInfo) + } - let key - let match - let value + // 1. Let code be closeInfo [" closeCode "] if present, or null otherwise. + const code = closeInfo.closeCode ?? null - paramRE.lastIndex = index + // 2. Let reason be closeInfo [" reason "]. + const reason = closeInfo.reason - while ((match = paramRE.exec(header))) { - if (match.index !== index) { - return defaultContentType - } + // 3. Close the WebSocket with this , code , and reason . + closeWebSocketConnection(this.#handler, code, reason, true) + } - index += match[0].length - key = match[1].toLowerCase() - value = match[2] + #write (chunk) { + // See /websockets/stream/tentative/write.any.html + chunk = webidl.converters.WebSocketStreamWrite(chunk) - if (value[0] === '"') { - // remove quotes and escapes - value = value - .slice(1, value.length - 1) + // 1. Let promise be a new promise created in stream ’s relevant realm . + const promise = createDeferredPromise() - quotedPairRE.test(value) && (value = value.replace(quotedPairRE, '$1')) - } + // 2. Let data be null. + let data = null - result.parameters[key] = value - } + // 3. Let opcode be null. + let opcode = null - if (index !== header.length) { - return defaultContentType - } + // 4. If chunk is a BufferSource , + if (webidl.is.BufferSource(chunk)) { + // 4.1. Set data to a copy of the bytes given chunk . + data = new Uint8Array(ArrayBuffer.isView(chunk) ? new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength) : chunk.slice()) - return result -} + // 4.2. Set opcode to a binary frame opcode. + opcode = opcodes.BINARY + } else { + // 5. Otherwise, -__webpack_unused_export__ = { parse, safeParse } -__webpack_unused_export__ = parse -module.exports.xL = safeParse -__webpack_unused_export__ = defaultContentType + // 5.1. Let string be the result of converting chunk to an IDL USVString . + // If this throws an exception, return a promise rejected with the exception. + let string + try { + string = webidl.converters.DOMString(chunk) + } catch (e) { + promise.reject(e) + return promise.promise + } -/***/ }), + // 5.2. Set data to the result of UTF-8 encoding string . + data = new TextEncoder().encode(string) -/***/ 3918: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nccwpck_require__) => { + // 5.3. Set opcode to a text frame opcode. + opcode = opcodes.TEXT + } -"use strict"; -// ESM COMPAT FLAG -__nccwpck_require__.r(__webpack_exports__); + // 6. In parallel, + // 6.1. Wait until there is sufficient buffer space in stream to send the message. -// EXPORTS -__nccwpck_require__.d(__webpack_exports__, { - Octokit: () => (/* binding */ dist_src_Octokit) -}); + // 6.2. If the closing handshake has not yet started , Send a WebSocket Message to stream comprised of data using opcode . + if (!this.#handler.closeState.has(sentCloseFrameState.SENT) && !this.#handler.closeState.has(sentCloseFrameState.RECEIVED)) { + const frame = new WebsocketFrameSend(data) -;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/universal-user-agent/7.0.3/cc533676cf04e8aac99e3561a188b8867414674edad01efaf2a65a6b92904df4/node_modules/universal-user-agent/index.js -function getUserAgent() { - if (typeof navigator === "object" && "userAgent" in navigator) { - return navigator.userAgent; - } + this.#handler.socket.write(frame.createFrame(opcode), () => { + promise.resolve(undefined) + }) + } - if (typeof process === "object" && process.version !== undefined) { - return `Node.js/${process.version.substr(1)} (${process.platform}; ${ - process.arch - })`; + // 6.3. Queue a global task on the WebSocket task source given stream ’s relevant global object to resolve promise with undefined. + return promise.promise } - return ""; -} + /** @type {import('../websocket').Handler['onConnectionEstablished']} */ + #onConnectionEstablished (response, parsedExtensions) { + this.#handler.socket = response.socket -;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/before-after-hook/4.0.0/1488bade5929b630234702d1039c0b9f6fcb00eaa2fa4988634014684001f87c/node_modules/before-after-hook/lib/register.js -// @ts-check + const parser = new ByteParser(this.#handler, parsedExtensions) + parser.on('drain', () => this.#handler.onParserDrain()) + parser.on('error', (err) => this.#handler.onParserError(err)) -function register(state, name, method, options) { - if (typeof method !== "function") { - throw new Error("method for before hook must be a function"); - } + this.#parser = parser - if (!options) { - options = {}; - } + // 1. Change stream ’s ready state to OPEN (1). + this.#handler.readyState = states.OPEN - if (Array.isArray(name)) { - return name.reverse().reduce((callback, name) => { - return register.bind(null, state, name, callback, options); - }, method)(); - } + // 2. Set stream ’s was ever connected to true. + // This is done in the opening handshake. - return Promise.resolve().then(() => { - if (!state.registry[name]) { - return method(options); - } + // 3. Let extensions be the extensions in use . + const extensions = parsedExtensions ?? '' - return state.registry[name].reduce((method, registered) => { - return registered.hook.bind(null, method, options); - }, method)(); - }); -} + // 4. Let protocol be the subprotocol in use . + const protocol = response.headersList.get('sec-websocket-protocol') ?? '' -;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/before-after-hook/4.0.0/1488bade5929b630234702d1039c0b9f6fcb00eaa2fa4988634014684001f87c/node_modules/before-after-hook/lib/add.js -// @ts-check + // 5. Let pullAlgorithm be an action that pulls bytes from stream . + // 6. Let cancelAlgorithm be an action that cancels stream with reason , given reason . + // 7. Let readable be a new ReadableStream . + // 8. Set up readable with pullAlgorithm and cancelAlgorithm . + const readable = new ReadableStream({ + start: (controller) => { + this.#readableStreamController = controller + }, + pull (controller) { + let chunk + while (controller.desiredSize > 0 && (chunk = response.socket.read()) !== null) { + controller.enqueue(chunk) + } + }, + cancel: (reason) => this.#cancel(reason) + }) -function addHook(state, kind, name, hook) { - const orig = hook; - if (!state.registry[name]) { - state.registry[name] = []; - } + // 9. Let writeAlgorithm be an action that writes chunk to stream , given chunk . + // 10. Let closeAlgorithm be an action that closes stream . + // 11. Let abortAlgorithm be an action that aborts stream with reason , given reason . + // 12. Let writable be a new WritableStream . + // 13. Set up writable with writeAlgorithm , closeAlgorithm , and abortAlgorithm . + const writable = new WritableStream({ + write: (chunk) => this.#write(chunk), + close: () => closeWebSocketConnection(this.#handler, null, null), + abort: (reason) => this.#closeUsingReason(reason) + }) - if (kind === "before") { - hook = (method, options) => { - return Promise.resolve() - .then(orig.bind(null, options)) - .then(method.bind(null, options)); - }; - } + // Set stream ’s readable stream to readable . + this.#readableStream = readable - if (kind === "after") { - hook = (method, options) => { - let result; - return Promise.resolve() - .then(method.bind(null, options)) - .then((result_) => { - result = result_; - return orig(result, options); - }) - .then(() => { - return result; - }); - }; - } + // Set stream ’s writable stream to writable . + this.#writableStream = writable - if (kind === "error") { - hook = (method, options) => { - return Promise.resolve() - .then(method.bind(null, options)) - .catch((error) => { - return orig(error, options); - }); - }; + // Resolve stream ’s opened promise with WebSocketOpenInfo «[ " extensions " → extensions , " protocol " → protocol , " readable " → readable , " writable " → writable ]». + this.#openedPromise.resolve({ + extensions, + protocol, + readable, + writable + }) } - state.registry[name].push({ - hook: hook, - orig: orig, - }); -} + /** @type {import('../websocket').Handler['onMessage']} */ + #onMessage (type, data) { + // 1. If stream’s ready state is not OPEN (1), then return. + if (this.#handler.readyState !== states.OPEN) { + return + } -;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/before-after-hook/4.0.0/1488bade5929b630234702d1039c0b9f6fcb00eaa2fa4988634014684001f87c/node_modules/before-after-hook/lib/remove.js -// @ts-check + // 2. Let chunk be determined by switching on type: + // - type indicates that the data is Text + // a new DOMString containing data + // - type indicates that the data is Binary + // a new Uint8Array object, created in the relevant Realm of the + // WebSocketStream object, whose contents are data + let chunk -function removeHook(state, name, method) { - if (!state.registry[name]) { - return; - } + if (type === opcodes.TEXT) { + try { + chunk = utf8Decode(data) + } catch { + failWebsocketConnection(this.#handler, 'Received invalid UTF-8 in text frame.') + return + } + } else if (type === opcodes.BINARY) { + chunk = new Uint8Array(data.buffer, data.byteOffset, data.byteLength) + } - const index = state.registry[name] - .map((registered) => { - return registered.orig; - }) - .indexOf(method); + // 3. Enqueue chunk into stream’s readable stream. + this.#readableStreamController.enqueue(chunk) - if (index === -1) { - return; + // 4. Apply backpressure to the WebSocket. } - state.registry[name].splice(index, 1); -} - -;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/before-after-hook/4.0.0/1488bade5929b630234702d1039c0b9f6fcb00eaa2fa4988634014684001f87c/node_modules/before-after-hook/index.js -// @ts-check - + /** @type {import('../websocket').Handler['onSocketClose']} */ + #onSocketClose () { + const wasClean = + this.#handler.closeState.has(sentCloseFrameState.SENT) && + this.#handler.closeState.has(sentCloseFrameState.RECEIVED) + // 1. Change the ready state to CLOSED (3). + this.#handler.readyState = states.CLOSED + // 2. If stream ’s handshake aborted is true, then return. + if (this.#handshakeAborted) { + return + } + // 3. If stream ’s was ever connected is false, then reject stream ’s opened promise with a new WebSocketError. + if (!this.#handler.wasEverConnected) { + this.#openedPromise.reject(new WebSocketError('Socket never opened')) + } -// bind with array of arguments: https://stackoverflow.com/a/21792913 -const bind = Function.bind; -const bindable = bind.bind(bind); + const result = this.#parser?.closingInfo -function bindApi(hook, state, name) { - const removeHookRef = bindable(removeHook, null).apply( - null, - name ? [state, name] : [state] - ); - hook.api = { remove: removeHookRef }; - hook.remove = removeHookRef; - ["before", "error", "after", "wrap"].forEach((kind) => { - const args = name ? [state, kind, name] : [state, kind]; - hook[kind] = hook.api[kind] = bindable(addHook, null).apply(null, args); - }); -} + // 4. Let code be the WebSocket connection close code . + // https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.5 + // If this Close control frame contains no status code, _The WebSocket + // Connection Close Code_ is considered to be 1005. If _The WebSocket + // Connection is Closed_ and no Close control frame was received by the + // endpoint (such as could occur if the underlying transport connection + // is lost), _The WebSocket Connection Close Code_ is considered to be + // 1006. + let code = result?.code ?? 1005 -function Singular() { - const singularHookName = Symbol("Singular"); - const singularHookState = { - registry: {}, - }; - const singularHook = register.bind(null, singularHookState, singularHookName); - bindApi(singularHook, singularHookState, singularHookName); - return singularHook; -} + if (!this.#handler.closeState.has(sentCloseFrameState.SENT) && !this.#handler.closeState.has(sentCloseFrameState.RECEIVED)) { + code = 1006 + } -function Collection() { - const state = { - registry: {}, - }; + // 5. Let reason be the result of applying UTF-8 decode without BOM to the WebSocket connection close reason . + const reason = result?.reason == null ? '' : utf8DecodeBytes(Buffer.from(result.reason)) - const hook = register.bind(null, state); - bindApi(hook, state); + // 6. If the connection was closed cleanly , + if (wasClean) { + // 6.1. Close stream ’s readable stream . + this.#readableStreamController.close() - return hook; -} + // 6.2. Error stream ’s writable stream with an " InvalidStateError " DOMException indicating that a closed WebSocketStream cannot be written to. + if (!this.#writableStream.locked) { + this.#writableStream.abort(new DOMException('A closed WebSocketStream cannot be written to', 'InvalidStateError')) + } -/* harmony default export */ const before_after_hook = ({ Singular, Collection }); + // 6.3. Resolve stream ’s closed promise with WebSocketCloseInfo «[ " closeCode " → code , " reason " → reason ]». + this.#closedPromise.resolve({ + closeCode: code, + reason + }) + } else { + // 7. Otherwise, -;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@octokit/endpoint/11.0.2/c40c09a599bfa85bfd8a4f173350fad63734cc375db4d3441e5b75d91852138f/node_modules/@octokit/endpoint/dist-bundle/index.js -// pkg/dist-src/defaults.js + // 7.1. Let error be a new WebSocketError whose closeCode is code and reason is reason . + const error = createUnvalidatedWebSocketError('unclean close', code, reason) + // 7.2. Error stream ’s readable stream with error . + this.#readableStreamController?.error(error) -// pkg/dist-src/version.js -var VERSION = "0.0.0-development"; + // 7.3. Error stream ’s writable stream with error . + this.#writableStream?.abort(error) -// pkg/dist-src/defaults.js -var userAgent = `octokit-endpoint.js/${VERSION} ${getUserAgent()}`; -var DEFAULTS = { - method: "GET", - baseUrl: "https://api.github.com", - headers: { - accept: "application/vnd.github.v3+json", - "user-agent": userAgent - }, - mediaType: { - format: "" + // 7.4. Reject stream ’s closed promise with error . + this.#closedPromise.reject(error) + } } -}; -// pkg/dist-src/util/lowercase-keys.js -function lowercaseKeys(object) { - if (!object) { - return {}; - } - return Object.keys(object).reduce((newObj, key) => { - newObj[key.toLowerCase()] = object[key]; - return newObj; - }, {}); -} + #closeUsingReason (reason) { + // 1. Let code be null. + let code = null -// pkg/dist-src/util/is-plain-object.js -function isPlainObject(value) { - if (typeof value !== "object" || value === null) return false; - if (Object.prototype.toString.call(value) !== "[object Object]") return false; - const proto = Object.getPrototypeOf(value); - if (proto === null) return true; - const Ctor = Object.prototype.hasOwnProperty.call(proto, "constructor") && proto.constructor; - return typeof Ctor === "function" && Ctor instanceof Ctor && Function.prototype.call(Ctor) === Function.prototype.call(value); -} + // 2. Let reasonString be the empty string. + let reasonString = '' -// pkg/dist-src/util/merge-deep.js -function mergeDeep(defaults, options) { - const result = Object.assign({}, defaults); - Object.keys(options).forEach((key) => { - if (isPlainObject(options[key])) { - if (!(key in defaults)) Object.assign(result, { [key]: options[key] }); - else result[key] = mergeDeep(defaults[key], options[key]); - } else { - Object.assign(result, { [key]: options[key] }); - } - }); - return result; -} + // 3. If reason implements WebSocketError , + if (webidl.is.WebSocketError(reason)) { + // 3.1. Set code to reason ’s closeCode . + code = reason.closeCode -// pkg/dist-src/util/remove-undefined-properties.js -function removeUndefinedProperties(obj) { - for (const key in obj) { - if (obj[key] === void 0) { - delete obj[key]; + // 3.2. Set reasonString to reason ’s reason . + reasonString = reason.reason } - } - return obj; -} -// pkg/dist-src/merge.js -function merge(defaults, route, options) { - if (typeof route === "string") { - let [method, url] = route.split(" "); - options = Object.assign(url ? { method, url } : { url: method }, options); - } else { - options = Object.assign({}, route); - } - options.headers = lowercaseKeys(options.headers); - removeUndefinedProperties(options); - removeUndefinedProperties(options.headers); - const mergedOptions = mergeDeep(defaults || {}, options); - if (options.url === "/graphql") { - if (defaults && defaults.mediaType.previews?.length) { - mergedOptions.mediaType.previews = defaults.mediaType.previews.filter( - (preview) => !mergedOptions.mediaType.previews.includes(preview) - ).concat(mergedOptions.mediaType.previews); - } - mergedOptions.mediaType.previews = (mergedOptions.mediaType.previews || []).map((preview) => preview.replace(/-preview/, "")); + // 4. Close the WebSocket with stream , code , and reasonString . If this throws an exception, + // discard code and reasonString and close the WebSocket with stream . + closeWebSocketConnection(this.#handler, code, reasonString) } - return mergedOptions; -} -// pkg/dist-src/util/add-query-parameters.js -function addQueryParameters(url, parameters) { - const separator = /\?/.test(url) ? "&" : "?"; - const names = Object.keys(parameters); - if (names.length === 0) { - return url; + // To cancel a WebSocketStream stream given reason , close using reason giving stream and reason . + #cancel (reason) { + this.#closeUsingReason(reason) } - return url + separator + names.map((name) => { - if (name === "q") { - return "q=" + parameters.q.split("+").map(encodeURIComponent).join("+"); - } - return `${name}=${encodeURIComponent(parameters[name])}`; - }).join("&"); } -// pkg/dist-src/util/extract-url-variable-names.js -var urlVariableRegex = /\{[^{}}]+\}/g; -function removeNonChars(variableName) { - return variableName.replace(/(?:^\W+)|(?:(? a.concat(b), []); -} +}) -// pkg/dist-src/util/omit.js -function omit(object, keysToOmit) { - const result = { __proto__: null }; - for (const key of Object.keys(object)) { - if (keysToOmit.indexOf(key) === -1) { - result[key] = object[key]; - } +webidl.converters.WebSocketStreamOptions = webidl.dictionaryConverter([ + { + key: 'protocols', + converter: webidl.sequenceConverter(webidl.converters.USVString), + defaultValue: () => [] + }, + { + key: 'signal', + converter: webidl.nullableConverter(webidl.converters.AbortSignal), + defaultValue: () => null } - return result; -} +]) -// pkg/dist-src/util/url-template.js -function encodeReserved(str) { - return str.split(/(%[0-9A-Fa-f]{2})/g).map(function(part) { - if (!/%[0-9A-Fa-f]/.test(part)) { - part = encodeURI(part).replace(/%5B/g, "[").replace(/%5D/g, "]"); - } - return part; - }).join(""); -} -function encodeUnreserved(str) { - return encodeURIComponent(str).replace(/[!'()*]/g, function(c) { - return "%" + c.charCodeAt(0).toString(16).toUpperCase(); - }); -} -function encodeValue(operator, value, key) { - value = operator === "+" || operator === "#" ? encodeReserved(value) : encodeUnreserved(value); - if (key) { - return encodeUnreserved(key) + "=" + value; - } else { - return value; - } -} -function isDefined(value) { - return value !== void 0 && value !== null; -} -function isKeyOperator(operator) { - return operator === ";" || operator === "&" || operator === "?"; -} -function getValues(context, operator, key, modifier) { - var value = context[key], result = []; - if (isDefined(value) && value !== "") { - if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") { - value = value.toString(); - if (modifier && modifier !== "*") { - value = value.substring(0, parseInt(modifier, 10)); - } - result.push( - encodeValue(operator, value, isKeyOperator(operator) ? key : "") - ); - } else { - if (modifier === "*") { - if (Array.isArray(value)) { - value.filter(isDefined).forEach(function(value2) { - result.push( - encodeValue(operator, value2, isKeyOperator(operator) ? key : "") - ); - }); - } else { - Object.keys(value).forEach(function(k) { - if (isDefined(value[k])) { - result.push(encodeValue(operator, value[k], k)); - } - }); - } - } else { - const tmp = []; - if (Array.isArray(value)) { - value.filter(isDefined).forEach(function(value2) { - tmp.push(encodeValue(operator, value2)); - }); - } else { - Object.keys(value).forEach(function(k) { - if (isDefined(value[k])) { - tmp.push(encodeUnreserved(k)); - tmp.push(encodeValue(operator, value[k].toString())); - } - }); - } - if (isKeyOperator(operator)) { - result.push(encodeUnreserved(key) + "=" + tmp.join(",")); - } else if (tmp.length !== 0) { - result.push(tmp.join(",")); - } - } - } - } else { - if (operator === ";") { - if (isDefined(value)) { - result.push(encodeUnreserved(key)); - } - } else if (value === "" && (operator === "&" || operator === "?")) { - result.push(encodeUnreserved(key) + "="); - } else if (value === "") { - result.push(""); - } - } - return result; -} -function parseUrl(template) { - return { - expand: expand.bind(null, template) - }; -} -function expand(template, context) { - var operators = ["+", "#", ".", "/", ";", "?", "&"]; - template = template.replace( - /\{([^\{\}]+)\}|([^\{\}]+)/g, - function(_, expression, literal) { - if (expression) { - let operator = ""; - const values = []; - if (operators.indexOf(expression.charAt(0)) !== -1) { - operator = expression.charAt(0); - expression = expression.substr(1); - } - expression.split(/,/g).forEach(function(variable) { - var tmp = /([^:\*]*)(?::(\d+)|(\*))?/.exec(variable); - values.push(getValues(context, operator, tmp[1], tmp[2] || tmp[3])); - }); - if (operator && operator !== "+") { - var separator = ","; - if (operator === "?") { - separator = "&"; - } else if (operator !== "#") { - separator = operator; - } - return (values.length !== 0 ? operator : "") + values.join(separator); - } else { - return values.join(","); - } - } else { - return encodeReserved(literal); - } - } - ); - if (template === "/") { - return template; - } else { - return template.replace(/\/$/, ""); +webidl.converters.WebSocketCloseInfo = webidl.dictionaryConverter([ + { + key: 'closeCode', + converter: (V) => webidl.converters['unsigned short'](V, webidl.attributes.EnforceRange) + }, + { + key: 'reason', + converter: webidl.converters.USVString, + defaultValue: () => '' } -} +]) -// pkg/dist-src/parse.js -function parse(options) { - let method = options.method.toUpperCase(); - let url = (options.url || "/").replace(/:([a-z]\w+)/g, "{$1}"); - let headers = Object.assign({}, options.headers); - let body; - let parameters = omit(options, [ - "method", - "baseUrl", - "url", - "headers", - "request", - "mediaType" - ]); - const urlVariableNames = extractUrlVariableNames(url); - url = parseUrl(url).expand(parameters); - if (!/^http/.test(url)) { - url = options.baseUrl + url; - } - const omittedParameters = Object.keys(options).filter((option) => urlVariableNames.includes(option)).concat("baseUrl"); - const remainingParameters = omit(parameters, omittedParameters); - const isBinaryRequest = /application\/octet-stream/i.test(headers.accept); - if (!isBinaryRequest) { - if (options.mediaType.format) { - headers.accept = headers.accept.split(/,/).map( - (format) => format.replace( - /application\/vnd(\.\w+)(\.v3)?(\.\w+)?(\+json)?$/, - `application/vnd$1$2.${options.mediaType.format}` - ) - ).join(","); - } - if (url.endsWith("/graphql")) { - if (options.mediaType.previews?.length) { - const previewsFromAcceptHeader = headers.accept.match(/(? { - const format = options.mediaType.format ? `.${options.mediaType.format}` : "+json"; - return `application/vnd.github.${preview}-preview${format}`; - }).join(","); - } - } - } - if (["GET", "HEAD"].includes(method)) { - url = addQueryParameters(url, remainingParameters); - } else { - if ("data" in remainingParameters) { - body = remainingParameters.data; - } else { - if (Object.keys(remainingParameters).length) { - body = remainingParameters; - } - } - } - if (!headers["content-type"] && typeof body !== "undefined") { - headers["content-type"] = "application/json; charset=utf-8"; - } - if (["PATCH", "PUT"].includes(method) && typeof body === "undefined") { - body = ""; +webidl.converters.WebSocketStreamWrite = function (V) { + if (typeof V === 'string') { + return webidl.converters.USVString(V) } - return Object.assign( - { method, url, headers }, - typeof body !== "undefined" ? { body } : null, - options.request ? { request: options.request } : null - ); -} -// pkg/dist-src/endpoint-with-defaults.js -function endpointWithDefaults(defaults, route, options) { - return parse(merge(defaults, route, options)); + return webidl.converters.BufferSource(V) } -// pkg/dist-src/with-defaults.js -function withDefaults(oldDefaults, newDefaults) { - const DEFAULTS2 = merge(oldDefaults, newDefaults); - const endpoint2 = endpointWithDefaults.bind(null, DEFAULTS2); - return Object.assign(endpoint2, { - DEFAULTS: DEFAULTS2, - defaults: withDefaults.bind(null, DEFAULTS2), - merge: merge.bind(null, DEFAULTS2), - parse - }); -} +module.exports = { WebSocketStream } -// pkg/dist-src/index.js -var endpoint = withDefaults(null, DEFAULTS); +/***/ }), -// EXTERNAL MODULE: ../../../Library/pnpm/store/v10/links/fast-content-type-parse/3.0.0/d143e4b4a18b5ed5e3b5a3ccf9a6b4667d50bd62c3713f15509757ebe8c7d68d/node_modules/fast-content-type-parse/index.js -var fast_content_type_parse = __nccwpck_require__(271); -;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@octokit/request-error/7.0.2/5b0e4bdf473658ab369e5c04938a642f5025a766a3e8adaff76f1cdd8b503197/node_modules/@octokit/request-error/dist-src/index.js -class RequestError extends Error { - name; - /** - * http status code - */ - status; - /** - * Request options that lead to the error. - */ - request; - /** - * Response object if a response was received - */ - response; - constructor(message, statusCode, options) { - super(message); - this.name = "HttpError"; - this.status = Number.parseInt(statusCode); - if (Number.isNaN(this.status)) { - this.status = 0; - } - if ("response" in options) { - this.response = options.response; - } - const requestCopy = Object.assign({}, options.request); - if (options.request.headers.authorization) { - requestCopy.headers = Object.assign({}, options.request.headers, { - authorization: options.request.headers.authorization.replace( - /(? { -;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@octokit/request/10.0.6/574737933ac68a53049a40cb32cfa67924485c9890c2abfe6ab565bb07f83cfd/node_modules/@octokit/request/dist-bundle/index.js -// pkg/dist-src/index.js +const { states, opcodes } = __nccwpck_require__(1078) +const { isUtf8 } = __nccwpck_require__(4573) +const { removeHTTPWhitespace } = __nccwpck_require__(1410) +const { collectASequenceOfCodePointsFast } = __nccwpck_require__(5074) -// pkg/dist-src/defaults.js +/** + * @param {number} readyState + * @returns {boolean} + */ +function isConnecting (readyState) { + // If the WebSocket connection is not yet established, and the connection + // is not yet closed, then the WebSocket connection is in the CONNECTING state. + return readyState === states.CONNECTING +} +/** + * @param {number} readyState + * @returns {boolean} + */ +function isEstablished (readyState) { + // If the server's response is validated as provided for above, it is + // said that _The WebSocket Connection is Established_ and that the + // WebSocket Connection is in the OPEN state. + return readyState === states.OPEN +} -// pkg/dist-src/version.js -var dist_bundle_VERSION = "10.0.6"; +/** + * @param {number} readyState + * @returns {boolean} + */ +function isClosing (readyState) { + // Upon either sending or receiving a Close control frame, it is said + // that _The WebSocket Closing Handshake is Started_ and that the + // WebSocket connection is in the CLOSING state. + return readyState === states.CLOSING +} -// pkg/dist-src/defaults.js -var defaults_default = { - headers: { - "user-agent": `octokit-request.js/${dist_bundle_VERSION} ${getUserAgent()}` - } -}; +/** + * @param {number} readyState + * @returns {boolean} + */ +function isClosed (readyState) { + return readyState === states.CLOSED +} -// pkg/dist-src/fetch-wrapper.js +/** + * @see https://dom.spec.whatwg.org/#concept-event-fire + * @param {string} e + * @param {EventTarget} target + * @param {(...args: ConstructorParameters) => Event} eventFactory + * @param {EventInit | undefined} eventInitDict + * @returns {void} + */ +function fireEvent (e, target, eventFactory = (type, init) => new Event(type, init), eventInitDict = {}) { + // 1. If eventConstructor is not given, then let eventConstructor be Event. + // 2. Let event be the result of creating an event given eventConstructor, + // in the relevant realm of target. + // 3. Initialize event’s type attribute to e. + const event = eventFactory(e, eventInitDict) -// pkg/dist-src/is-plain-object.js -function dist_bundle_isPlainObject(value) { - if (typeof value !== "object" || value === null) return false; - if (Object.prototype.toString.call(value) !== "[object Object]") return false; - const proto = Object.getPrototypeOf(value); - if (proto === null) return true; - const Ctor = Object.prototype.hasOwnProperty.call(proto, "constructor") && proto.constructor; - return typeof Ctor === "function" && Ctor instanceof Ctor && Function.prototype.call(Ctor) === Function.prototype.call(value); + // 4. Initialize any other IDL attributes of event as described in the + // invocation of this algorithm. + + // 5. Return the result of dispatching event at target, with legacy target + // override flag set if set. + target.dispatchEvent(event) } -// pkg/dist-src/fetch-wrapper.js +/** + * @see https://websockets.spec.whatwg.org/#feedback-from-the-protocol + * @param {import('./websocket').Handler} handler + * @param {number} type Opcode + * @param {Buffer} data application data + * @returns {void} + */ +function websocketMessageReceived (handler, type, data) { + handler.onMessage(type, data) +} -async function fetchWrapper(requestOptions) { - const fetch = requestOptions.request?.fetch || globalThis.fetch; - if (!fetch) { - throw new Error( - "fetch is not set. Please pass a fetch implementation as new Octokit({ request: { fetch }}). Learn more at https://github.com/octokit/octokit.js/#fetch-missing" - ); - } - const log = requestOptions.request?.log || console; - const parseSuccessResponseBody = requestOptions.request?.parseSuccessResponseBody !== false; - const body = dist_bundle_isPlainObject(requestOptions.body) || Array.isArray(requestOptions.body) ? JSON.stringify(requestOptions.body) : requestOptions.body; - const requestHeaders = Object.fromEntries( - Object.entries(requestOptions.headers).map(([name, value]) => [ - name, - String(value) - ]) - ); - let fetchResponse; - try { - fetchResponse = await fetch(requestOptions.url, { - method: requestOptions.method, - body, - redirect: requestOptions.request?.redirect, - headers: requestHeaders, - signal: requestOptions.request?.signal, - // duplex must be set if request.body is ReadableStream or Async Iterables. - // See https://fetch.spec.whatwg.org/#dom-requestinit-duplex. - ...requestOptions.body && { duplex: "half" } - }); - } catch (error) { - let message = "Unknown Error"; - if (error instanceof Error) { - if (error.name === "AbortError") { - error.status = 500; - throw error; - } - message = error.message; - if (error.name === "TypeError" && "cause" in error) { - if (error.cause instanceof Error) { - message = error.cause.message; - } else if (typeof error.cause === "string") { - message = error.cause; - } - } - } - const requestError = new RequestError(message, 500, { - request: requestOptions - }); - requestError.cause = error; - throw requestError; - } - const status = fetchResponse.status; - const url = fetchResponse.url; - const responseHeaders = {}; - for (const [key, value] of fetchResponse.headers) { - responseHeaders[key] = value; - } - const octokitResponse = { - url, - status, - headers: responseHeaders, - data: "" - }; - if ("deprecation" in responseHeaders) { - const matches = responseHeaders.link && responseHeaders.link.match(/<([^<>]+)>; rel="deprecation"/); - const deprecationLink = matches && matches.pop(); - log.warn( - `[@octokit/request] "${requestOptions.method} ${requestOptions.url}" is deprecated. It is scheduled to be removed on ${responseHeaders.sunset}${deprecationLink ? `. See ${deprecationLink}` : ""}` - ); - } - if (status === 204 || status === 205) { - return octokitResponse; - } - if (requestOptions.method === "HEAD") { - if (status < 400) { - return octokitResponse; - } - throw new RequestError(fetchResponse.statusText, status, { - response: octokitResponse, - request: requestOptions - }); - } - if (status === 304) { - octokitResponse.data = await getResponseData(fetchResponse); - throw new RequestError("Not modified", status, { - response: octokitResponse, - request: requestOptions - }); - } - if (status >= 400) { - octokitResponse.data = await getResponseData(fetchResponse); - throw new RequestError(toErrorMessage(octokitResponse.data), status, { - response: octokitResponse, - request: requestOptions - }); +/** + * @param {Buffer} buffer + * @returns {ArrayBuffer} + */ +function toArrayBuffer (buffer) { + if (buffer.byteLength === buffer.buffer.byteLength) { + return buffer.buffer } - octokitResponse.data = parseSuccessResponseBody ? await getResponseData(fetchResponse) : fetchResponse.body; - return octokitResponse; + return new Uint8Array(buffer).buffer } -async function getResponseData(response) { - const contentType = response.headers.get("content-type"); - if (!contentType) { - return response.text().catch(() => ""); + +/** + * @see https://datatracker.ietf.org/doc/html/rfc6455 + * @see https://datatracker.ietf.org/doc/html/rfc2616 + * @see https://bugs.chromium.org/p/chromium/issues/detail?id=398407 + * @param {string} protocol + * @returns {boolean} + */ +function isValidSubprotocol (protocol) { + // If present, this value indicates one + // or more comma-separated subprotocol the client wishes to speak, + // ordered by preference. The elements that comprise this value + // MUST be non-empty strings with characters in the range U+0021 to + // U+007E not including separator characters as defined in + // [RFC2616] and MUST all be unique strings. + if (protocol.length === 0) { + return false } - const mimetype = (0,fast_content_type_parse/* safeParse */.xL)(contentType); - if (isJSONResponse(mimetype)) { - let text = ""; - try { - text = await response.text(); - return JSON.parse(text); - } catch (err) { - return text; + + for (let i = 0; i < protocol.length; ++i) { + const code = protocol.charCodeAt(i) + + if ( + code < 0x21 || // CTL, contains SP (0x20) and HT (0x09) + code > 0x7E || + code === 0x22 || // " + code === 0x28 || // ( + code === 0x29 || // ) + code === 0x2C || // , + code === 0x2F || // / + code === 0x3A || // : + code === 0x3B || // ; + code === 0x3C || // < + code === 0x3D || // = + code === 0x3E || // > + code === 0x3F || // ? + code === 0x40 || // @ + code === 0x5B || // [ + code === 0x5C || // \ + code === 0x5D || // ] + code === 0x7B || // { + code === 0x7D // } + ) { + return false } - } else if (mimetype.type.startsWith("text/") || mimetype.parameters.charset?.toLowerCase() === "utf-8") { - return response.text().catch(() => ""); - } else { - return response.arrayBuffer().catch(() => new ArrayBuffer(0)); } + + return true } -function isJSONResponse(mimetype) { - return mimetype.type === "application/json" || mimetype.type === "application/scim+json"; -} -function toErrorMessage(data) { - if (typeof data === "string") { - return data; - } - if (data instanceof ArrayBuffer) { - return "Unknown error"; - } - if ("message" in data) { - const suffix = "documentation_url" in data ? ` - ${data.documentation_url}` : ""; - return Array.isArray(data.errors) ? `${data.message}: ${data.errors.map((v) => JSON.stringify(v)).join(", ")}${suffix}` : `${data.message}${suffix}`; + +/** + * @see https://datatracker.ietf.org/doc/html/rfc6455#section-7-4 + * @param {number} code + * @returns {boolean} + */ +function isValidStatusCode (code) { + if (code >= 1000 && code < 1015) { + return ( + code !== 1004 && // reserved + code !== 1005 && // "MUST NOT be set as a status code" + code !== 1006 // "MUST NOT be set as a status code" + ) } - return `Unknown error: ${JSON.stringify(data)}`; + + return code >= 3000 && code <= 4999 } -// pkg/dist-src/with-defaults.js -function dist_bundle_withDefaults(oldEndpoint, newDefaults) { - const endpoint2 = oldEndpoint.defaults(newDefaults); - const newApi = function(route, parameters) { - const endpointOptions = endpoint2.merge(route, parameters); - if (!endpointOptions.request || !endpointOptions.request.hook) { - return fetchWrapper(endpoint2.parse(endpointOptions)); - } - const request2 = (route2, parameters2) => { - return fetchWrapper( - endpoint2.parse(endpoint2.merge(route2, parameters2)) - ); - }; - Object.assign(request2, { - endpoint: endpoint2, - defaults: dist_bundle_withDefaults.bind(null, endpoint2) - }); - return endpointOptions.request.hook(request2, endpointOptions); - }; - return Object.assign(newApi, { - endpoint: endpoint2, - defaults: dist_bundle_withDefaults.bind(null, endpoint2) - }); +/** + * @see https://datatracker.ietf.org/doc/html/rfc6455#section-5.5 + * @param {number} opcode + * @returns {boolean} + */ +function isControlFrame (opcode) { + return ( + opcode === opcodes.CLOSE || + opcode === opcodes.PING || + opcode === opcodes.PONG + ) } -// pkg/dist-src/index.js -var request = dist_bundle_withDefaults(endpoint, defaults_default); +/** + * @param {number} opcode + * @returns {boolean} + */ +function isContinuationFrame (opcode) { + return opcode === opcodes.CONTINUATION +} +/** + * @param {number} opcode + * @returns {boolean} + */ +function isTextBinaryFrame (opcode) { + return opcode === opcodes.TEXT || opcode === opcodes.BINARY +} -;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@octokit/graphql/9.0.3/15813a75b543b69a2dc2f9bebbfc8fe9957e5d14a2be8c5307ea39d391ddf87e/node_modules/@octokit/graphql/dist-bundle/index.js -// pkg/dist-src/index.js +/** + * + * @param {number} opcode + * @returns {boolean} + */ +function isValidOpcode (opcode) { + return isTextBinaryFrame(opcode) || isContinuationFrame(opcode) || isControlFrame(opcode) +} +/** + * Parses a Sec-WebSocket-Extensions header value. + * @param {string} extensions + * @returns {Map} + */ +// TODO(@Uzlopak, @KhafraDev): make compliant https://datatracker.ietf.org/doc/html/rfc6455#section-9.1 +function parseExtensions (extensions) { + const position = { position: 0 } + const extensionList = new Map() + while (position.position < extensions.length) { + const pair = collectASequenceOfCodePointsFast(';', extensions, position) + const [name, value = ''] = pair.split('=', 2) -// pkg/dist-src/version.js -var graphql_dist_bundle_VERSION = "0.0.0-development"; + extensionList.set( + removeHTTPWhitespace(name, true, false), + removeHTTPWhitespace(value, false, true) + ) -// pkg/dist-src/with-defaults.js + position.position++ + } + return extensionList +} -// pkg/dist-src/graphql.js +/** + * @see https://www.rfc-editor.org/rfc/rfc7692#section-7.1.2.2 + * @description "client-max-window-bits = 1*DIGIT" + * @param {string} value + * @returns {boolean} + */ +function isValidClientWindowBits (value) { + for (let i = 0; i < value.length; i++) { + const byte = value.charCodeAt(i) + if (byte < 0x30 || byte > 0x39) { + return false + } + } -// pkg/dist-src/error.js -function _buildMessageForResponseErrors(data) { - return `Request failed due to following response errors: -` + data.errors.map((e) => ` - ${e.message}`).join("\n"); + return true } -var GraphqlResponseError = class extends Error { - constructor(request2, headers, response) { - super(_buildMessageForResponseErrors(response)); - this.request = request2; - this.headers = headers; - this.response = response; - this.errors = response.errors; - this.data = response.data; - if (Error.captureStackTrace) { - Error.captureStackTrace(this, this.constructor); - } + +/** + * @see https://whatpr.org/websockets/48/7b748d3...d5570f3.html#get-a-url-record + * @param {string} url + * @param {string} [baseURL] + */ +function getURLRecord (url, baseURL) { + // 1. Let urlRecord be the result of applying the URL parser to url with baseURL . + // 2. If urlRecord is failure, then throw a " SyntaxError " DOMException . + let urlRecord + + try { + urlRecord = new URL(url, baseURL) + } catch (e) { + throw new DOMException(e, 'SyntaxError') } - name = "GraphqlResponseError"; - errors; - data; -}; -// pkg/dist-src/graphql.js -var NON_VARIABLE_OPTIONS = [ - "method", - "baseUrl", - "url", - "headers", - "request", - "query", - "mediaType", - "operationName" -]; -var FORBIDDEN_VARIABLE_OPTIONS = ["query", "method", "url"]; -var GHES_V3_SUFFIX_REGEX = /\/api\/v3\/?$/; -function graphql(request2, query, options) { - if (options) { - if (typeof query === "string" && "query" in options) { - return Promise.reject( - new Error(`[@octokit/graphql] "query" cannot be used as variable name`) - ); - } - for (const key in options) { - if (!FORBIDDEN_VARIABLE_OPTIONS.includes(key)) continue; - return Promise.reject( - new Error( - `[@octokit/graphql] "${key}" cannot be used as variable name` - ) - ); - } + // 3. If urlRecord ’s scheme is " http ", then set urlRecord ’s scheme to " ws ". + // 4. Otherwise, if urlRecord ’s scheme is " https ", set urlRecord ’s scheme to " wss ". + if (urlRecord.protocol === 'http:') { + urlRecord.protocol = 'ws:' + } else if (urlRecord.protocol === 'https:') { + urlRecord.protocol = 'wss:' } - const parsedOptions = typeof query === "string" ? Object.assign({ query }, options) : query; - const requestOptions = Object.keys( - parsedOptions - ).reduce((result, key) => { - if (NON_VARIABLE_OPTIONS.includes(key)) { - result[key] = parsedOptions[key]; - return result; - } - if (!result.variables) { - result.variables = {}; - } - result.variables[key] = parsedOptions[key]; - return result; - }, {}); - const baseUrl = parsedOptions.baseUrl || request2.endpoint.DEFAULTS.baseUrl; - if (GHES_V3_SUFFIX_REGEX.test(baseUrl)) { - requestOptions.url = baseUrl.replace(GHES_V3_SUFFIX_REGEX, "/api/graphql"); + + // 5. If urlRecord ’s scheme is not " ws " or " wss ", then throw a " SyntaxError " DOMException . + if (urlRecord.protocol !== 'ws:' && urlRecord.protocol !== 'wss:') { + throw new DOMException('expected a ws: or wss: url', 'SyntaxError') } - return request2(requestOptions).then((response) => { - if (response.data.errors) { - const headers = {}; - for (const key of Object.keys(response.headers)) { - headers[key] = response.headers[key]; - } - throw new GraphqlResponseError( - requestOptions, - headers, - response.data - ); - } - return response.data.data; - }); -} -// pkg/dist-src/with-defaults.js -function graphql_dist_bundle_withDefaults(request2, newDefaults) { - const newRequest = request2.defaults(newDefaults); - const newApi = (query, options) => { - return graphql(newRequest, query, options); - }; - return Object.assign(newApi, { - defaults: graphql_dist_bundle_withDefaults.bind(null, newRequest), - endpoint: newRequest.endpoint - }); -} + // If urlRecord ’s fragment is non-null, then throw a " SyntaxError " DOMException . + if (urlRecord.hash.length || urlRecord.href.endsWith('#')) { + throw new DOMException('hash', 'SyntaxError') + } -// pkg/dist-src/index.js -var graphql2 = graphql_dist_bundle_withDefaults(request, { - headers: { - "user-agent": `octokit-graphql.js/${graphql_dist_bundle_VERSION} ${getUserAgent()}` - }, - method: "POST", - url: "/graphql" -}); -function withCustomRequest(customRequest) { - return graphql_dist_bundle_withDefaults(customRequest, { - method: "POST", - url: "/graphql" - }); + // Return urlRecord . + return urlRecord } +// https://whatpr.org/websockets/48.html#validate-close-code-and-reason +function validateCloseCodeAndReason (code, reason) { + // 1. If code is not null, but is neither an integer equal to + // 1000 nor an integer in the range 3000 to 4999, inclusive, + // throw an "InvalidAccessError" DOMException. + if (code !== null) { + if (code !== 1000 && (code < 3000 || code > 4999)) { + throw new DOMException('invalid code', 'InvalidAccessError') + } + } -;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@octokit/auth-token/6.0.0/08b03fb2cdd18bc44a83469bff0b5dd0f542de689bdb885e7a744e288e52565a/node_modules/@octokit/auth-token/dist-bundle/index.js -// pkg/dist-src/is-jwt.js -var b64url = "(?:[a-zA-Z0-9_-]+)"; -var sep = "\\."; -var jwtRE = new RegExp(`^${b64url}${sep}${b64url}${sep}${b64url}$`); -var isJWT = jwtRE.test.bind(jwtRE); + // 2. If reason is not null, then: + if (reason !== null) { + // 2.1. Let reasonBytes be the result of UTF-8 encoding reason. + // 2.2. If reasonBytes is longer than 123 bytes, then throw a + // "SyntaxError" DOMException. + const reasonBytesLength = Buffer.byteLength(reason) -// pkg/dist-src/auth.js -async function auth(token) { - const isApp = isJWT(token); - const isInstallation = token.startsWith("v1.") || token.startsWith("ghs_"); - const isUserToServer = token.startsWith("ghu_"); - const tokenType = isApp ? "app" : isInstallation ? "installation" : isUserToServer ? "user-to-server" : "oauth"; - return { - type: "token", - token, - tokenType - }; + if (reasonBytesLength > 123) { + throw new DOMException(`Reason must be less than 123 bytes; received ${reasonBytesLength}`, 'SyntaxError') + } + } } -// pkg/dist-src/with-authorization-prefix.js -function withAuthorizationPrefix(token) { - if (token.split(/\./).length === 3) { - return `bearer ${token}`; +/** + * Converts a Buffer to utf-8, even on platforms without icu. + * @type {(buffer: Buffer) => string} + */ +const utf8Decode = (() => { + if (typeof process.versions.icu === 'string') { + const fatalDecoder = new TextDecoder('utf-8', { fatal: true }) + return fatalDecoder.decode.bind(fatalDecoder) } - return `token ${token}`; -} + return function (buffer) { + if (isUtf8(buffer)) { + return buffer.toString('utf-8') + } + throw new TypeError('Invalid utf-8 received.') + } +})() -// pkg/dist-src/hook.js -async function hook(token, request, route, parameters) { - const endpoint = request.endpoint.merge( - route, - parameters - ); - endpoint.headers.authorization = withAuthorizationPrefix(token); - return request(endpoint); +module.exports = { + isConnecting, + isEstablished, + isClosing, + isClosed, + fireEvent, + isValidSubprotocol, + isValidStatusCode, + websocketMessageReceived, + utf8Decode, + isControlFrame, + isContinuationFrame, + isTextBinaryFrame, + isValidOpcode, + parseExtensions, + isValidClientWindowBits, + toArrayBuffer, + getURLRecord, + validateCloseCodeAndReason } -// pkg/dist-src/index.js -var createTokenAuth = function createTokenAuth2(token) { - if (!token) { - throw new Error("[@octokit/auth-token] No token passed to createTokenAuth"); - } - if (typeof token !== "string") { - throw new Error( - "[@octokit/auth-token] Token passed to createTokenAuth is not a string" - ); - } - token = token.replace(/^(token|bearer) +/i, ""); - return Object.assign(auth.bind(null, token), { - hook: hook.bind(null, token) - }); -}; +/***/ }), -;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@octokit/core/7.0.6/62376fcda0a91a2d50ad254cd93e83ae4bd5317a357d24ba6c141c5fcf9334af/node_modules/@octokit/core/dist-src/version.js -const version_VERSION = "7.0.6"; +/***/ 1652: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@octokit/core/7.0.6/62376fcda0a91a2d50ad254cd93e83ae4bd5317a357d24ba6c141c5fcf9334af/node_modules/@octokit/core/dist-src/index.js +const { isArrayBuffer } = __nccwpck_require__(3429) +const { webidl } = __nccwpck_require__(909) +const { URLSerializer } = __nccwpck_require__(1410) +const { environmentSettingsObject } = __nccwpck_require__(3106) +const { staticPropertyDescriptors, states, sentCloseFrameState, sendHints, opcodes } = __nccwpck_require__(1078) +const { + isConnecting, + isEstablished, + isClosing, + isClosed, + isValidSubprotocol, + fireEvent, + utf8Decode, + toArrayBuffer, + getURLRecord +} = __nccwpck_require__(6667) +const { establishWebSocketConnection, closeWebSocketConnection, failWebsocketConnection } = __nccwpck_require__(7823) +const { ByteParser } = __nccwpck_require__(2094) +const { kEnumerableProperty } = __nccwpck_require__(2550) +const { getGlobalDispatcher } = __nccwpck_require__(7483) +const { ErrorEvent, CloseEvent, createFastMessageEvent } = __nccwpck_require__(1954) +const { SendQueue } = __nccwpck_require__(4738) +const { WebsocketFrameSend } = __nccwpck_require__(2222) +const { channels } = __nccwpck_require__(2248) +/** + * @typedef {object} Handler + * @property {(response: any, extensions?: string[]) => void} onConnectionEstablished + * @property {(opcode: number, data: Buffer) => void} onMessage + * @property {(error: Error) => void} onParserError + * @property {() => void} onParserDrain + * @property {(chunk: Buffer) => void} onSocketData + * @property {(err: Error) => void} onSocketError + * @property {() => void} onSocketClose + * @property {(body: Buffer) => void} onPing + * @property {(body: Buffer) => void} onPong + * + * @property {number} readyState + * @property {import('stream').Duplex} socket + * @property {Set} closeState + * @property {import('../fetch/index').Fetch} controller + * @property {boolean} [wasEverConnected=false] + */ +// https://websockets.spec.whatwg.org/#interface-definition +class WebSocket extends EventTarget { + #events = { + open: null, + error: null, + close: null, + message: null + } + #bufferedAmount = 0 + #protocol = '' + #extensions = '' + /** @type {SendQueue} */ + #sendQueue -const noop = () => { -}; -const consoleWarn = console.warn.bind(console); -const consoleError = console.error.bind(console); -function createLogger(logger = {}) { - if (typeof logger.debug !== "function") { - logger.debug = noop; - } - if (typeof logger.info !== "function") { - logger.info = noop; - } - if (typeof logger.warn !== "function") { - logger.warn = consoleWarn; - } - if (typeof logger.error !== "function") { - logger.error = consoleError; - } - return logger; -} -const userAgentTrail = `octokit-core.js/${version_VERSION} ${getUserAgent()}`; -class Octokit { - static VERSION = version_VERSION; - static defaults(defaults) { - const OctokitWithDefaults = class extends this { - constructor(...args) { - const options = args[0] || {}; - if (typeof defaults === "function") { - super(defaults(options)); - return; - } - super( - Object.assign( - {}, - defaults, - options, - options.userAgent && defaults.userAgent ? { - userAgent: `${options.userAgent} ${defaults.userAgent}` - } : null - ) - ); + /** @type {Handler} */ + #handler = { + onConnectionEstablished: (response, extensions) => this.#onConnectionEstablished(response, extensions), + onMessage: (opcode, data) => this.#onMessage(opcode, data), + onParserError: (err) => failWebsocketConnection(this.#handler, null, err.message), + onParserDrain: () => this.#onParserDrain(), + onSocketData: (chunk) => { + if (!this.#parser.write(chunk)) { + this.#handler.socket.pause() } - }; - return OctokitWithDefaults; + }, + onSocketError: (err) => { + this.#handler.readyState = states.CLOSING + + if (channels.socketError.hasSubscribers) { + channels.socketError.publish(err) + } + + this.#handler.socket.destroy() + }, + onSocketClose: () => this.#onSocketClose(), + onPing: (body) => { + if (channels.ping.hasSubscribers) { + channels.ping.publish({ + payload: body, + websocket: this + }) + } + }, + onPong: (body) => { + if (channels.pong.hasSubscribers) { + channels.pong.publish({ + payload: body, + websocket: this + }) + } + }, + + readyState: states.CONNECTING, + socket: null, + closeState: new Set(), + controller: null, + wasEverConnected: false } - static plugins = []; + + #url + #binaryType + /** @type {import('./receiver').ByteParser} */ + #parser + /** - * Attach a plugin (or many) to your Octokit instance. - * - * @example - * const API = Octokit.plugin(plugin1, plugin2, plugin3, ...) + * @param {string} url + * @param {string|string[]} protocols */ - static plugin(...newPlugins) { - const currentPlugins = this.plugins; - const NewOctokit = class extends this { - static plugins = currentPlugins.concat( - newPlugins.filter((plugin) => !currentPlugins.includes(plugin)) - ); - }; - return NewOctokit; - } - constructor(options = {}) { - const hook = new before_after_hook.Collection(); - const requestDefaults = { - baseUrl: request.endpoint.DEFAULTS.baseUrl, - headers: {}, - request: Object.assign({}, options.request, { - // @ts-ignore internal usage only, no need to type - hook: hook.bind(null, "request") - }), - mediaType: { - previews: [], - format: "" - } - }; - requestDefaults.headers["user-agent"] = options.userAgent ? `${options.userAgent} ${userAgentTrail}` : userAgentTrail; - if (options.baseUrl) { - requestDefaults.baseUrl = options.baseUrl; - } - if (options.previews) { - requestDefaults.mediaType.previews = options.previews; - } - if (options.timeZone) { - requestDefaults.headers["time-zone"] = options.timeZone; - } - this.request = request.defaults(requestDefaults); - this.graphql = withCustomRequest(this.request).defaults(requestDefaults); - this.log = createLogger(options.log); - this.hook = hook; - if (!options.authStrategy) { - if (!options.auth) { - this.auth = async () => ({ - type: "unauthenticated" - }); - } else { - const auth = createTokenAuth(options.auth); - hook.wrap("request", auth.hook); - this.auth = auth; - } - } else { - const { authStrategy, ...otherOptions } = options; - const auth = authStrategy( - Object.assign( - { - request: this.request, - log: this.log, - // we pass the current octokit instance as well as its constructor options - // to allow for authentication strategies that return a new octokit instance - // that shares the same internal state as the current one. The original - // requirement for this was the "event-octokit" authentication strategy - // of https://github.com/probot/octokit-auth-probot. - octokit: this, - octokitOptions: otherOptions - }, - options.auth - ) - ); - hook.wrap("request", auth.hook); - this.auth = auth; + constructor (url, protocols = []) { + super() + + webidl.util.markAsUncloneable(this) + + const prefix = 'WebSocket constructor' + webidl.argumentLengthCheck(arguments, 1, prefix) + + const options = webidl.converters['DOMString or sequence or WebSocketInit'](protocols, prefix, 'options') + + url = webidl.converters.USVString(url) + protocols = options.protocols + + // 1. Let baseURL be this's relevant settings object's API base URL. + const baseURL = environmentSettingsObject.settingsObject.baseUrl + + // 2. Let urlRecord be the result of getting a URL record given url and baseURL. + const urlRecord = getURLRecord(url, baseURL) + + // 3. If protocols is a string, set protocols to a sequence consisting + // of just that string. + if (typeof protocols === 'string') { + protocols = [protocols] } - const classConstructor = this.constructor; - for (let i = 0; i < classConstructor.plugins.length; ++i) { - Object.assign(this, classConstructor.plugins[i](this, options)); + + // 4. If any of the values in protocols occur more than once or otherwise + // fail to match the requirements for elements that comprise the value + // of `Sec-WebSocket-Protocol` fields as defined by The WebSocket + // protocol, then throw a "SyntaxError" DOMException. + if (protocols.length !== new Set(protocols.map(p => p.toLowerCase())).size) { + throw new DOMException('Invalid Sec-WebSocket-Protocol value', 'SyntaxError') } - } - // assigned during constructor - request; - graphql; - log; - hook; - // TODO: type `octokit.auth` based on passed options.authStrategy - auth; -} + if (protocols.length > 0 && !protocols.every(p => isValidSubprotocol(p))) { + throw new DOMException('Invalid Sec-WebSocket-Protocol value', 'SyntaxError') + } -;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@octokit/plugin-request-log/6.0.0/14b098bdb1f0daf676fbad85305c94e3f10bcf8e271a2efb211b347676ca5591/node_modules/@octokit/plugin-request-log/dist-src/version.js -const dist_src_version_VERSION = "6.0.0"; + // 5. Set this's url to urlRecord. + this.#url = new URL(urlRecord.href) + // 6. Let client be this's relevant settings object. + const client = environmentSettingsObject.settingsObject -;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@octokit/plugin-request-log/6.0.0/14b098bdb1f0daf676fbad85305c94e3f10bcf8e271a2efb211b347676ca5591/node_modules/@octokit/plugin-request-log/dist-src/index.js + // 7. Run this step in parallel: + // 7.1. Establish a WebSocket connection given urlRecord, protocols, + // and client. + this.#handler.controller = establishWebSocketConnection( + urlRecord, + protocols, + client, + this.#handler, + options + ) -function requestLog(octokit) { - octokit.hook.wrap("request", (request, options) => { - octokit.log.debug("request", options); - const start = Date.now(); - const requestOptions = octokit.request.endpoint.parse(options); - const path = requestOptions.url.replace(options.baseUrl, ""); - return request(options).then((response) => { - const requestId = response.headers["x-github-request-id"]; - octokit.log.info( - `${requestOptions.method} ${path} - ${response.status} with id ${requestId} in ${Date.now() - start}ms` - ); - return response; - }).catch((error) => { - const requestId = error.response?.headers["x-github-request-id"] || "UNKNOWN"; - octokit.log.error( - `${requestOptions.method} ${path} - ${error.status} with id ${requestId} in ${Date.now() - start}ms` - ); - throw error; - }); - }); -} -requestLog.VERSION = dist_src_version_VERSION; + // Each WebSocket object has an associated ready state, which is a + // number representing the state of the connection. Initially it must + // be CONNECTING (0). + this.#handler.readyState = WebSocket.CONNECTING + // The extensions attribute must initially return the empty string. -;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@octokit/plugin-paginate-rest/14.0.0/19ec16e2c5fdca4ca7f96c8aee21c7af275d329ba4ff9a2237dac909640ef23f/node_modules/@octokit/plugin-paginate-rest/dist-bundle/index.js -// pkg/dist-src/version.js -var plugin_paginate_rest_dist_bundle_VERSION = "0.0.0-development"; + // The protocol attribute must initially return the empty string. -// pkg/dist-src/normalize-paginated-list-response.js -function normalizePaginatedListResponse(response) { - if (!response.data) { - return { - ...response, - data: [] - }; - } - const responseNeedsNormalization = ("total_count" in response.data || "total_commits" in response.data) && !("url" in response.data); - if (!responseNeedsNormalization) return response; - const incompleteResults = response.data.incomplete_results; - const repositorySelection = response.data.repository_selection; - const totalCount = response.data.total_count; - const totalCommits = response.data.total_commits; - delete response.data.incomplete_results; - delete response.data.repository_selection; - delete response.data.total_count; - delete response.data.total_commits; - const namespaceKey = Object.keys(response.data)[0]; - const data = response.data[namespaceKey]; - response.data = data; - if (typeof incompleteResults !== "undefined") { - response.data.incomplete_results = incompleteResults; - } - if (typeof repositorySelection !== "undefined") { - response.data.repository_selection = repositorySelection; + // Each WebSocket object has an associated binary type, which is a + // BinaryType. Initially it must be "blob". + this.#binaryType = 'blob' } - response.data.total_count = totalCount; - response.data.total_commits = totalCommits; - return response; -} -// pkg/dist-src/iterator.js -function iterator(octokit, route, parameters) { - const options = typeof route === "function" ? route.endpoint(parameters) : octokit.request.endpoint(route, parameters); - const requestMethod = typeof route === "function" ? route : octokit.request; - const method = options.method; - const headers = options.headers; - let url = options.url; - return { - [Symbol.asyncIterator]: () => ({ - async next() { - if (!url) return { done: true }; - try { - const response = await requestMethod({ method, url, headers }); - const normalizedResponse = normalizePaginatedListResponse(response); - url = ((normalizedResponse.headers.link || "").match( - /<([^<>]+)>;\s*rel="next"/ - ) || [])[1]; - if (!url && "total_commits" in normalizedResponse.data) { - const parsedUrl = new URL(normalizedResponse.url); - const params = parsedUrl.searchParams; - const page = parseInt(params.get("page") || "1", 10); - const per_page = parseInt(params.get("per_page") || "250", 10); - if (page * per_page < normalizedResponse.data.total_commits) { - params.set("page", String(page + 1)); - url = parsedUrl.toString(); - } - } - return { value: normalizedResponse }; - } catch (error) { - if (error.status !== 409) throw error; - url = ""; - return { - value: { - status: 200, - headers: {}, - data: [] - } - }; - } - } - }) - }; -} + /** + * @see https://websockets.spec.whatwg.org/#dom-websocket-close + * @param {number|undefined} code + * @param {string|undefined} reason + */ + close (code = undefined, reason = undefined) { + webidl.brandCheck(this, WebSocket) -// pkg/dist-src/paginate.js -function paginate(octokit, route, parameters, mapFn) { - if (typeof parameters === "function") { - mapFn = parameters; - parameters = void 0; - } - return gather( - octokit, - [], - iterator(octokit, route, parameters)[Symbol.asyncIterator](), - mapFn - ); -} -function gather(octokit, results, iterator2, mapFn) { - return iterator2.next().then((result) => { - if (result.done) { - return results; - } - let earlyExit = false; - function done() { - earlyExit = true; + const prefix = 'WebSocket.close' + + if (code !== undefined) { + code = webidl.converters['unsigned short'](code, prefix, 'code', webidl.attributes.Clamp) } - results = results.concat( - mapFn ? mapFn(result.value, done) : result.value.data - ); - if (earlyExit) { - return results; + + if (reason !== undefined) { + reason = webidl.converters.USVString(reason) } - return gather(octokit, results, iterator2, mapFn); - }); -} -// pkg/dist-src/compose-paginate.js -var composePaginateRest = Object.assign(paginate, { - iterator -}); + // 1. If code is the special value "missing", then set code to null. + code ??= null -// pkg/dist-src/generated/paginating-endpoints.js -var paginatingEndpoints = (/* unused pure expression or super */ null && ([ - "GET /advisories", - "GET /app/hook/deliveries", - "GET /app/installation-requests", - "GET /app/installations", - "GET /assignments/{assignment_id}/accepted_assignments", - "GET /classrooms", - "GET /classrooms/{classroom_id}/assignments", - "GET /enterprises/{enterprise}/code-security/configurations", - "GET /enterprises/{enterprise}/code-security/configurations/{configuration_id}/repositories", - "GET /enterprises/{enterprise}/dependabot/alerts", - "GET /enterprises/{enterprise}/teams", - "GET /enterprises/{enterprise}/teams/{enterprise-team}/memberships", - "GET /enterprises/{enterprise}/teams/{enterprise-team}/organizations", - "GET /events", - "GET /gists", - "GET /gists/public", - "GET /gists/starred", - "GET /gists/{gist_id}/comments", - "GET /gists/{gist_id}/commits", - "GET /gists/{gist_id}/forks", - "GET /installation/repositories", - "GET /issues", - "GET /licenses", - "GET /marketplace_listing/plans", - "GET /marketplace_listing/plans/{plan_id}/accounts", - "GET /marketplace_listing/stubbed/plans", - "GET /marketplace_listing/stubbed/plans/{plan_id}/accounts", - "GET /networks/{owner}/{repo}/events", - "GET /notifications", - "GET /organizations", - "GET /organizations/{org}/dependabot/repository-access", - "GET /orgs/{org}/actions/cache/usage-by-repository", - "GET /orgs/{org}/actions/hosted-runners", - "GET /orgs/{org}/actions/permissions/repositories", - "GET /orgs/{org}/actions/permissions/self-hosted-runners/repositories", - "GET /orgs/{org}/actions/runner-groups", - "GET /orgs/{org}/actions/runner-groups/{runner_group_id}/hosted-runners", - "GET /orgs/{org}/actions/runner-groups/{runner_group_id}/repositories", - "GET /orgs/{org}/actions/runner-groups/{runner_group_id}/runners", - "GET /orgs/{org}/actions/runners", - "GET /orgs/{org}/actions/secrets", - "GET /orgs/{org}/actions/secrets/{secret_name}/repositories", - "GET /orgs/{org}/actions/variables", - "GET /orgs/{org}/actions/variables/{name}/repositories", - "GET /orgs/{org}/attestations/repositories", - "GET /orgs/{org}/attestations/{subject_digest}", - "GET /orgs/{org}/blocks", - "GET /orgs/{org}/campaigns", - "GET /orgs/{org}/code-scanning/alerts", - "GET /orgs/{org}/code-security/configurations", - "GET /orgs/{org}/code-security/configurations/{configuration_id}/repositories", - "GET /orgs/{org}/codespaces", - "GET /orgs/{org}/codespaces/secrets", - "GET /orgs/{org}/codespaces/secrets/{secret_name}/repositories", - "GET /orgs/{org}/copilot/billing/seats", - "GET /orgs/{org}/copilot/metrics", - "GET /orgs/{org}/dependabot/alerts", - "GET /orgs/{org}/dependabot/secrets", - "GET /orgs/{org}/dependabot/secrets/{secret_name}/repositories", - "GET /orgs/{org}/events", - "GET /orgs/{org}/failed_invitations", - "GET /orgs/{org}/hooks", - "GET /orgs/{org}/hooks/{hook_id}/deliveries", - "GET /orgs/{org}/insights/api/route-stats/{actor_type}/{actor_id}", - "GET /orgs/{org}/insights/api/subject-stats", - "GET /orgs/{org}/insights/api/user-stats/{user_id}", - "GET /orgs/{org}/installations", - "GET /orgs/{org}/invitations", - "GET /orgs/{org}/invitations/{invitation_id}/teams", - "GET /orgs/{org}/issues", - "GET /orgs/{org}/members", - "GET /orgs/{org}/members/{username}/codespaces", - "GET /orgs/{org}/migrations", - "GET /orgs/{org}/migrations/{migration_id}/repositories", - "GET /orgs/{org}/organization-roles/{role_id}/teams", - "GET /orgs/{org}/organization-roles/{role_id}/users", - "GET /orgs/{org}/outside_collaborators", - "GET /orgs/{org}/packages", - "GET /orgs/{org}/packages/{package_type}/{package_name}/versions", - "GET /orgs/{org}/personal-access-token-requests", - "GET /orgs/{org}/personal-access-token-requests/{pat_request_id}/repositories", - "GET /orgs/{org}/personal-access-tokens", - "GET /orgs/{org}/personal-access-tokens/{pat_id}/repositories", - "GET /orgs/{org}/private-registries", - "GET /orgs/{org}/projects", - "GET /orgs/{org}/projectsV2", - "GET /orgs/{org}/projectsV2/{project_number}/fields", - "GET /orgs/{org}/projectsV2/{project_number}/items", - "GET /orgs/{org}/properties/values", - "GET /orgs/{org}/public_members", - "GET /orgs/{org}/repos", - "GET /orgs/{org}/rulesets", - "GET /orgs/{org}/rulesets/rule-suites", - "GET /orgs/{org}/rulesets/{ruleset_id}/history", - "GET /orgs/{org}/secret-scanning/alerts", - "GET /orgs/{org}/security-advisories", - "GET /orgs/{org}/settings/immutable-releases/repositories", - "GET /orgs/{org}/settings/network-configurations", - "GET /orgs/{org}/team/{team_slug}/copilot/metrics", - "GET /orgs/{org}/teams", - "GET /orgs/{org}/teams/{team_slug}/discussions", - "GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments", - "GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions", - "GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions", - "GET /orgs/{org}/teams/{team_slug}/invitations", - "GET /orgs/{org}/teams/{team_slug}/members", - "GET /orgs/{org}/teams/{team_slug}/projects", - "GET /orgs/{org}/teams/{team_slug}/repos", - "GET /orgs/{org}/teams/{team_slug}/teams", - "GET /projects/{project_id}/collaborators", - "GET /repos/{owner}/{repo}/actions/artifacts", - "GET /repos/{owner}/{repo}/actions/caches", - "GET /repos/{owner}/{repo}/actions/organization-secrets", - "GET /repos/{owner}/{repo}/actions/organization-variables", - "GET /repos/{owner}/{repo}/actions/runners", - "GET /repos/{owner}/{repo}/actions/runs", - "GET /repos/{owner}/{repo}/actions/runs/{run_id}/artifacts", - "GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}/jobs", - "GET /repos/{owner}/{repo}/actions/runs/{run_id}/jobs", - "GET /repos/{owner}/{repo}/actions/secrets", - "GET /repos/{owner}/{repo}/actions/variables", - "GET /repos/{owner}/{repo}/actions/workflows", - "GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/runs", - "GET /repos/{owner}/{repo}/activity", - "GET /repos/{owner}/{repo}/assignees", - "GET /repos/{owner}/{repo}/attestations/{subject_digest}", - "GET /repos/{owner}/{repo}/branches", - "GET /repos/{owner}/{repo}/check-runs/{check_run_id}/annotations", - "GET /repos/{owner}/{repo}/check-suites/{check_suite_id}/check-runs", - "GET /repos/{owner}/{repo}/code-scanning/alerts", - "GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}/instances", - "GET /repos/{owner}/{repo}/code-scanning/analyses", - "GET /repos/{owner}/{repo}/codespaces", - "GET /repos/{owner}/{repo}/codespaces/devcontainers", - "GET /repos/{owner}/{repo}/codespaces/secrets", - "GET /repos/{owner}/{repo}/collaborators", - "GET /repos/{owner}/{repo}/comments", - "GET /repos/{owner}/{repo}/comments/{comment_id}/reactions", - "GET /repos/{owner}/{repo}/commits", - "GET /repos/{owner}/{repo}/commits/{commit_sha}/comments", - "GET /repos/{owner}/{repo}/commits/{commit_sha}/pulls", - "GET /repos/{owner}/{repo}/commits/{ref}/check-runs", - "GET /repos/{owner}/{repo}/commits/{ref}/check-suites", - "GET /repos/{owner}/{repo}/commits/{ref}/status", - "GET /repos/{owner}/{repo}/commits/{ref}/statuses", - "GET /repos/{owner}/{repo}/compare/{basehead}", - "GET /repos/{owner}/{repo}/compare/{base}...{head}", - "GET /repos/{owner}/{repo}/contributors", - "GET /repos/{owner}/{repo}/dependabot/alerts", - "GET /repos/{owner}/{repo}/dependabot/secrets", - "GET /repos/{owner}/{repo}/deployments", - "GET /repos/{owner}/{repo}/deployments/{deployment_id}/statuses", - "GET /repos/{owner}/{repo}/environments", - "GET /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies", - "GET /repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules/apps", - "GET /repos/{owner}/{repo}/environments/{environment_name}/secrets", - "GET /repos/{owner}/{repo}/environments/{environment_name}/variables", - "GET /repos/{owner}/{repo}/events", - "GET /repos/{owner}/{repo}/forks", - "GET /repos/{owner}/{repo}/hooks", - "GET /repos/{owner}/{repo}/hooks/{hook_id}/deliveries", - "GET /repos/{owner}/{repo}/invitations", - "GET /repos/{owner}/{repo}/issues", - "GET /repos/{owner}/{repo}/issues/comments", - "GET /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions", - "GET /repos/{owner}/{repo}/issues/events", - "GET /repos/{owner}/{repo}/issues/{issue_number}/comments", - "GET /repos/{owner}/{repo}/issues/{issue_number}/dependencies/blocked_by", - "GET /repos/{owner}/{repo}/issues/{issue_number}/dependencies/blocking", - "GET /repos/{owner}/{repo}/issues/{issue_number}/events", - "GET /repos/{owner}/{repo}/issues/{issue_number}/labels", - "GET /repos/{owner}/{repo}/issues/{issue_number}/reactions", - "GET /repos/{owner}/{repo}/issues/{issue_number}/sub_issues", - "GET /repos/{owner}/{repo}/issues/{issue_number}/timeline", - "GET /repos/{owner}/{repo}/keys", - "GET /repos/{owner}/{repo}/labels", - "GET /repos/{owner}/{repo}/milestones", - "GET /repos/{owner}/{repo}/milestones/{milestone_number}/labels", - "GET /repos/{owner}/{repo}/notifications", - "GET /repos/{owner}/{repo}/pages/builds", - "GET /repos/{owner}/{repo}/projects", - "GET /repos/{owner}/{repo}/pulls", - "GET /repos/{owner}/{repo}/pulls/comments", - "GET /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions", - "GET /repos/{owner}/{repo}/pulls/{pull_number}/comments", - "GET /repos/{owner}/{repo}/pulls/{pull_number}/commits", - "GET /repos/{owner}/{repo}/pulls/{pull_number}/files", - "GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews", - "GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/comments", - "GET /repos/{owner}/{repo}/releases", - "GET /repos/{owner}/{repo}/releases/{release_id}/assets", - "GET /repos/{owner}/{repo}/releases/{release_id}/reactions", - "GET /repos/{owner}/{repo}/rules/branches/{branch}", - "GET /repos/{owner}/{repo}/rulesets", - "GET /repos/{owner}/{repo}/rulesets/rule-suites", - "GET /repos/{owner}/{repo}/rulesets/{ruleset_id}/history", - "GET /repos/{owner}/{repo}/secret-scanning/alerts", - "GET /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}/locations", - "GET /repos/{owner}/{repo}/security-advisories", - "GET /repos/{owner}/{repo}/stargazers", - "GET /repos/{owner}/{repo}/subscribers", - "GET /repos/{owner}/{repo}/tags", - "GET /repos/{owner}/{repo}/teams", - "GET /repos/{owner}/{repo}/topics", - "GET /repositories", - "GET /search/code", - "GET /search/commits", - "GET /search/issues", - "GET /search/labels", - "GET /search/repositories", - "GET /search/topics", - "GET /search/users", - "GET /teams/{team_id}/discussions", - "GET /teams/{team_id}/discussions/{discussion_number}/comments", - "GET /teams/{team_id}/discussions/{discussion_number}/comments/{comment_number}/reactions", - "GET /teams/{team_id}/discussions/{discussion_number}/reactions", - "GET /teams/{team_id}/invitations", - "GET /teams/{team_id}/members", - "GET /teams/{team_id}/projects", - "GET /teams/{team_id}/repos", - "GET /teams/{team_id}/teams", - "GET /user/blocks", - "GET /user/codespaces", - "GET /user/codespaces/secrets", - "GET /user/emails", - "GET /user/followers", - "GET /user/following", - "GET /user/gpg_keys", - "GET /user/installations", - "GET /user/installations/{installation_id}/repositories", - "GET /user/issues", - "GET /user/keys", - "GET /user/marketplace_purchases", - "GET /user/marketplace_purchases/stubbed", - "GET /user/memberships/orgs", - "GET /user/migrations", - "GET /user/migrations/{migration_id}/repositories", - "GET /user/orgs", - "GET /user/packages", - "GET /user/packages/{package_type}/{package_name}/versions", - "GET /user/public_emails", - "GET /user/repos", - "GET /user/repository_invitations", - "GET /user/social_accounts", - "GET /user/ssh_signing_keys", - "GET /user/starred", - "GET /user/subscriptions", - "GET /user/teams", - "GET /users", - "GET /users/{username}/attestations/{subject_digest}", - "GET /users/{username}/events", - "GET /users/{username}/events/orgs/{org}", - "GET /users/{username}/events/public", - "GET /users/{username}/followers", - "GET /users/{username}/following", - "GET /users/{username}/gists", - "GET /users/{username}/gpg_keys", - "GET /users/{username}/keys", - "GET /users/{username}/orgs", - "GET /users/{username}/packages", - "GET /users/{username}/projects", - "GET /users/{username}/projectsV2", - "GET /users/{username}/projectsV2/{project_number}/fields", - "GET /users/{username}/projectsV2/{project_number}/items", - "GET /users/{username}/received_events", - "GET /users/{username}/received_events/public", - "GET /users/{username}/repos", - "GET /users/{username}/social_accounts", - "GET /users/{username}/ssh_signing_keys", - "GET /users/{username}/starred", - "GET /users/{username}/subscriptions" -])); + // 2. If reason is the special value "missing", then set reason to the empty string. + reason ??= '' -// pkg/dist-src/paginating-endpoints.js -function isPaginatingEndpoint(arg) { - if (typeof arg === "string") { - return paginatingEndpoints.includes(arg); - } else { - return false; + // 3. Close the WebSocket with this, code, and reason. + closeWebSocketConnection(this.#handler, code, reason, true) } -} -// pkg/dist-src/index.js -function paginateRest(octokit) { - return { - paginate: Object.assign(paginate.bind(null, octokit), { - iterator: iterator.bind(null, octokit) - }) - }; -} -paginateRest.VERSION = plugin_paginate_rest_dist_bundle_VERSION; + /** + * @see https://websockets.spec.whatwg.org/#dom-websocket-send + * @param {NodeJS.TypedArray|ArrayBuffer|Blob|string} data + */ + send (data) { + webidl.brandCheck(this, WebSocket) + const prefix = 'WebSocket.send' + webidl.argumentLengthCheck(arguments, 1, prefix) -;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@octokit/plugin-rest-endpoint-methods/17.0.0/23bcad6a6f09bbdd8bd9193c1b6ebd3b4d7d5c15f3d5d6a119345284a74f0760/node_modules/@octokit/plugin-rest-endpoint-methods/dist-src/version.js -const plugin_rest_endpoint_methods_dist_src_version_VERSION = "17.0.0"; + data = webidl.converters.WebSocketSendData(data, prefix, 'data') -//# sourceMappingURL=version.js.map + // 1. If this's ready state is CONNECTING, then throw an + // "InvalidStateError" DOMException. + if (isConnecting(this.#handler.readyState)) { + throw new DOMException('Sent before connected.', 'InvalidStateError') + } -;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@octokit/plugin-rest-endpoint-methods/17.0.0/23bcad6a6f09bbdd8bd9193c1b6ebd3b4d7d5c15f3d5d6a119345284a74f0760/node_modules/@octokit/plugin-rest-endpoint-methods/dist-src/generated/endpoints.js -const Endpoints = { - actions: { - addCustomLabelsToSelfHostedRunnerForOrg: [ - "POST /orgs/{org}/actions/runners/{runner_id}/labels" - ], - addCustomLabelsToSelfHostedRunnerForRepo: [ - "POST /repos/{owner}/{repo}/actions/runners/{runner_id}/labels" - ], - addRepoAccessToSelfHostedRunnerGroupInOrg: [ - "PUT /orgs/{org}/actions/runner-groups/{runner_group_id}/repositories/{repository_id}" - ], - addSelectedRepoToOrgSecret: [ - "PUT /orgs/{org}/actions/secrets/{secret_name}/repositories/{repository_id}" - ], - addSelectedRepoToOrgVariable: [ - "PUT /orgs/{org}/actions/variables/{name}/repositories/{repository_id}" - ], - approveWorkflowRun: [ - "POST /repos/{owner}/{repo}/actions/runs/{run_id}/approve" - ], - cancelWorkflowRun: [ - "POST /repos/{owner}/{repo}/actions/runs/{run_id}/cancel" - ], - createEnvironmentVariable: [ - "POST /repos/{owner}/{repo}/environments/{environment_name}/variables" - ], - createHostedRunnerForOrg: ["POST /orgs/{org}/actions/hosted-runners"], - createOrUpdateEnvironmentSecret: [ - "PUT /repos/{owner}/{repo}/environments/{environment_name}/secrets/{secret_name}" - ], - createOrUpdateOrgSecret: ["PUT /orgs/{org}/actions/secrets/{secret_name}"], - createOrUpdateRepoSecret: [ - "PUT /repos/{owner}/{repo}/actions/secrets/{secret_name}" - ], - createOrgVariable: ["POST /orgs/{org}/actions/variables"], - createRegistrationTokenForOrg: [ - "POST /orgs/{org}/actions/runners/registration-token" - ], - createRegistrationTokenForRepo: [ - "POST /repos/{owner}/{repo}/actions/runners/registration-token" - ], - createRemoveTokenForOrg: ["POST /orgs/{org}/actions/runners/remove-token"], - createRemoveTokenForRepo: [ - "POST /repos/{owner}/{repo}/actions/runners/remove-token" - ], - createRepoVariable: ["POST /repos/{owner}/{repo}/actions/variables"], - createWorkflowDispatch: [ - "POST /repos/{owner}/{repo}/actions/workflows/{workflow_id}/dispatches" - ], - deleteActionsCacheById: [ - "DELETE /repos/{owner}/{repo}/actions/caches/{cache_id}" - ], - deleteActionsCacheByKey: [ - "DELETE /repos/{owner}/{repo}/actions/caches{?key,ref}" - ], - deleteArtifact: [ - "DELETE /repos/{owner}/{repo}/actions/artifacts/{artifact_id}" - ], - deleteCustomImageFromOrg: [ - "DELETE /orgs/{org}/actions/hosted-runners/images/custom/{image_definition_id}" - ], - deleteCustomImageVersionFromOrg: [ - "DELETE /orgs/{org}/actions/hosted-runners/images/custom/{image_definition_id}/versions/{version}" - ], - deleteEnvironmentSecret: [ - "DELETE /repos/{owner}/{repo}/environments/{environment_name}/secrets/{secret_name}" - ], - deleteEnvironmentVariable: [ - "DELETE /repos/{owner}/{repo}/environments/{environment_name}/variables/{name}" - ], - deleteHostedRunnerForOrg: [ - "DELETE /orgs/{org}/actions/hosted-runners/{hosted_runner_id}" - ], - deleteOrgSecret: ["DELETE /orgs/{org}/actions/secrets/{secret_name}"], - deleteOrgVariable: ["DELETE /orgs/{org}/actions/variables/{name}"], - deleteRepoSecret: [ - "DELETE /repos/{owner}/{repo}/actions/secrets/{secret_name}" - ], - deleteRepoVariable: [ - "DELETE /repos/{owner}/{repo}/actions/variables/{name}" - ], - deleteSelfHostedRunnerFromOrg: [ - "DELETE /orgs/{org}/actions/runners/{runner_id}" - ], - deleteSelfHostedRunnerFromRepo: [ - "DELETE /repos/{owner}/{repo}/actions/runners/{runner_id}" - ], - deleteWorkflowRun: ["DELETE /repos/{owner}/{repo}/actions/runs/{run_id}"], - deleteWorkflowRunLogs: [ - "DELETE /repos/{owner}/{repo}/actions/runs/{run_id}/logs" - ], - disableSelectedRepositoryGithubActionsOrganization: [ - "DELETE /orgs/{org}/actions/permissions/repositories/{repository_id}" - ], - disableWorkflow: [ - "PUT /repos/{owner}/{repo}/actions/workflows/{workflow_id}/disable" - ], - downloadArtifact: [ - "GET /repos/{owner}/{repo}/actions/artifacts/{artifact_id}/{archive_format}" - ], - downloadJobLogsForWorkflowRun: [ - "GET /repos/{owner}/{repo}/actions/jobs/{job_id}/logs" - ], - downloadWorkflowRunAttemptLogs: [ - "GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}/logs" - ], - downloadWorkflowRunLogs: [ - "GET /repos/{owner}/{repo}/actions/runs/{run_id}/logs" - ], - enableSelectedRepositoryGithubActionsOrganization: [ - "PUT /orgs/{org}/actions/permissions/repositories/{repository_id}" - ], - enableWorkflow: [ - "PUT /repos/{owner}/{repo}/actions/workflows/{workflow_id}/enable" - ], - forceCancelWorkflowRun: [ - "POST /repos/{owner}/{repo}/actions/runs/{run_id}/force-cancel" - ], - generateRunnerJitconfigForOrg: [ - "POST /orgs/{org}/actions/runners/generate-jitconfig" - ], - generateRunnerJitconfigForRepo: [ - "POST /repos/{owner}/{repo}/actions/runners/generate-jitconfig" - ], - getActionsCacheList: ["GET /repos/{owner}/{repo}/actions/caches"], - getActionsCacheUsage: ["GET /repos/{owner}/{repo}/actions/cache/usage"], - getActionsCacheUsageByRepoForOrg: [ - "GET /orgs/{org}/actions/cache/usage-by-repository" - ], - getActionsCacheUsageForOrg: ["GET /orgs/{org}/actions/cache/usage"], - getAllowedActionsOrganization: [ - "GET /orgs/{org}/actions/permissions/selected-actions" - ], - getAllowedActionsRepository: [ - "GET /repos/{owner}/{repo}/actions/permissions/selected-actions" - ], - getArtifact: ["GET /repos/{owner}/{repo}/actions/artifacts/{artifact_id}"], - getCustomImageForOrg: [ - "GET /orgs/{org}/actions/hosted-runners/images/custom/{image_definition_id}" - ], - getCustomImageVersionForOrg: [ - "GET /orgs/{org}/actions/hosted-runners/images/custom/{image_definition_id}/versions/{version}" - ], - getCustomOidcSubClaimForRepo: [ - "GET /repos/{owner}/{repo}/actions/oidc/customization/sub" - ], - getEnvironmentPublicKey: [ - "GET /repos/{owner}/{repo}/environments/{environment_name}/secrets/public-key" - ], - getEnvironmentSecret: [ - "GET /repos/{owner}/{repo}/environments/{environment_name}/secrets/{secret_name}" - ], - getEnvironmentVariable: [ - "GET /repos/{owner}/{repo}/environments/{environment_name}/variables/{name}" - ], - getGithubActionsDefaultWorkflowPermissionsOrganization: [ - "GET /orgs/{org}/actions/permissions/workflow" - ], - getGithubActionsDefaultWorkflowPermissionsRepository: [ - "GET /repos/{owner}/{repo}/actions/permissions/workflow" - ], - getGithubActionsPermissionsOrganization: [ - "GET /orgs/{org}/actions/permissions" - ], - getGithubActionsPermissionsRepository: [ - "GET /repos/{owner}/{repo}/actions/permissions" - ], - getHostedRunnerForOrg: [ - "GET /orgs/{org}/actions/hosted-runners/{hosted_runner_id}" - ], - getHostedRunnersGithubOwnedImagesForOrg: [ - "GET /orgs/{org}/actions/hosted-runners/images/github-owned" - ], - getHostedRunnersLimitsForOrg: [ - "GET /orgs/{org}/actions/hosted-runners/limits" - ], - getHostedRunnersMachineSpecsForOrg: [ - "GET /orgs/{org}/actions/hosted-runners/machine-sizes" - ], - getHostedRunnersPartnerImagesForOrg: [ - "GET /orgs/{org}/actions/hosted-runners/images/partner" - ], - getHostedRunnersPlatformsForOrg: [ - "GET /orgs/{org}/actions/hosted-runners/platforms" - ], - getJobForWorkflowRun: ["GET /repos/{owner}/{repo}/actions/jobs/{job_id}"], - getOrgPublicKey: ["GET /orgs/{org}/actions/secrets/public-key"], - getOrgSecret: ["GET /orgs/{org}/actions/secrets/{secret_name}"], - getOrgVariable: ["GET /orgs/{org}/actions/variables/{name}"], - getPendingDeploymentsForRun: [ - "GET /repos/{owner}/{repo}/actions/runs/{run_id}/pending_deployments" - ], - getRepoPermissions: [ - "GET /repos/{owner}/{repo}/actions/permissions", - {}, - { renamed: ["actions", "getGithubActionsPermissionsRepository"] } - ], - getRepoPublicKey: ["GET /repos/{owner}/{repo}/actions/secrets/public-key"], - getRepoSecret: ["GET /repos/{owner}/{repo}/actions/secrets/{secret_name}"], - getRepoVariable: ["GET /repos/{owner}/{repo}/actions/variables/{name}"], - getReviewsForRun: [ - "GET /repos/{owner}/{repo}/actions/runs/{run_id}/approvals" - ], - getSelfHostedRunnerForOrg: ["GET /orgs/{org}/actions/runners/{runner_id}"], - getSelfHostedRunnerForRepo: [ - "GET /repos/{owner}/{repo}/actions/runners/{runner_id}" - ], - getWorkflow: ["GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}"], - getWorkflowAccessToRepository: [ - "GET /repos/{owner}/{repo}/actions/permissions/access" - ], - getWorkflowRun: ["GET /repos/{owner}/{repo}/actions/runs/{run_id}"], - getWorkflowRunAttempt: [ - "GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}" - ], - getWorkflowRunUsage: [ - "GET /repos/{owner}/{repo}/actions/runs/{run_id}/timing" - ], - getWorkflowUsage: [ - "GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/timing" - ], - listArtifactsForRepo: ["GET /repos/{owner}/{repo}/actions/artifacts"], - listCustomImageVersionsForOrg: [ - "GET /orgs/{org}/actions/hosted-runners/images/custom/{image_definition_id}/versions" - ], - listCustomImagesForOrg: [ - "GET /orgs/{org}/actions/hosted-runners/images/custom" - ], - listEnvironmentSecrets: [ - "GET /repos/{owner}/{repo}/environments/{environment_name}/secrets" - ], - listEnvironmentVariables: [ - "GET /repos/{owner}/{repo}/environments/{environment_name}/variables" - ], - listGithubHostedRunnersInGroupForOrg: [ - "GET /orgs/{org}/actions/runner-groups/{runner_group_id}/hosted-runners" - ], - listHostedRunnersForOrg: ["GET /orgs/{org}/actions/hosted-runners"], - listJobsForWorkflowRun: [ - "GET /repos/{owner}/{repo}/actions/runs/{run_id}/jobs" - ], - listJobsForWorkflowRunAttempt: [ - "GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}/jobs" - ], - listLabelsForSelfHostedRunnerForOrg: [ - "GET /orgs/{org}/actions/runners/{runner_id}/labels" - ], - listLabelsForSelfHostedRunnerForRepo: [ - "GET /repos/{owner}/{repo}/actions/runners/{runner_id}/labels" - ], - listOrgSecrets: ["GET /orgs/{org}/actions/secrets"], - listOrgVariables: ["GET /orgs/{org}/actions/variables"], - listRepoOrganizationSecrets: [ - "GET /repos/{owner}/{repo}/actions/organization-secrets" - ], - listRepoOrganizationVariables: [ - "GET /repos/{owner}/{repo}/actions/organization-variables" - ], - listRepoSecrets: ["GET /repos/{owner}/{repo}/actions/secrets"], - listRepoVariables: ["GET /repos/{owner}/{repo}/actions/variables"], - listRepoWorkflows: ["GET /repos/{owner}/{repo}/actions/workflows"], - listRunnerApplicationsForOrg: ["GET /orgs/{org}/actions/runners/downloads"], - listRunnerApplicationsForRepo: [ - "GET /repos/{owner}/{repo}/actions/runners/downloads" - ], - listSelectedReposForOrgSecret: [ - "GET /orgs/{org}/actions/secrets/{secret_name}/repositories" - ], - listSelectedReposForOrgVariable: [ - "GET /orgs/{org}/actions/variables/{name}/repositories" - ], - listSelectedRepositoriesEnabledGithubActionsOrganization: [ - "GET /orgs/{org}/actions/permissions/repositories" - ], - listSelfHostedRunnersForOrg: ["GET /orgs/{org}/actions/runners"], - listSelfHostedRunnersForRepo: ["GET /repos/{owner}/{repo}/actions/runners"], - listWorkflowRunArtifacts: [ - "GET /repos/{owner}/{repo}/actions/runs/{run_id}/artifacts" - ], - listWorkflowRuns: [ - "GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/runs" - ], - listWorkflowRunsForRepo: ["GET /repos/{owner}/{repo}/actions/runs"], - reRunJobForWorkflowRun: [ - "POST /repos/{owner}/{repo}/actions/jobs/{job_id}/rerun" - ], - reRunWorkflow: ["POST /repos/{owner}/{repo}/actions/runs/{run_id}/rerun"], - reRunWorkflowFailedJobs: [ - "POST /repos/{owner}/{repo}/actions/runs/{run_id}/rerun-failed-jobs" - ], - removeAllCustomLabelsFromSelfHostedRunnerForOrg: [ - "DELETE /orgs/{org}/actions/runners/{runner_id}/labels" - ], - removeAllCustomLabelsFromSelfHostedRunnerForRepo: [ - "DELETE /repos/{owner}/{repo}/actions/runners/{runner_id}/labels" - ], - removeCustomLabelFromSelfHostedRunnerForOrg: [ - "DELETE /orgs/{org}/actions/runners/{runner_id}/labels/{name}" - ], - removeCustomLabelFromSelfHostedRunnerForRepo: [ - "DELETE /repos/{owner}/{repo}/actions/runners/{runner_id}/labels/{name}" - ], - removeSelectedRepoFromOrgSecret: [ - "DELETE /orgs/{org}/actions/secrets/{secret_name}/repositories/{repository_id}" - ], - removeSelectedRepoFromOrgVariable: [ - "DELETE /orgs/{org}/actions/variables/{name}/repositories/{repository_id}" - ], - reviewCustomGatesForRun: [ - "POST /repos/{owner}/{repo}/actions/runs/{run_id}/deployment_protection_rule" - ], - reviewPendingDeploymentsForRun: [ - "POST /repos/{owner}/{repo}/actions/runs/{run_id}/pending_deployments" - ], - setAllowedActionsOrganization: [ - "PUT /orgs/{org}/actions/permissions/selected-actions" - ], - setAllowedActionsRepository: [ - "PUT /repos/{owner}/{repo}/actions/permissions/selected-actions" - ], - setCustomLabelsForSelfHostedRunnerForOrg: [ - "PUT /orgs/{org}/actions/runners/{runner_id}/labels" - ], - setCustomLabelsForSelfHostedRunnerForRepo: [ - "PUT /repos/{owner}/{repo}/actions/runners/{runner_id}/labels" - ], - setCustomOidcSubClaimForRepo: [ - "PUT /repos/{owner}/{repo}/actions/oidc/customization/sub" - ], - setGithubActionsDefaultWorkflowPermissionsOrganization: [ - "PUT /orgs/{org}/actions/permissions/workflow" - ], - setGithubActionsDefaultWorkflowPermissionsRepository: [ - "PUT /repos/{owner}/{repo}/actions/permissions/workflow" - ], - setGithubActionsPermissionsOrganization: [ - "PUT /orgs/{org}/actions/permissions" - ], - setGithubActionsPermissionsRepository: [ - "PUT /repos/{owner}/{repo}/actions/permissions" - ], - setSelectedReposForOrgSecret: [ - "PUT /orgs/{org}/actions/secrets/{secret_name}/repositories" - ], - setSelectedReposForOrgVariable: [ - "PUT /orgs/{org}/actions/variables/{name}/repositories" - ], - setSelectedRepositoriesEnabledGithubActionsOrganization: [ - "PUT /orgs/{org}/actions/permissions/repositories" - ], - setWorkflowAccessToRepository: [ - "PUT /repos/{owner}/{repo}/actions/permissions/access" - ], - updateEnvironmentVariable: [ - "PATCH /repos/{owner}/{repo}/environments/{environment_name}/variables/{name}" - ], - updateHostedRunnerForOrg: [ - "PATCH /orgs/{org}/actions/hosted-runners/{hosted_runner_id}" - ], - updateOrgVariable: ["PATCH /orgs/{org}/actions/variables/{name}"], - updateRepoVariable: [ - "PATCH /repos/{owner}/{repo}/actions/variables/{name}" - ] - }, - activity: { - checkRepoIsStarredByAuthenticatedUser: ["GET /user/starred/{owner}/{repo}"], - deleteRepoSubscription: ["DELETE /repos/{owner}/{repo}/subscription"], - deleteThreadSubscription: [ - "DELETE /notifications/threads/{thread_id}/subscription" - ], - getFeeds: ["GET /feeds"], - getRepoSubscription: ["GET /repos/{owner}/{repo}/subscription"], - getThread: ["GET /notifications/threads/{thread_id}"], - getThreadSubscriptionForAuthenticatedUser: [ - "GET /notifications/threads/{thread_id}/subscription" - ], - listEventsForAuthenticatedUser: ["GET /users/{username}/events"], - listNotificationsForAuthenticatedUser: ["GET /notifications"], - listOrgEventsForAuthenticatedUser: [ - "GET /users/{username}/events/orgs/{org}" - ], - listPublicEvents: ["GET /events"], - listPublicEventsForRepoNetwork: ["GET /networks/{owner}/{repo}/events"], - listPublicEventsForUser: ["GET /users/{username}/events/public"], - listPublicOrgEvents: ["GET /orgs/{org}/events"], - listReceivedEventsForUser: ["GET /users/{username}/received_events"], - listReceivedPublicEventsForUser: [ - "GET /users/{username}/received_events/public" - ], - listRepoEvents: ["GET /repos/{owner}/{repo}/events"], - listRepoNotificationsForAuthenticatedUser: [ - "GET /repos/{owner}/{repo}/notifications" - ], - listReposStarredByAuthenticatedUser: ["GET /user/starred"], - listReposStarredByUser: ["GET /users/{username}/starred"], - listReposWatchedByUser: ["GET /users/{username}/subscriptions"], - listStargazersForRepo: ["GET /repos/{owner}/{repo}/stargazers"], - listWatchedReposForAuthenticatedUser: ["GET /user/subscriptions"], - listWatchersForRepo: ["GET /repos/{owner}/{repo}/subscribers"], - markNotificationsAsRead: ["PUT /notifications"], - markRepoNotificationsAsRead: ["PUT /repos/{owner}/{repo}/notifications"], - markThreadAsDone: ["DELETE /notifications/threads/{thread_id}"], - markThreadAsRead: ["PATCH /notifications/threads/{thread_id}"], - setRepoSubscription: ["PUT /repos/{owner}/{repo}/subscription"], - setThreadSubscription: [ - "PUT /notifications/threads/{thread_id}/subscription" - ], - starRepoForAuthenticatedUser: ["PUT /user/starred/{owner}/{repo}"], - unstarRepoForAuthenticatedUser: ["DELETE /user/starred/{owner}/{repo}"] - }, - apps: { - addRepoToInstallation: [ - "PUT /user/installations/{installation_id}/repositories/{repository_id}", - {}, - { renamed: ["apps", "addRepoToInstallationForAuthenticatedUser"] } - ], - addRepoToInstallationForAuthenticatedUser: [ - "PUT /user/installations/{installation_id}/repositories/{repository_id}" - ], - checkToken: ["POST /applications/{client_id}/token"], - createFromManifest: ["POST /app-manifests/{code}/conversions"], - createInstallationAccessToken: [ - "POST /app/installations/{installation_id}/access_tokens" - ], - deleteAuthorization: ["DELETE /applications/{client_id}/grant"], - deleteInstallation: ["DELETE /app/installations/{installation_id}"], - deleteToken: ["DELETE /applications/{client_id}/token"], - getAuthenticated: ["GET /app"], - getBySlug: ["GET /apps/{app_slug}"], - getInstallation: ["GET /app/installations/{installation_id}"], - getOrgInstallation: ["GET /orgs/{org}/installation"], - getRepoInstallation: ["GET /repos/{owner}/{repo}/installation"], - getSubscriptionPlanForAccount: [ - "GET /marketplace_listing/accounts/{account_id}" - ], - getSubscriptionPlanForAccountStubbed: [ - "GET /marketplace_listing/stubbed/accounts/{account_id}" - ], - getUserInstallation: ["GET /users/{username}/installation"], - getWebhookConfigForApp: ["GET /app/hook/config"], - getWebhookDelivery: ["GET /app/hook/deliveries/{delivery_id}"], - listAccountsForPlan: ["GET /marketplace_listing/plans/{plan_id}/accounts"], - listAccountsForPlanStubbed: [ - "GET /marketplace_listing/stubbed/plans/{plan_id}/accounts" - ], - listInstallationReposForAuthenticatedUser: [ - "GET /user/installations/{installation_id}/repositories" - ], - listInstallationRequestsForAuthenticatedApp: [ - "GET /app/installation-requests" - ], - listInstallations: ["GET /app/installations"], - listInstallationsForAuthenticatedUser: ["GET /user/installations"], - listPlans: ["GET /marketplace_listing/plans"], - listPlansStubbed: ["GET /marketplace_listing/stubbed/plans"], - listReposAccessibleToInstallation: ["GET /installation/repositories"], - listSubscriptionsForAuthenticatedUser: ["GET /user/marketplace_purchases"], - listSubscriptionsForAuthenticatedUserStubbed: [ - "GET /user/marketplace_purchases/stubbed" - ], - listWebhookDeliveries: ["GET /app/hook/deliveries"], - redeliverWebhookDelivery: [ - "POST /app/hook/deliveries/{delivery_id}/attempts" - ], - removeRepoFromInstallation: [ - "DELETE /user/installations/{installation_id}/repositories/{repository_id}", - {}, - { renamed: ["apps", "removeRepoFromInstallationForAuthenticatedUser"] } - ], - removeRepoFromInstallationForAuthenticatedUser: [ - "DELETE /user/installations/{installation_id}/repositories/{repository_id}" - ], - resetToken: ["PATCH /applications/{client_id}/token"], - revokeInstallationAccessToken: ["DELETE /installation/token"], - scopeToken: ["POST /applications/{client_id}/token/scoped"], - suspendInstallation: ["PUT /app/installations/{installation_id}/suspended"], - unsuspendInstallation: [ - "DELETE /app/installations/{installation_id}/suspended" - ], - updateWebhookConfigForApp: ["PATCH /app/hook/config"] - }, - billing: { - getGithubActionsBillingOrg: ["GET /orgs/{org}/settings/billing/actions"], - getGithubActionsBillingUser: [ - "GET /users/{username}/settings/billing/actions" - ], - getGithubBillingPremiumRequestUsageReportOrg: [ - "GET /organizations/{org}/settings/billing/premium_request/usage" - ], - getGithubBillingPremiumRequestUsageReportUser: [ - "GET /users/{username}/settings/billing/premium_request/usage" - ], - getGithubBillingUsageReportOrg: [ - "GET /organizations/{org}/settings/billing/usage" - ], - getGithubBillingUsageReportUser: [ - "GET /users/{username}/settings/billing/usage" - ], - getGithubPackagesBillingOrg: ["GET /orgs/{org}/settings/billing/packages"], - getGithubPackagesBillingUser: [ - "GET /users/{username}/settings/billing/packages" - ], - getSharedStorageBillingOrg: [ - "GET /orgs/{org}/settings/billing/shared-storage" - ], - getSharedStorageBillingUser: [ - "GET /users/{username}/settings/billing/shared-storage" - ] - }, - campaigns: { - createCampaign: ["POST /orgs/{org}/campaigns"], - deleteCampaign: ["DELETE /orgs/{org}/campaigns/{campaign_number}"], - getCampaignSummary: ["GET /orgs/{org}/campaigns/{campaign_number}"], - listOrgCampaigns: ["GET /orgs/{org}/campaigns"], - updateCampaign: ["PATCH /orgs/{org}/campaigns/{campaign_number}"] - }, - checks: { - create: ["POST /repos/{owner}/{repo}/check-runs"], - createSuite: ["POST /repos/{owner}/{repo}/check-suites"], - get: ["GET /repos/{owner}/{repo}/check-runs/{check_run_id}"], - getSuite: ["GET /repos/{owner}/{repo}/check-suites/{check_suite_id}"], - listAnnotations: [ - "GET /repos/{owner}/{repo}/check-runs/{check_run_id}/annotations" - ], - listForRef: ["GET /repos/{owner}/{repo}/commits/{ref}/check-runs"], - listForSuite: [ - "GET /repos/{owner}/{repo}/check-suites/{check_suite_id}/check-runs" - ], - listSuitesForRef: ["GET /repos/{owner}/{repo}/commits/{ref}/check-suites"], - rerequestRun: [ - "POST /repos/{owner}/{repo}/check-runs/{check_run_id}/rerequest" - ], - rerequestSuite: [ - "POST /repos/{owner}/{repo}/check-suites/{check_suite_id}/rerequest" - ], - setSuitesPreferences: [ - "PATCH /repos/{owner}/{repo}/check-suites/preferences" - ], - update: ["PATCH /repos/{owner}/{repo}/check-runs/{check_run_id}"] - }, - codeScanning: { - commitAutofix: [ - "POST /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}/autofix/commits" - ], - createAutofix: [ - "POST /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}/autofix" - ], - createVariantAnalysis: [ - "POST /repos/{owner}/{repo}/code-scanning/codeql/variant-analyses" - ], - deleteAnalysis: [ - "DELETE /repos/{owner}/{repo}/code-scanning/analyses/{analysis_id}{?confirm_delete}" - ], - deleteCodeqlDatabase: [ - "DELETE /repos/{owner}/{repo}/code-scanning/codeql/databases/{language}" - ], - getAlert: [ - "GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}", - {}, - { renamedParameters: { alert_id: "alert_number" } } - ], - getAnalysis: [ - "GET /repos/{owner}/{repo}/code-scanning/analyses/{analysis_id}" - ], - getAutofix: [ - "GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}/autofix" - ], - getCodeqlDatabase: [ - "GET /repos/{owner}/{repo}/code-scanning/codeql/databases/{language}" - ], - getDefaultSetup: ["GET /repos/{owner}/{repo}/code-scanning/default-setup"], - getSarif: ["GET /repos/{owner}/{repo}/code-scanning/sarifs/{sarif_id}"], - getVariantAnalysis: [ - "GET /repos/{owner}/{repo}/code-scanning/codeql/variant-analyses/{codeql_variant_analysis_id}" - ], - getVariantAnalysisRepoTask: [ - "GET /repos/{owner}/{repo}/code-scanning/codeql/variant-analyses/{codeql_variant_analysis_id}/repos/{repo_owner}/{repo_name}" - ], - listAlertInstances: [ - "GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}/instances" - ], - listAlertsForOrg: ["GET /orgs/{org}/code-scanning/alerts"], - listAlertsForRepo: ["GET /repos/{owner}/{repo}/code-scanning/alerts"], - listAlertsInstances: [ - "GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}/instances", - {}, - { renamed: ["codeScanning", "listAlertInstances"] } - ], - listCodeqlDatabases: [ - "GET /repos/{owner}/{repo}/code-scanning/codeql/databases" - ], - listRecentAnalyses: ["GET /repos/{owner}/{repo}/code-scanning/analyses"], - updateAlert: [ - "PATCH /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}" - ], - updateDefaultSetup: [ - "PATCH /repos/{owner}/{repo}/code-scanning/default-setup" - ], - uploadSarif: ["POST /repos/{owner}/{repo}/code-scanning/sarifs"] - }, - codeSecurity: { - attachConfiguration: [ - "POST /orgs/{org}/code-security/configurations/{configuration_id}/attach" - ], - attachEnterpriseConfiguration: [ - "POST /enterprises/{enterprise}/code-security/configurations/{configuration_id}/attach" - ], - createConfiguration: ["POST /orgs/{org}/code-security/configurations"], - createConfigurationForEnterprise: [ - "POST /enterprises/{enterprise}/code-security/configurations" - ], - deleteConfiguration: [ - "DELETE /orgs/{org}/code-security/configurations/{configuration_id}" - ], - deleteConfigurationForEnterprise: [ - "DELETE /enterprises/{enterprise}/code-security/configurations/{configuration_id}" - ], - detachConfiguration: [ - "DELETE /orgs/{org}/code-security/configurations/detach" - ], - getConfiguration: [ - "GET /orgs/{org}/code-security/configurations/{configuration_id}" - ], - getConfigurationForRepository: [ - "GET /repos/{owner}/{repo}/code-security-configuration" - ], - getConfigurationsForEnterprise: [ - "GET /enterprises/{enterprise}/code-security/configurations" - ], - getConfigurationsForOrg: ["GET /orgs/{org}/code-security/configurations"], - getDefaultConfigurations: [ - "GET /orgs/{org}/code-security/configurations/defaults" - ], - getDefaultConfigurationsForEnterprise: [ - "GET /enterprises/{enterprise}/code-security/configurations/defaults" - ], - getRepositoriesForConfiguration: [ - "GET /orgs/{org}/code-security/configurations/{configuration_id}/repositories" - ], - getRepositoriesForEnterpriseConfiguration: [ - "GET /enterprises/{enterprise}/code-security/configurations/{configuration_id}/repositories" - ], - getSingleConfigurationForEnterprise: [ - "GET /enterprises/{enterprise}/code-security/configurations/{configuration_id}" - ], - setConfigurationAsDefault: [ - "PUT /orgs/{org}/code-security/configurations/{configuration_id}/defaults" - ], - setConfigurationAsDefaultForEnterprise: [ - "PUT /enterprises/{enterprise}/code-security/configurations/{configuration_id}/defaults" - ], - updateConfiguration: [ - "PATCH /orgs/{org}/code-security/configurations/{configuration_id}" - ], - updateEnterpriseConfiguration: [ - "PATCH /enterprises/{enterprise}/code-security/configurations/{configuration_id}" - ] - }, - codesOfConduct: { - getAllCodesOfConduct: ["GET /codes_of_conduct"], - getConductCode: ["GET /codes_of_conduct/{key}"] - }, - codespaces: { - addRepositoryForSecretForAuthenticatedUser: [ - "PUT /user/codespaces/secrets/{secret_name}/repositories/{repository_id}" - ], - addSelectedRepoToOrgSecret: [ - "PUT /orgs/{org}/codespaces/secrets/{secret_name}/repositories/{repository_id}" - ], - checkPermissionsForDevcontainer: [ - "GET /repos/{owner}/{repo}/codespaces/permissions_check" - ], - codespaceMachinesForAuthenticatedUser: [ - "GET /user/codespaces/{codespace_name}/machines" - ], - createForAuthenticatedUser: ["POST /user/codespaces"], - createOrUpdateOrgSecret: [ - "PUT /orgs/{org}/codespaces/secrets/{secret_name}" - ], - createOrUpdateRepoSecret: [ - "PUT /repos/{owner}/{repo}/codespaces/secrets/{secret_name}" - ], - createOrUpdateSecretForAuthenticatedUser: [ - "PUT /user/codespaces/secrets/{secret_name}" - ], - createWithPrForAuthenticatedUser: [ - "POST /repos/{owner}/{repo}/pulls/{pull_number}/codespaces" - ], - createWithRepoForAuthenticatedUser: [ - "POST /repos/{owner}/{repo}/codespaces" - ], - deleteForAuthenticatedUser: ["DELETE /user/codespaces/{codespace_name}"], - deleteFromOrganization: [ - "DELETE /orgs/{org}/members/{username}/codespaces/{codespace_name}" - ], - deleteOrgSecret: ["DELETE /orgs/{org}/codespaces/secrets/{secret_name}"], - deleteRepoSecret: [ - "DELETE /repos/{owner}/{repo}/codespaces/secrets/{secret_name}" - ], - deleteSecretForAuthenticatedUser: [ - "DELETE /user/codespaces/secrets/{secret_name}" - ], - exportForAuthenticatedUser: [ - "POST /user/codespaces/{codespace_name}/exports" - ], - getCodespacesForUserInOrg: [ - "GET /orgs/{org}/members/{username}/codespaces" - ], - getExportDetailsForAuthenticatedUser: [ - "GET /user/codespaces/{codespace_name}/exports/{export_id}" - ], - getForAuthenticatedUser: ["GET /user/codespaces/{codespace_name}"], - getOrgPublicKey: ["GET /orgs/{org}/codespaces/secrets/public-key"], - getOrgSecret: ["GET /orgs/{org}/codespaces/secrets/{secret_name}"], - getPublicKeyForAuthenticatedUser: [ - "GET /user/codespaces/secrets/public-key" - ], - getRepoPublicKey: [ - "GET /repos/{owner}/{repo}/codespaces/secrets/public-key" - ], - getRepoSecret: [ - "GET /repos/{owner}/{repo}/codespaces/secrets/{secret_name}" - ], - getSecretForAuthenticatedUser: [ - "GET /user/codespaces/secrets/{secret_name}" - ], - listDevcontainersInRepositoryForAuthenticatedUser: [ - "GET /repos/{owner}/{repo}/codespaces/devcontainers" - ], - listForAuthenticatedUser: ["GET /user/codespaces"], - listInOrganization: [ - "GET /orgs/{org}/codespaces", - {}, - { renamedParameters: { org_id: "org" } } - ], - listInRepositoryForAuthenticatedUser: [ - "GET /repos/{owner}/{repo}/codespaces" - ], - listOrgSecrets: ["GET /orgs/{org}/codespaces/secrets"], - listRepoSecrets: ["GET /repos/{owner}/{repo}/codespaces/secrets"], - listRepositoriesForSecretForAuthenticatedUser: [ - "GET /user/codespaces/secrets/{secret_name}/repositories" - ], - listSecretsForAuthenticatedUser: ["GET /user/codespaces/secrets"], - listSelectedReposForOrgSecret: [ - "GET /orgs/{org}/codespaces/secrets/{secret_name}/repositories" - ], - preFlightWithRepoForAuthenticatedUser: [ - "GET /repos/{owner}/{repo}/codespaces/new" - ], - publishForAuthenticatedUser: [ - "POST /user/codespaces/{codespace_name}/publish" - ], - removeRepositoryForSecretForAuthenticatedUser: [ - "DELETE /user/codespaces/secrets/{secret_name}/repositories/{repository_id}" - ], - removeSelectedRepoFromOrgSecret: [ - "DELETE /orgs/{org}/codespaces/secrets/{secret_name}/repositories/{repository_id}" - ], - repoMachinesForAuthenticatedUser: [ - "GET /repos/{owner}/{repo}/codespaces/machines" - ], - setRepositoriesForSecretForAuthenticatedUser: [ - "PUT /user/codespaces/secrets/{secret_name}/repositories" - ], - setSelectedReposForOrgSecret: [ - "PUT /orgs/{org}/codespaces/secrets/{secret_name}/repositories" - ], - startForAuthenticatedUser: ["POST /user/codespaces/{codespace_name}/start"], - stopForAuthenticatedUser: ["POST /user/codespaces/{codespace_name}/stop"], - stopInOrganization: [ - "POST /orgs/{org}/members/{username}/codespaces/{codespace_name}/stop" - ], - updateForAuthenticatedUser: ["PATCH /user/codespaces/{codespace_name}"] - }, - copilot: { - addCopilotSeatsForTeams: [ - "POST /orgs/{org}/copilot/billing/selected_teams" - ], - addCopilotSeatsForUsers: [ - "POST /orgs/{org}/copilot/billing/selected_users" - ], - cancelCopilotSeatAssignmentForTeams: [ - "DELETE /orgs/{org}/copilot/billing/selected_teams" - ], - cancelCopilotSeatAssignmentForUsers: [ - "DELETE /orgs/{org}/copilot/billing/selected_users" - ], - copilotMetricsForOrganization: ["GET /orgs/{org}/copilot/metrics"], - copilotMetricsForTeam: ["GET /orgs/{org}/team/{team_slug}/copilot/metrics"], - getCopilotOrganizationDetails: ["GET /orgs/{org}/copilot/billing"], - getCopilotSeatDetailsForUser: [ - "GET /orgs/{org}/members/{username}/copilot" - ], - listCopilotSeats: ["GET /orgs/{org}/copilot/billing/seats"] - }, - credentials: { revoke: ["POST /credentials/revoke"] }, - dependabot: { - addSelectedRepoToOrgSecret: [ - "PUT /orgs/{org}/dependabot/secrets/{secret_name}/repositories/{repository_id}" - ], - createOrUpdateOrgSecret: [ - "PUT /orgs/{org}/dependabot/secrets/{secret_name}" - ], - createOrUpdateRepoSecret: [ - "PUT /repos/{owner}/{repo}/dependabot/secrets/{secret_name}" - ], - deleteOrgSecret: ["DELETE /orgs/{org}/dependabot/secrets/{secret_name}"], - deleteRepoSecret: [ - "DELETE /repos/{owner}/{repo}/dependabot/secrets/{secret_name}" - ], - getAlert: ["GET /repos/{owner}/{repo}/dependabot/alerts/{alert_number}"], - getOrgPublicKey: ["GET /orgs/{org}/dependabot/secrets/public-key"], - getOrgSecret: ["GET /orgs/{org}/dependabot/secrets/{secret_name}"], - getRepoPublicKey: [ - "GET /repos/{owner}/{repo}/dependabot/secrets/public-key" - ], - getRepoSecret: [ - "GET /repos/{owner}/{repo}/dependabot/secrets/{secret_name}" - ], - listAlertsForEnterprise: [ - "GET /enterprises/{enterprise}/dependabot/alerts" - ], - listAlertsForOrg: ["GET /orgs/{org}/dependabot/alerts"], - listAlertsForRepo: ["GET /repos/{owner}/{repo}/dependabot/alerts"], - listOrgSecrets: ["GET /orgs/{org}/dependabot/secrets"], - listRepoSecrets: ["GET /repos/{owner}/{repo}/dependabot/secrets"], - listSelectedReposForOrgSecret: [ - "GET /orgs/{org}/dependabot/secrets/{secret_name}/repositories" - ], - removeSelectedRepoFromOrgSecret: [ - "DELETE /orgs/{org}/dependabot/secrets/{secret_name}/repositories/{repository_id}" - ], - repositoryAccessForOrg: [ - "GET /organizations/{org}/dependabot/repository-access" - ], - setRepositoryAccessDefaultLevel: [ - "PUT /organizations/{org}/dependabot/repository-access/default-level" - ], - setSelectedReposForOrgSecret: [ - "PUT /orgs/{org}/dependabot/secrets/{secret_name}/repositories" - ], - updateAlert: [ - "PATCH /repos/{owner}/{repo}/dependabot/alerts/{alert_number}" - ], - updateRepositoryAccessForOrg: [ - "PATCH /organizations/{org}/dependabot/repository-access" - ] - }, - dependencyGraph: { - createRepositorySnapshot: [ - "POST /repos/{owner}/{repo}/dependency-graph/snapshots" - ], - diffRange: [ - "GET /repos/{owner}/{repo}/dependency-graph/compare/{basehead}" - ], - exportSbom: ["GET /repos/{owner}/{repo}/dependency-graph/sbom"] - }, - emojis: { get: ["GET /emojis"] }, - enterpriseTeamMemberships: { - add: [ - "PUT /enterprises/{enterprise}/teams/{enterprise-team}/memberships/{username}" - ], - bulkAdd: [ - "POST /enterprises/{enterprise}/teams/{enterprise-team}/memberships/add" - ], - bulkRemove: [ - "POST /enterprises/{enterprise}/teams/{enterprise-team}/memberships/remove" - ], - get: [ - "GET /enterprises/{enterprise}/teams/{enterprise-team}/memberships/{username}" - ], - list: ["GET /enterprises/{enterprise}/teams/{enterprise-team}/memberships"], - remove: [ - "DELETE /enterprises/{enterprise}/teams/{enterprise-team}/memberships/{username}" - ] - }, - enterpriseTeamOrganizations: { - add: [ - "PUT /enterprises/{enterprise}/teams/{enterprise-team}/organizations/{org}" - ], - bulkAdd: [ - "POST /enterprises/{enterprise}/teams/{enterprise-team}/organizations/add" - ], - bulkRemove: [ - "POST /enterprises/{enterprise}/teams/{enterprise-team}/organizations/remove" - ], - delete: [ - "DELETE /enterprises/{enterprise}/teams/{enterprise-team}/organizations/{org}" - ], - getAssignment: [ - "GET /enterprises/{enterprise}/teams/{enterprise-team}/organizations/{org}" - ], - getAssignments: [ - "GET /enterprises/{enterprise}/teams/{enterprise-team}/organizations" - ] - }, - enterpriseTeams: { - create: ["POST /enterprises/{enterprise}/teams"], - delete: ["DELETE /enterprises/{enterprise}/teams/{team_slug}"], - get: ["GET /enterprises/{enterprise}/teams/{team_slug}"], - list: ["GET /enterprises/{enterprise}/teams"], - update: ["PATCH /enterprises/{enterprise}/teams/{team_slug}"] - }, - gists: { - checkIsStarred: ["GET /gists/{gist_id}/star"], - create: ["POST /gists"], - createComment: ["POST /gists/{gist_id}/comments"], - delete: ["DELETE /gists/{gist_id}"], - deleteComment: ["DELETE /gists/{gist_id}/comments/{comment_id}"], - fork: ["POST /gists/{gist_id}/forks"], - get: ["GET /gists/{gist_id}"], - getComment: ["GET /gists/{gist_id}/comments/{comment_id}"], - getRevision: ["GET /gists/{gist_id}/{sha}"], - list: ["GET /gists"], - listComments: ["GET /gists/{gist_id}/comments"], - listCommits: ["GET /gists/{gist_id}/commits"], - listForUser: ["GET /users/{username}/gists"], - listForks: ["GET /gists/{gist_id}/forks"], - listPublic: ["GET /gists/public"], - listStarred: ["GET /gists/starred"], - star: ["PUT /gists/{gist_id}/star"], - unstar: ["DELETE /gists/{gist_id}/star"], - update: ["PATCH /gists/{gist_id}"], - updateComment: ["PATCH /gists/{gist_id}/comments/{comment_id}"] - }, - git: { - createBlob: ["POST /repos/{owner}/{repo}/git/blobs"], - createCommit: ["POST /repos/{owner}/{repo}/git/commits"], - createRef: ["POST /repos/{owner}/{repo}/git/refs"], - createTag: ["POST /repos/{owner}/{repo}/git/tags"], - createTree: ["POST /repos/{owner}/{repo}/git/trees"], - deleteRef: ["DELETE /repos/{owner}/{repo}/git/refs/{ref}"], - getBlob: ["GET /repos/{owner}/{repo}/git/blobs/{file_sha}"], - getCommit: ["GET /repos/{owner}/{repo}/git/commits/{commit_sha}"], - getRef: ["GET /repos/{owner}/{repo}/git/ref/{ref}"], - getTag: ["GET /repos/{owner}/{repo}/git/tags/{tag_sha}"], - getTree: ["GET /repos/{owner}/{repo}/git/trees/{tree_sha}"], - listMatchingRefs: ["GET /repos/{owner}/{repo}/git/matching-refs/{ref}"], - updateRef: ["PATCH /repos/{owner}/{repo}/git/refs/{ref}"] - }, - gitignore: { - getAllTemplates: ["GET /gitignore/templates"], - getTemplate: ["GET /gitignore/templates/{name}"] - }, - hostedCompute: { - createNetworkConfigurationForOrg: [ - "POST /orgs/{org}/settings/network-configurations" - ], - deleteNetworkConfigurationFromOrg: [ - "DELETE /orgs/{org}/settings/network-configurations/{network_configuration_id}" - ], - getNetworkConfigurationForOrg: [ - "GET /orgs/{org}/settings/network-configurations/{network_configuration_id}" - ], - getNetworkSettingsForOrg: [ - "GET /orgs/{org}/settings/network-settings/{network_settings_id}" - ], - listNetworkConfigurationsForOrg: [ - "GET /orgs/{org}/settings/network-configurations" - ], - updateNetworkConfigurationForOrg: [ - "PATCH /orgs/{org}/settings/network-configurations/{network_configuration_id}" - ] - }, - interactions: { - getRestrictionsForAuthenticatedUser: ["GET /user/interaction-limits"], - getRestrictionsForOrg: ["GET /orgs/{org}/interaction-limits"], - getRestrictionsForRepo: ["GET /repos/{owner}/{repo}/interaction-limits"], - getRestrictionsForYourPublicRepos: [ - "GET /user/interaction-limits", - {}, - { renamed: ["interactions", "getRestrictionsForAuthenticatedUser"] } - ], - removeRestrictionsForAuthenticatedUser: ["DELETE /user/interaction-limits"], - removeRestrictionsForOrg: ["DELETE /orgs/{org}/interaction-limits"], - removeRestrictionsForRepo: [ - "DELETE /repos/{owner}/{repo}/interaction-limits" - ], - removeRestrictionsForYourPublicRepos: [ - "DELETE /user/interaction-limits", - {}, - { renamed: ["interactions", "removeRestrictionsForAuthenticatedUser"] } - ], - setRestrictionsForAuthenticatedUser: ["PUT /user/interaction-limits"], - setRestrictionsForOrg: ["PUT /orgs/{org}/interaction-limits"], - setRestrictionsForRepo: ["PUT /repos/{owner}/{repo}/interaction-limits"], - setRestrictionsForYourPublicRepos: [ - "PUT /user/interaction-limits", - {}, - { renamed: ["interactions", "setRestrictionsForAuthenticatedUser"] } - ] - }, - issues: { - addAssignees: [ - "POST /repos/{owner}/{repo}/issues/{issue_number}/assignees" - ], - addBlockedByDependency: [ - "POST /repos/{owner}/{repo}/issues/{issue_number}/dependencies/blocked_by" - ], - addLabels: ["POST /repos/{owner}/{repo}/issues/{issue_number}/labels"], - addSubIssue: [ - "POST /repos/{owner}/{repo}/issues/{issue_number}/sub_issues" - ], - checkUserCanBeAssigned: ["GET /repos/{owner}/{repo}/assignees/{assignee}"], - checkUserCanBeAssignedToIssue: [ - "GET /repos/{owner}/{repo}/issues/{issue_number}/assignees/{assignee}" - ], - create: ["POST /repos/{owner}/{repo}/issues"], - createComment: [ - "POST /repos/{owner}/{repo}/issues/{issue_number}/comments" - ], - createLabel: ["POST /repos/{owner}/{repo}/labels"], - createMilestone: ["POST /repos/{owner}/{repo}/milestones"], - deleteComment: [ - "DELETE /repos/{owner}/{repo}/issues/comments/{comment_id}" - ], - deleteLabel: ["DELETE /repos/{owner}/{repo}/labels/{name}"], - deleteMilestone: [ - "DELETE /repos/{owner}/{repo}/milestones/{milestone_number}" - ], - get: ["GET /repos/{owner}/{repo}/issues/{issue_number}"], - getComment: ["GET /repos/{owner}/{repo}/issues/comments/{comment_id}"], - getEvent: ["GET /repos/{owner}/{repo}/issues/events/{event_id}"], - getLabel: ["GET /repos/{owner}/{repo}/labels/{name}"], - getMilestone: ["GET /repos/{owner}/{repo}/milestones/{milestone_number}"], - getParent: ["GET /repos/{owner}/{repo}/issues/{issue_number}/parent"], - list: ["GET /issues"], - listAssignees: ["GET /repos/{owner}/{repo}/assignees"], - listComments: ["GET /repos/{owner}/{repo}/issues/{issue_number}/comments"], - listCommentsForRepo: ["GET /repos/{owner}/{repo}/issues/comments"], - listDependenciesBlockedBy: [ - "GET /repos/{owner}/{repo}/issues/{issue_number}/dependencies/blocked_by" - ], - listDependenciesBlocking: [ - "GET /repos/{owner}/{repo}/issues/{issue_number}/dependencies/blocking" - ], - listEvents: ["GET /repos/{owner}/{repo}/issues/{issue_number}/events"], - listEventsForRepo: ["GET /repos/{owner}/{repo}/issues/events"], - listEventsForTimeline: [ - "GET /repos/{owner}/{repo}/issues/{issue_number}/timeline" - ], - listForAuthenticatedUser: ["GET /user/issues"], - listForOrg: ["GET /orgs/{org}/issues"], - listForRepo: ["GET /repos/{owner}/{repo}/issues"], - listLabelsForMilestone: [ - "GET /repos/{owner}/{repo}/milestones/{milestone_number}/labels" - ], - listLabelsForRepo: ["GET /repos/{owner}/{repo}/labels"], - listLabelsOnIssue: [ - "GET /repos/{owner}/{repo}/issues/{issue_number}/labels" - ], - listMilestones: ["GET /repos/{owner}/{repo}/milestones"], - listSubIssues: [ - "GET /repos/{owner}/{repo}/issues/{issue_number}/sub_issues" - ], - lock: ["PUT /repos/{owner}/{repo}/issues/{issue_number}/lock"], - removeAllLabels: [ - "DELETE /repos/{owner}/{repo}/issues/{issue_number}/labels" - ], - removeAssignees: [ - "DELETE /repos/{owner}/{repo}/issues/{issue_number}/assignees" - ], - removeDependencyBlockedBy: [ - "DELETE /repos/{owner}/{repo}/issues/{issue_number}/dependencies/blocked_by/{issue_id}" - ], - removeLabel: [ - "DELETE /repos/{owner}/{repo}/issues/{issue_number}/labels/{name}" - ], - removeSubIssue: [ - "DELETE /repos/{owner}/{repo}/issues/{issue_number}/sub_issue" - ], - reprioritizeSubIssue: [ - "PATCH /repos/{owner}/{repo}/issues/{issue_number}/sub_issues/priority" - ], - setLabels: ["PUT /repos/{owner}/{repo}/issues/{issue_number}/labels"], - unlock: ["DELETE /repos/{owner}/{repo}/issues/{issue_number}/lock"], - update: ["PATCH /repos/{owner}/{repo}/issues/{issue_number}"], - updateComment: ["PATCH /repos/{owner}/{repo}/issues/comments/{comment_id}"], - updateLabel: ["PATCH /repos/{owner}/{repo}/labels/{name}"], - updateMilestone: [ - "PATCH /repos/{owner}/{repo}/milestones/{milestone_number}" - ] - }, - licenses: { - get: ["GET /licenses/{license}"], - getAllCommonlyUsed: ["GET /licenses"], - getForRepo: ["GET /repos/{owner}/{repo}/license"] - }, - markdown: { - render: ["POST /markdown"], - renderRaw: [ - "POST /markdown/raw", - { headers: { "content-type": "text/plain; charset=utf-8" } } - ] - }, - meta: { - get: ["GET /meta"], - getAllVersions: ["GET /versions"], - getOctocat: ["GET /octocat"], - getZen: ["GET /zen"], - root: ["GET /"] - }, - migrations: { - deleteArchiveForAuthenticatedUser: [ - "DELETE /user/migrations/{migration_id}/archive" - ], - deleteArchiveForOrg: [ - "DELETE /orgs/{org}/migrations/{migration_id}/archive" - ], - downloadArchiveForOrg: [ - "GET /orgs/{org}/migrations/{migration_id}/archive" - ], - getArchiveForAuthenticatedUser: [ - "GET /user/migrations/{migration_id}/archive" - ], - getStatusForAuthenticatedUser: ["GET /user/migrations/{migration_id}"], - getStatusForOrg: ["GET /orgs/{org}/migrations/{migration_id}"], - listForAuthenticatedUser: ["GET /user/migrations"], - listForOrg: ["GET /orgs/{org}/migrations"], - listReposForAuthenticatedUser: [ - "GET /user/migrations/{migration_id}/repositories" - ], - listReposForOrg: ["GET /orgs/{org}/migrations/{migration_id}/repositories"], - listReposForUser: [ - "GET /user/migrations/{migration_id}/repositories", - {}, - { renamed: ["migrations", "listReposForAuthenticatedUser"] } - ], - startForAuthenticatedUser: ["POST /user/migrations"], - startForOrg: ["POST /orgs/{org}/migrations"], - unlockRepoForAuthenticatedUser: [ - "DELETE /user/migrations/{migration_id}/repos/{repo_name}/lock" - ], - unlockRepoForOrg: [ - "DELETE /orgs/{org}/migrations/{migration_id}/repos/{repo_name}/lock" - ] - }, - oidc: { - getOidcCustomSubTemplateForOrg: [ - "GET /orgs/{org}/actions/oidc/customization/sub" - ], - updateOidcCustomSubTemplateForOrg: [ - "PUT /orgs/{org}/actions/oidc/customization/sub" - ] - }, - orgs: { - addSecurityManagerTeam: [ - "PUT /orgs/{org}/security-managers/teams/{team_slug}", - {}, - { - deprecated: "octokit.rest.orgs.addSecurityManagerTeam() is deprecated, see https://docs.github.com/rest/orgs/security-managers#add-a-security-manager-team" - } - ], - assignTeamToOrgRole: [ - "PUT /orgs/{org}/organization-roles/teams/{team_slug}/{role_id}" - ], - assignUserToOrgRole: [ - "PUT /orgs/{org}/organization-roles/users/{username}/{role_id}" - ], - blockUser: ["PUT /orgs/{org}/blocks/{username}"], - cancelInvitation: ["DELETE /orgs/{org}/invitations/{invitation_id}"], - checkBlockedUser: ["GET /orgs/{org}/blocks/{username}"], - checkMembershipForUser: ["GET /orgs/{org}/members/{username}"], - checkPublicMembershipForUser: ["GET /orgs/{org}/public_members/{username}"], - convertMemberToOutsideCollaborator: [ - "PUT /orgs/{org}/outside_collaborators/{username}" - ], - createArtifactStorageRecord: [ - "POST /orgs/{org}/artifacts/metadata/storage-record" - ], - createInvitation: ["POST /orgs/{org}/invitations"], - createIssueType: ["POST /orgs/{org}/issue-types"], - createWebhook: ["POST /orgs/{org}/hooks"], - customPropertiesForOrgsCreateOrUpdateOrganizationValues: [ - "PATCH /organizations/{org}/org-properties/values" - ], - customPropertiesForOrgsGetOrganizationValues: [ - "GET /organizations/{org}/org-properties/values" - ], - customPropertiesForReposCreateOrUpdateOrganizationDefinition: [ - "PUT /orgs/{org}/properties/schema/{custom_property_name}" - ], - customPropertiesForReposCreateOrUpdateOrganizationDefinitions: [ - "PATCH /orgs/{org}/properties/schema" - ], - customPropertiesForReposCreateOrUpdateOrganizationValues: [ - "PATCH /orgs/{org}/properties/values" - ], - customPropertiesForReposDeleteOrganizationDefinition: [ - "DELETE /orgs/{org}/properties/schema/{custom_property_name}" - ], - customPropertiesForReposGetOrganizationDefinition: [ - "GET /orgs/{org}/properties/schema/{custom_property_name}" - ], - customPropertiesForReposGetOrganizationDefinitions: [ - "GET /orgs/{org}/properties/schema" - ], - customPropertiesForReposGetOrganizationValues: [ - "GET /orgs/{org}/properties/values" - ], - delete: ["DELETE /orgs/{org}"], - deleteAttestationsBulk: ["POST /orgs/{org}/attestations/delete-request"], - deleteAttestationsById: [ - "DELETE /orgs/{org}/attestations/{attestation_id}" - ], - deleteAttestationsBySubjectDigest: [ - "DELETE /orgs/{org}/attestations/digest/{subject_digest}" - ], - deleteIssueType: ["DELETE /orgs/{org}/issue-types/{issue_type_id}"], - deleteWebhook: ["DELETE /orgs/{org}/hooks/{hook_id}"], - disableSelectedRepositoryImmutableReleasesOrganization: [ - "DELETE /orgs/{org}/settings/immutable-releases/repositories/{repository_id}" - ], - enableSelectedRepositoryImmutableReleasesOrganization: [ - "PUT /orgs/{org}/settings/immutable-releases/repositories/{repository_id}" - ], - get: ["GET /orgs/{org}"], - getImmutableReleasesSettings: [ - "GET /orgs/{org}/settings/immutable-releases" - ], - getImmutableReleasesSettingsRepositories: [ - "GET /orgs/{org}/settings/immutable-releases/repositories" - ], - getMembershipForAuthenticatedUser: ["GET /user/memberships/orgs/{org}"], - getMembershipForUser: ["GET /orgs/{org}/memberships/{username}"], - getOrgRole: ["GET /orgs/{org}/organization-roles/{role_id}"], - getOrgRulesetHistory: ["GET /orgs/{org}/rulesets/{ruleset_id}/history"], - getOrgRulesetVersion: [ - "GET /orgs/{org}/rulesets/{ruleset_id}/history/{version_id}" - ], - getWebhook: ["GET /orgs/{org}/hooks/{hook_id}"], - getWebhookConfigForOrg: ["GET /orgs/{org}/hooks/{hook_id}/config"], - getWebhookDelivery: [ - "GET /orgs/{org}/hooks/{hook_id}/deliveries/{delivery_id}" - ], - list: ["GET /organizations"], - listAppInstallations: ["GET /orgs/{org}/installations"], - listArtifactStorageRecords: [ - "GET /orgs/{org}/artifacts/{subject_digest}/metadata/storage-records" - ], - listAttestationRepositories: ["GET /orgs/{org}/attestations/repositories"], - listAttestations: ["GET /orgs/{org}/attestations/{subject_digest}"], - listAttestationsBulk: [ - "POST /orgs/{org}/attestations/bulk-list{?per_page,before,after}" - ], - listBlockedUsers: ["GET /orgs/{org}/blocks"], - listFailedInvitations: ["GET /orgs/{org}/failed_invitations"], - listForAuthenticatedUser: ["GET /user/orgs"], - listForUser: ["GET /users/{username}/orgs"], - listInvitationTeams: ["GET /orgs/{org}/invitations/{invitation_id}/teams"], - listIssueTypes: ["GET /orgs/{org}/issue-types"], - listMembers: ["GET /orgs/{org}/members"], - listMembershipsForAuthenticatedUser: ["GET /user/memberships/orgs"], - listOrgRoleTeams: ["GET /orgs/{org}/organization-roles/{role_id}/teams"], - listOrgRoleUsers: ["GET /orgs/{org}/organization-roles/{role_id}/users"], - listOrgRoles: ["GET /orgs/{org}/organization-roles"], - listOrganizationFineGrainedPermissions: [ - "GET /orgs/{org}/organization-fine-grained-permissions" - ], - listOutsideCollaborators: ["GET /orgs/{org}/outside_collaborators"], - listPatGrantRepositories: [ - "GET /orgs/{org}/personal-access-tokens/{pat_id}/repositories" - ], - listPatGrantRequestRepositories: [ - "GET /orgs/{org}/personal-access-token-requests/{pat_request_id}/repositories" - ], - listPatGrantRequests: ["GET /orgs/{org}/personal-access-token-requests"], - listPatGrants: ["GET /orgs/{org}/personal-access-tokens"], - listPendingInvitations: ["GET /orgs/{org}/invitations"], - listPublicMembers: ["GET /orgs/{org}/public_members"], - listSecurityManagerTeams: [ - "GET /orgs/{org}/security-managers", - {}, - { - deprecated: "octokit.rest.orgs.listSecurityManagerTeams() is deprecated, see https://docs.github.com/rest/orgs/security-managers#list-security-manager-teams" - } - ], - listWebhookDeliveries: ["GET /orgs/{org}/hooks/{hook_id}/deliveries"], - listWebhooks: ["GET /orgs/{org}/hooks"], - pingWebhook: ["POST /orgs/{org}/hooks/{hook_id}/pings"], - redeliverWebhookDelivery: [ - "POST /orgs/{org}/hooks/{hook_id}/deliveries/{delivery_id}/attempts" - ], - removeMember: ["DELETE /orgs/{org}/members/{username}"], - removeMembershipForUser: ["DELETE /orgs/{org}/memberships/{username}"], - removeOutsideCollaborator: [ - "DELETE /orgs/{org}/outside_collaborators/{username}" - ], - removePublicMembershipForAuthenticatedUser: [ - "DELETE /orgs/{org}/public_members/{username}" - ], - removeSecurityManagerTeam: [ - "DELETE /orgs/{org}/security-managers/teams/{team_slug}", - {}, - { - deprecated: "octokit.rest.orgs.removeSecurityManagerTeam() is deprecated, see https://docs.github.com/rest/orgs/security-managers#remove-a-security-manager-team" - } - ], - reviewPatGrantRequest: [ - "POST /orgs/{org}/personal-access-token-requests/{pat_request_id}" - ], - reviewPatGrantRequestsInBulk: [ - "POST /orgs/{org}/personal-access-token-requests" - ], - revokeAllOrgRolesTeam: [ - "DELETE /orgs/{org}/organization-roles/teams/{team_slug}" - ], - revokeAllOrgRolesUser: [ - "DELETE /orgs/{org}/organization-roles/users/{username}" - ], - revokeOrgRoleTeam: [ - "DELETE /orgs/{org}/organization-roles/teams/{team_slug}/{role_id}" - ], - revokeOrgRoleUser: [ - "DELETE /orgs/{org}/organization-roles/users/{username}/{role_id}" - ], - setImmutableReleasesSettings: [ - "PUT /orgs/{org}/settings/immutable-releases" - ], - setImmutableReleasesSettingsRepositories: [ - "PUT /orgs/{org}/settings/immutable-releases/repositories" - ], - setMembershipForUser: ["PUT /orgs/{org}/memberships/{username}"], - setPublicMembershipForAuthenticatedUser: [ - "PUT /orgs/{org}/public_members/{username}" - ], - unblockUser: ["DELETE /orgs/{org}/blocks/{username}"], - update: ["PATCH /orgs/{org}"], - updateIssueType: ["PUT /orgs/{org}/issue-types/{issue_type_id}"], - updateMembershipForAuthenticatedUser: [ - "PATCH /user/memberships/orgs/{org}" - ], - updatePatAccess: ["POST /orgs/{org}/personal-access-tokens/{pat_id}"], - updatePatAccesses: ["POST /orgs/{org}/personal-access-tokens"], - updateWebhook: ["PATCH /orgs/{org}/hooks/{hook_id}"], - updateWebhookConfigForOrg: ["PATCH /orgs/{org}/hooks/{hook_id}/config"] - }, - packages: { - deletePackageForAuthenticatedUser: [ - "DELETE /user/packages/{package_type}/{package_name}" - ], - deletePackageForOrg: [ - "DELETE /orgs/{org}/packages/{package_type}/{package_name}" - ], - deletePackageForUser: [ - "DELETE /users/{username}/packages/{package_type}/{package_name}" - ], - deletePackageVersionForAuthenticatedUser: [ - "DELETE /user/packages/{package_type}/{package_name}/versions/{package_version_id}" - ], - deletePackageVersionForOrg: [ - "DELETE /orgs/{org}/packages/{package_type}/{package_name}/versions/{package_version_id}" - ], - deletePackageVersionForUser: [ - "DELETE /users/{username}/packages/{package_type}/{package_name}/versions/{package_version_id}" - ], - getAllPackageVersionsForAPackageOwnedByAnOrg: [ - "GET /orgs/{org}/packages/{package_type}/{package_name}/versions", - {}, - { renamed: ["packages", "getAllPackageVersionsForPackageOwnedByOrg"] } - ], - getAllPackageVersionsForAPackageOwnedByTheAuthenticatedUser: [ - "GET /user/packages/{package_type}/{package_name}/versions", - {}, - { - renamed: [ - "packages", - "getAllPackageVersionsForPackageOwnedByAuthenticatedUser" - ] - } - ], - getAllPackageVersionsForPackageOwnedByAuthenticatedUser: [ - "GET /user/packages/{package_type}/{package_name}/versions" - ], - getAllPackageVersionsForPackageOwnedByOrg: [ - "GET /orgs/{org}/packages/{package_type}/{package_name}/versions" - ], - getAllPackageVersionsForPackageOwnedByUser: [ - "GET /users/{username}/packages/{package_type}/{package_name}/versions" - ], - getPackageForAuthenticatedUser: [ - "GET /user/packages/{package_type}/{package_name}" - ], - getPackageForOrganization: [ - "GET /orgs/{org}/packages/{package_type}/{package_name}" - ], - getPackageForUser: [ - "GET /users/{username}/packages/{package_type}/{package_name}" - ], - getPackageVersionForAuthenticatedUser: [ - "GET /user/packages/{package_type}/{package_name}/versions/{package_version_id}" - ], - getPackageVersionForOrganization: [ - "GET /orgs/{org}/packages/{package_type}/{package_name}/versions/{package_version_id}" - ], - getPackageVersionForUser: [ - "GET /users/{username}/packages/{package_type}/{package_name}/versions/{package_version_id}" - ], - listDockerMigrationConflictingPackagesForAuthenticatedUser: [ - "GET /user/docker/conflicts" - ], - listDockerMigrationConflictingPackagesForOrganization: [ - "GET /orgs/{org}/docker/conflicts" - ], - listDockerMigrationConflictingPackagesForUser: [ - "GET /users/{username}/docker/conflicts" - ], - listPackagesForAuthenticatedUser: ["GET /user/packages"], - listPackagesForOrganization: ["GET /orgs/{org}/packages"], - listPackagesForUser: ["GET /users/{username}/packages"], - restorePackageForAuthenticatedUser: [ - "POST /user/packages/{package_type}/{package_name}/restore{?token}" - ], - restorePackageForOrg: [ - "POST /orgs/{org}/packages/{package_type}/{package_name}/restore{?token}" - ], - restorePackageForUser: [ - "POST /users/{username}/packages/{package_type}/{package_name}/restore{?token}" - ], - restorePackageVersionForAuthenticatedUser: [ - "POST /user/packages/{package_type}/{package_name}/versions/{package_version_id}/restore" - ], - restorePackageVersionForOrg: [ - "POST /orgs/{org}/packages/{package_type}/{package_name}/versions/{package_version_id}/restore" - ], - restorePackageVersionForUser: [ - "POST /users/{username}/packages/{package_type}/{package_name}/versions/{package_version_id}/restore" - ] - }, - privateRegistries: { - createOrgPrivateRegistry: ["POST /orgs/{org}/private-registries"], - deleteOrgPrivateRegistry: [ - "DELETE /orgs/{org}/private-registries/{secret_name}" - ], - getOrgPrivateRegistry: ["GET /orgs/{org}/private-registries/{secret_name}"], - getOrgPublicKey: ["GET /orgs/{org}/private-registries/public-key"], - listOrgPrivateRegistries: ["GET /orgs/{org}/private-registries"], - updateOrgPrivateRegistry: [ - "PATCH /orgs/{org}/private-registries/{secret_name}" - ] - }, - projects: { - addItemForOrg: ["POST /orgs/{org}/projectsV2/{project_number}/items"], - addItemForUser: [ - "POST /users/{username}/projectsV2/{project_number}/items" - ], - deleteItemForOrg: [ - "DELETE /orgs/{org}/projectsV2/{project_number}/items/{item_id}" - ], - deleteItemForUser: [ - "DELETE /users/{username}/projectsV2/{project_number}/items/{item_id}" - ], - getFieldForOrg: [ - "GET /orgs/{org}/projectsV2/{project_number}/fields/{field_id}" - ], - getFieldForUser: [ - "GET /users/{username}/projectsV2/{project_number}/fields/{field_id}" - ], - getForOrg: ["GET /orgs/{org}/projectsV2/{project_number}"], - getForUser: ["GET /users/{username}/projectsV2/{project_number}"], - getOrgItem: ["GET /orgs/{org}/projectsV2/{project_number}/items/{item_id}"], - getUserItem: [ - "GET /users/{username}/projectsV2/{project_number}/items/{item_id}" - ], - listFieldsForOrg: ["GET /orgs/{org}/projectsV2/{project_number}/fields"], - listFieldsForUser: [ - "GET /users/{username}/projectsV2/{project_number}/fields" - ], - listForOrg: ["GET /orgs/{org}/projectsV2"], - listForUser: ["GET /users/{username}/projectsV2"], - listItemsForOrg: ["GET /orgs/{org}/projectsV2/{project_number}/items"], - listItemsForUser: [ - "GET /users/{username}/projectsV2/{project_number}/items" - ], - updateItemForOrg: [ - "PATCH /orgs/{org}/projectsV2/{project_number}/items/{item_id}" - ], - updateItemForUser: [ - "PATCH /users/{username}/projectsV2/{project_number}/items/{item_id}" - ] - }, - pulls: { - checkIfMerged: ["GET /repos/{owner}/{repo}/pulls/{pull_number}/merge"], - create: ["POST /repos/{owner}/{repo}/pulls"], - createReplyForReviewComment: [ - "POST /repos/{owner}/{repo}/pulls/{pull_number}/comments/{comment_id}/replies" - ], - createReview: ["POST /repos/{owner}/{repo}/pulls/{pull_number}/reviews"], - createReviewComment: [ - "POST /repos/{owner}/{repo}/pulls/{pull_number}/comments" - ], - deletePendingReview: [ - "DELETE /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}" - ], - deleteReviewComment: [ - "DELETE /repos/{owner}/{repo}/pulls/comments/{comment_id}" - ], - dismissReview: [ - "PUT /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/dismissals" - ], - get: ["GET /repos/{owner}/{repo}/pulls/{pull_number}"], - getReview: [ - "GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}" - ], - getReviewComment: ["GET /repos/{owner}/{repo}/pulls/comments/{comment_id}"], - list: ["GET /repos/{owner}/{repo}/pulls"], - listCommentsForReview: [ - "GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/comments" - ], - listCommits: ["GET /repos/{owner}/{repo}/pulls/{pull_number}/commits"], - listFiles: ["GET /repos/{owner}/{repo}/pulls/{pull_number}/files"], - listRequestedReviewers: [ - "GET /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers" - ], - listReviewComments: [ - "GET /repos/{owner}/{repo}/pulls/{pull_number}/comments" - ], - listReviewCommentsForRepo: ["GET /repos/{owner}/{repo}/pulls/comments"], - listReviews: ["GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews"], - merge: ["PUT /repos/{owner}/{repo}/pulls/{pull_number}/merge"], - removeRequestedReviewers: [ - "DELETE /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers" - ], - requestReviewers: [ - "POST /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers" - ], - submitReview: [ - "POST /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/events" - ], - update: ["PATCH /repos/{owner}/{repo}/pulls/{pull_number}"], - updateBranch: [ - "PUT /repos/{owner}/{repo}/pulls/{pull_number}/update-branch" - ], - updateReview: [ - "PUT /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}" - ], - updateReviewComment: [ - "PATCH /repos/{owner}/{repo}/pulls/comments/{comment_id}" - ] - }, - rateLimit: { get: ["GET /rate_limit"] }, - reactions: { - createForCommitComment: [ - "POST /repos/{owner}/{repo}/comments/{comment_id}/reactions" - ], - createForIssue: [ - "POST /repos/{owner}/{repo}/issues/{issue_number}/reactions" - ], - createForIssueComment: [ - "POST /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions" - ], - createForPullRequestReviewComment: [ - "POST /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions" - ], - createForRelease: [ - "POST /repos/{owner}/{repo}/releases/{release_id}/reactions" - ], - createForTeamDiscussionCommentInOrg: [ - "POST /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions" - ], - createForTeamDiscussionInOrg: [ - "POST /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions" - ], - deleteForCommitComment: [ - "DELETE /repos/{owner}/{repo}/comments/{comment_id}/reactions/{reaction_id}" - ], - deleteForIssue: [ - "DELETE /repos/{owner}/{repo}/issues/{issue_number}/reactions/{reaction_id}" - ], - deleteForIssueComment: [ - "DELETE /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions/{reaction_id}" - ], - deleteForPullRequestComment: [ - "DELETE /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions/{reaction_id}" - ], - deleteForRelease: [ - "DELETE /repos/{owner}/{repo}/releases/{release_id}/reactions/{reaction_id}" - ], - deleteForTeamDiscussion: [ - "DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions/{reaction_id}" - ], - deleteForTeamDiscussionComment: [ - "DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions/{reaction_id}" - ], - listForCommitComment: [ - "GET /repos/{owner}/{repo}/comments/{comment_id}/reactions" - ], - listForIssue: ["GET /repos/{owner}/{repo}/issues/{issue_number}/reactions"], - listForIssueComment: [ - "GET /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions" - ], - listForPullRequestReviewComment: [ - "GET /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions" - ], - listForRelease: [ - "GET /repos/{owner}/{repo}/releases/{release_id}/reactions" - ], - listForTeamDiscussionCommentInOrg: [ - "GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions" - ], - listForTeamDiscussionInOrg: [ - "GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions" - ] - }, - repos: { - acceptInvitation: [ - "PATCH /user/repository_invitations/{invitation_id}", - {}, - { renamed: ["repos", "acceptInvitationForAuthenticatedUser"] } - ], - acceptInvitationForAuthenticatedUser: [ - "PATCH /user/repository_invitations/{invitation_id}" - ], - addAppAccessRestrictions: [ - "POST /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps", - {}, - { mapToData: "apps" } - ], - addCollaborator: ["PUT /repos/{owner}/{repo}/collaborators/{username}"], - addStatusCheckContexts: [ - "POST /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks/contexts", - {}, - { mapToData: "contexts" } - ], - addTeamAccessRestrictions: [ - "POST /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams", - {}, - { mapToData: "teams" } - ], - addUserAccessRestrictions: [ - "POST /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users", - {}, - { mapToData: "users" } - ], - cancelPagesDeployment: [ - "POST /repos/{owner}/{repo}/pages/deployments/{pages_deployment_id}/cancel" - ], - checkAutomatedSecurityFixes: [ - "GET /repos/{owner}/{repo}/automated-security-fixes" - ], - checkCollaborator: ["GET /repos/{owner}/{repo}/collaborators/{username}"], - checkImmutableReleases: ["GET /repos/{owner}/{repo}/immutable-releases"], - checkPrivateVulnerabilityReporting: [ - "GET /repos/{owner}/{repo}/private-vulnerability-reporting" - ], - checkVulnerabilityAlerts: [ - "GET /repos/{owner}/{repo}/vulnerability-alerts" - ], - codeownersErrors: ["GET /repos/{owner}/{repo}/codeowners/errors"], - compareCommits: ["GET /repos/{owner}/{repo}/compare/{base}...{head}"], - compareCommitsWithBasehead: [ - "GET /repos/{owner}/{repo}/compare/{basehead}" - ], - createAttestation: ["POST /repos/{owner}/{repo}/attestations"], - createAutolink: ["POST /repos/{owner}/{repo}/autolinks"], - createCommitComment: [ - "POST /repos/{owner}/{repo}/commits/{commit_sha}/comments" - ], - createCommitSignatureProtection: [ - "POST /repos/{owner}/{repo}/branches/{branch}/protection/required_signatures" - ], - createCommitStatus: ["POST /repos/{owner}/{repo}/statuses/{sha}"], - createDeployKey: ["POST /repos/{owner}/{repo}/keys"], - createDeployment: ["POST /repos/{owner}/{repo}/deployments"], - createDeploymentBranchPolicy: [ - "POST /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies" - ], - createDeploymentProtectionRule: [ - "POST /repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules" - ], - createDeploymentStatus: [ - "POST /repos/{owner}/{repo}/deployments/{deployment_id}/statuses" - ], - createDispatchEvent: ["POST /repos/{owner}/{repo}/dispatches"], - createForAuthenticatedUser: ["POST /user/repos"], - createFork: ["POST /repos/{owner}/{repo}/forks"], - createInOrg: ["POST /orgs/{org}/repos"], - createOrUpdateEnvironment: [ - "PUT /repos/{owner}/{repo}/environments/{environment_name}" - ], - createOrUpdateFileContents: ["PUT /repos/{owner}/{repo}/contents/{path}"], - createOrgRuleset: ["POST /orgs/{org}/rulesets"], - createPagesDeployment: ["POST /repos/{owner}/{repo}/pages/deployments"], - createPagesSite: ["POST /repos/{owner}/{repo}/pages"], - createRelease: ["POST /repos/{owner}/{repo}/releases"], - createRepoRuleset: ["POST /repos/{owner}/{repo}/rulesets"], - createUsingTemplate: [ - "POST /repos/{template_owner}/{template_repo}/generate" - ], - createWebhook: ["POST /repos/{owner}/{repo}/hooks"], - customPropertiesForReposCreateOrUpdateRepositoryValues: [ - "PATCH /repos/{owner}/{repo}/properties/values" - ], - customPropertiesForReposGetRepositoryValues: [ - "GET /repos/{owner}/{repo}/properties/values" - ], - declineInvitation: [ - "DELETE /user/repository_invitations/{invitation_id}", - {}, - { renamed: ["repos", "declineInvitationForAuthenticatedUser"] } - ], - declineInvitationForAuthenticatedUser: [ - "DELETE /user/repository_invitations/{invitation_id}" - ], - delete: ["DELETE /repos/{owner}/{repo}"], - deleteAccessRestrictions: [ - "DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions" - ], - deleteAdminBranchProtection: [ - "DELETE /repos/{owner}/{repo}/branches/{branch}/protection/enforce_admins" - ], - deleteAnEnvironment: [ - "DELETE /repos/{owner}/{repo}/environments/{environment_name}" - ], - deleteAutolink: ["DELETE /repos/{owner}/{repo}/autolinks/{autolink_id}"], - deleteBranchProtection: [ - "DELETE /repos/{owner}/{repo}/branches/{branch}/protection" - ], - deleteCommitComment: ["DELETE /repos/{owner}/{repo}/comments/{comment_id}"], - deleteCommitSignatureProtection: [ - "DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_signatures" - ], - deleteDeployKey: ["DELETE /repos/{owner}/{repo}/keys/{key_id}"], - deleteDeployment: [ - "DELETE /repos/{owner}/{repo}/deployments/{deployment_id}" - ], - deleteDeploymentBranchPolicy: [ - "DELETE /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies/{branch_policy_id}" - ], - deleteFile: ["DELETE /repos/{owner}/{repo}/contents/{path}"], - deleteInvitation: [ - "DELETE /repos/{owner}/{repo}/invitations/{invitation_id}" - ], - deleteOrgRuleset: ["DELETE /orgs/{org}/rulesets/{ruleset_id}"], - deletePagesSite: ["DELETE /repos/{owner}/{repo}/pages"], - deletePullRequestReviewProtection: [ - "DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews" - ], - deleteRelease: ["DELETE /repos/{owner}/{repo}/releases/{release_id}"], - deleteReleaseAsset: [ - "DELETE /repos/{owner}/{repo}/releases/assets/{asset_id}" - ], - deleteRepoRuleset: ["DELETE /repos/{owner}/{repo}/rulesets/{ruleset_id}"], - deleteWebhook: ["DELETE /repos/{owner}/{repo}/hooks/{hook_id}"], - disableAutomatedSecurityFixes: [ - "DELETE /repos/{owner}/{repo}/automated-security-fixes" - ], - disableDeploymentProtectionRule: [ - "DELETE /repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules/{protection_rule_id}" - ], - disableImmutableReleases: [ - "DELETE /repos/{owner}/{repo}/immutable-releases" - ], - disablePrivateVulnerabilityReporting: [ - "DELETE /repos/{owner}/{repo}/private-vulnerability-reporting" - ], - disableVulnerabilityAlerts: [ - "DELETE /repos/{owner}/{repo}/vulnerability-alerts" - ], - downloadArchive: [ - "GET /repos/{owner}/{repo}/zipball/{ref}", - {}, - { renamed: ["repos", "downloadZipballArchive"] } - ], - downloadTarballArchive: ["GET /repos/{owner}/{repo}/tarball/{ref}"], - downloadZipballArchive: ["GET /repos/{owner}/{repo}/zipball/{ref}"], - enableAutomatedSecurityFixes: [ - "PUT /repos/{owner}/{repo}/automated-security-fixes" - ], - enableImmutableReleases: ["PUT /repos/{owner}/{repo}/immutable-releases"], - enablePrivateVulnerabilityReporting: [ - "PUT /repos/{owner}/{repo}/private-vulnerability-reporting" - ], - enableVulnerabilityAlerts: [ - "PUT /repos/{owner}/{repo}/vulnerability-alerts" - ], - generateReleaseNotes: [ - "POST /repos/{owner}/{repo}/releases/generate-notes" - ], - get: ["GET /repos/{owner}/{repo}"], - getAccessRestrictions: [ - "GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions" - ], - getAdminBranchProtection: [ - "GET /repos/{owner}/{repo}/branches/{branch}/protection/enforce_admins" - ], - getAllDeploymentProtectionRules: [ - "GET /repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules" - ], - getAllEnvironments: ["GET /repos/{owner}/{repo}/environments"], - getAllStatusCheckContexts: [ - "GET /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks/contexts" - ], - getAllTopics: ["GET /repos/{owner}/{repo}/topics"], - getAppsWithAccessToProtectedBranch: [ - "GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps" - ], - getAutolink: ["GET /repos/{owner}/{repo}/autolinks/{autolink_id}"], - getBranch: ["GET /repos/{owner}/{repo}/branches/{branch}"], - getBranchProtection: [ - "GET /repos/{owner}/{repo}/branches/{branch}/protection" - ], - getBranchRules: ["GET /repos/{owner}/{repo}/rules/branches/{branch}"], - getClones: ["GET /repos/{owner}/{repo}/traffic/clones"], - getCodeFrequencyStats: ["GET /repos/{owner}/{repo}/stats/code_frequency"], - getCollaboratorPermissionLevel: [ - "GET /repos/{owner}/{repo}/collaborators/{username}/permission" - ], - getCombinedStatusForRef: ["GET /repos/{owner}/{repo}/commits/{ref}/status"], - getCommit: ["GET /repos/{owner}/{repo}/commits/{ref}"], - getCommitActivityStats: ["GET /repos/{owner}/{repo}/stats/commit_activity"], - getCommitComment: ["GET /repos/{owner}/{repo}/comments/{comment_id}"], - getCommitSignatureProtection: [ - "GET /repos/{owner}/{repo}/branches/{branch}/protection/required_signatures" - ], - getCommunityProfileMetrics: ["GET /repos/{owner}/{repo}/community/profile"], - getContent: ["GET /repos/{owner}/{repo}/contents/{path}"], - getContributorsStats: ["GET /repos/{owner}/{repo}/stats/contributors"], - getCustomDeploymentProtectionRule: [ - "GET /repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules/{protection_rule_id}" - ], - getDeployKey: ["GET /repos/{owner}/{repo}/keys/{key_id}"], - getDeployment: ["GET /repos/{owner}/{repo}/deployments/{deployment_id}"], - getDeploymentBranchPolicy: [ - "GET /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies/{branch_policy_id}" - ], - getDeploymentStatus: [ - "GET /repos/{owner}/{repo}/deployments/{deployment_id}/statuses/{status_id}" - ], - getEnvironment: [ - "GET /repos/{owner}/{repo}/environments/{environment_name}" - ], - getLatestPagesBuild: ["GET /repos/{owner}/{repo}/pages/builds/latest"], - getLatestRelease: ["GET /repos/{owner}/{repo}/releases/latest"], - getOrgRuleSuite: ["GET /orgs/{org}/rulesets/rule-suites/{rule_suite_id}"], - getOrgRuleSuites: ["GET /orgs/{org}/rulesets/rule-suites"], - getOrgRuleset: ["GET /orgs/{org}/rulesets/{ruleset_id}"], - getOrgRulesets: ["GET /orgs/{org}/rulesets"], - getPages: ["GET /repos/{owner}/{repo}/pages"], - getPagesBuild: ["GET /repos/{owner}/{repo}/pages/builds/{build_id}"], - getPagesDeployment: [ - "GET /repos/{owner}/{repo}/pages/deployments/{pages_deployment_id}" - ], - getPagesHealthCheck: ["GET /repos/{owner}/{repo}/pages/health"], - getParticipationStats: ["GET /repos/{owner}/{repo}/stats/participation"], - getPullRequestReviewProtection: [ - "GET /repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews" - ], - getPunchCardStats: ["GET /repos/{owner}/{repo}/stats/punch_card"], - getReadme: ["GET /repos/{owner}/{repo}/readme"], - getReadmeInDirectory: ["GET /repos/{owner}/{repo}/readme/{dir}"], - getRelease: ["GET /repos/{owner}/{repo}/releases/{release_id}"], - getReleaseAsset: ["GET /repos/{owner}/{repo}/releases/assets/{asset_id}"], - getReleaseByTag: ["GET /repos/{owner}/{repo}/releases/tags/{tag}"], - getRepoRuleSuite: [ - "GET /repos/{owner}/{repo}/rulesets/rule-suites/{rule_suite_id}" - ], - getRepoRuleSuites: ["GET /repos/{owner}/{repo}/rulesets/rule-suites"], - getRepoRuleset: ["GET /repos/{owner}/{repo}/rulesets/{ruleset_id}"], - getRepoRulesetHistory: [ - "GET /repos/{owner}/{repo}/rulesets/{ruleset_id}/history" - ], - getRepoRulesetVersion: [ - "GET /repos/{owner}/{repo}/rulesets/{ruleset_id}/history/{version_id}" - ], - getRepoRulesets: ["GET /repos/{owner}/{repo}/rulesets"], - getStatusChecksProtection: [ - "GET /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks" - ], - getTeamsWithAccessToProtectedBranch: [ - "GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams" - ], - getTopPaths: ["GET /repos/{owner}/{repo}/traffic/popular/paths"], - getTopReferrers: ["GET /repos/{owner}/{repo}/traffic/popular/referrers"], - getUsersWithAccessToProtectedBranch: [ - "GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users" - ], - getViews: ["GET /repos/{owner}/{repo}/traffic/views"], - getWebhook: ["GET /repos/{owner}/{repo}/hooks/{hook_id}"], - getWebhookConfigForRepo: [ - "GET /repos/{owner}/{repo}/hooks/{hook_id}/config" - ], - getWebhookDelivery: [ - "GET /repos/{owner}/{repo}/hooks/{hook_id}/deliveries/{delivery_id}" - ], - listActivities: ["GET /repos/{owner}/{repo}/activity"], - listAttestations: [ - "GET /repos/{owner}/{repo}/attestations/{subject_digest}" - ], - listAutolinks: ["GET /repos/{owner}/{repo}/autolinks"], - listBranches: ["GET /repos/{owner}/{repo}/branches"], - listBranchesForHeadCommit: [ - "GET /repos/{owner}/{repo}/commits/{commit_sha}/branches-where-head" - ], - listCollaborators: ["GET /repos/{owner}/{repo}/collaborators"], - listCommentsForCommit: [ - "GET /repos/{owner}/{repo}/commits/{commit_sha}/comments" - ], - listCommitCommentsForRepo: ["GET /repos/{owner}/{repo}/comments"], - listCommitStatusesForRef: [ - "GET /repos/{owner}/{repo}/commits/{ref}/statuses" - ], - listCommits: ["GET /repos/{owner}/{repo}/commits"], - listContributors: ["GET /repos/{owner}/{repo}/contributors"], - listCustomDeploymentRuleIntegrations: [ - "GET /repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules/apps" - ], - listDeployKeys: ["GET /repos/{owner}/{repo}/keys"], - listDeploymentBranchPolicies: [ - "GET /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies" - ], - listDeploymentStatuses: [ - "GET /repos/{owner}/{repo}/deployments/{deployment_id}/statuses" - ], - listDeployments: ["GET /repos/{owner}/{repo}/deployments"], - listForAuthenticatedUser: ["GET /user/repos"], - listForOrg: ["GET /orgs/{org}/repos"], - listForUser: ["GET /users/{username}/repos"], - listForks: ["GET /repos/{owner}/{repo}/forks"], - listInvitations: ["GET /repos/{owner}/{repo}/invitations"], - listInvitationsForAuthenticatedUser: ["GET /user/repository_invitations"], - listLanguages: ["GET /repos/{owner}/{repo}/languages"], - listPagesBuilds: ["GET /repos/{owner}/{repo}/pages/builds"], - listPublic: ["GET /repositories"], - listPullRequestsAssociatedWithCommit: [ - "GET /repos/{owner}/{repo}/commits/{commit_sha}/pulls" - ], - listReleaseAssets: [ - "GET /repos/{owner}/{repo}/releases/{release_id}/assets" - ], - listReleases: ["GET /repos/{owner}/{repo}/releases"], - listTags: ["GET /repos/{owner}/{repo}/tags"], - listTeams: ["GET /repos/{owner}/{repo}/teams"], - listWebhookDeliveries: [ - "GET /repos/{owner}/{repo}/hooks/{hook_id}/deliveries" - ], - listWebhooks: ["GET /repos/{owner}/{repo}/hooks"], - merge: ["POST /repos/{owner}/{repo}/merges"], - mergeUpstream: ["POST /repos/{owner}/{repo}/merge-upstream"], - pingWebhook: ["POST /repos/{owner}/{repo}/hooks/{hook_id}/pings"], - redeliverWebhookDelivery: [ - "POST /repos/{owner}/{repo}/hooks/{hook_id}/deliveries/{delivery_id}/attempts" - ], - removeAppAccessRestrictions: [ - "DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps", - {}, - { mapToData: "apps" } - ], - removeCollaborator: [ - "DELETE /repos/{owner}/{repo}/collaborators/{username}" - ], - removeStatusCheckContexts: [ - "DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks/contexts", - {}, - { mapToData: "contexts" } - ], - removeStatusCheckProtection: [ - "DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks" - ], - removeTeamAccessRestrictions: [ - "DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams", - {}, - { mapToData: "teams" } - ], - removeUserAccessRestrictions: [ - "DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users", - {}, - { mapToData: "users" } - ], - renameBranch: ["POST /repos/{owner}/{repo}/branches/{branch}/rename"], - replaceAllTopics: ["PUT /repos/{owner}/{repo}/topics"], - requestPagesBuild: ["POST /repos/{owner}/{repo}/pages/builds"], - setAdminBranchProtection: [ - "POST /repos/{owner}/{repo}/branches/{branch}/protection/enforce_admins" - ], - setAppAccessRestrictions: [ - "PUT /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps", - {}, - { mapToData: "apps" } - ], - setStatusCheckContexts: [ - "PUT /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks/contexts", - {}, - { mapToData: "contexts" } - ], - setTeamAccessRestrictions: [ - "PUT /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams", - {}, - { mapToData: "teams" } - ], - setUserAccessRestrictions: [ - "PUT /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users", - {}, - { mapToData: "users" } - ], - testPushWebhook: ["POST /repos/{owner}/{repo}/hooks/{hook_id}/tests"], - transfer: ["POST /repos/{owner}/{repo}/transfer"], - update: ["PATCH /repos/{owner}/{repo}"], - updateBranchProtection: [ - "PUT /repos/{owner}/{repo}/branches/{branch}/protection" - ], - updateCommitComment: ["PATCH /repos/{owner}/{repo}/comments/{comment_id}"], - updateDeploymentBranchPolicy: [ - "PUT /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies/{branch_policy_id}" - ], - updateInformationAboutPagesSite: ["PUT /repos/{owner}/{repo}/pages"], - updateInvitation: [ - "PATCH /repos/{owner}/{repo}/invitations/{invitation_id}" - ], - updateOrgRuleset: ["PUT /orgs/{org}/rulesets/{ruleset_id}"], - updatePullRequestReviewProtection: [ - "PATCH /repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews" - ], - updateRelease: ["PATCH /repos/{owner}/{repo}/releases/{release_id}"], - updateReleaseAsset: [ - "PATCH /repos/{owner}/{repo}/releases/assets/{asset_id}" - ], - updateRepoRuleset: ["PUT /repos/{owner}/{repo}/rulesets/{ruleset_id}"], - updateStatusCheckPotection: [ - "PATCH /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks", - {}, - { renamed: ["repos", "updateStatusCheckProtection"] } - ], - updateStatusCheckProtection: [ - "PATCH /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks" - ], - updateWebhook: ["PATCH /repos/{owner}/{repo}/hooks/{hook_id}"], - updateWebhookConfigForRepo: [ - "PATCH /repos/{owner}/{repo}/hooks/{hook_id}/config" - ], - uploadReleaseAsset: [ - "POST /repos/{owner}/{repo}/releases/{release_id}/assets{?name,label}", - { baseUrl: "https://uploads.github.com" } - ] - }, - search: { - code: ["GET /search/code"], - commits: ["GET /search/commits"], - issuesAndPullRequests: ["GET /search/issues"], - labels: ["GET /search/labels"], - repos: ["GET /search/repositories"], - topics: ["GET /search/topics"], - users: ["GET /search/users"] - }, - secretScanning: { - createPushProtectionBypass: [ - "POST /repos/{owner}/{repo}/secret-scanning/push-protection-bypasses" - ], - getAlert: [ - "GET /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}" - ], - getScanHistory: ["GET /repos/{owner}/{repo}/secret-scanning/scan-history"], - listAlertsForOrg: ["GET /orgs/{org}/secret-scanning/alerts"], - listAlertsForRepo: ["GET /repos/{owner}/{repo}/secret-scanning/alerts"], - listLocationsForAlert: [ - "GET /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}/locations" - ], - listOrgPatternConfigs: [ - "GET /orgs/{org}/secret-scanning/pattern-configurations" - ], - updateAlert: [ - "PATCH /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}" - ], - updateOrgPatternConfigs: [ - "PATCH /orgs/{org}/secret-scanning/pattern-configurations" - ] - }, - securityAdvisories: { - createFork: [ - "POST /repos/{owner}/{repo}/security-advisories/{ghsa_id}/forks" - ], - createPrivateVulnerabilityReport: [ - "POST /repos/{owner}/{repo}/security-advisories/reports" - ], - createRepositoryAdvisory: [ - "POST /repos/{owner}/{repo}/security-advisories" - ], - createRepositoryAdvisoryCveRequest: [ - "POST /repos/{owner}/{repo}/security-advisories/{ghsa_id}/cve" - ], - getGlobalAdvisory: ["GET /advisories/{ghsa_id}"], - getRepositoryAdvisory: [ - "GET /repos/{owner}/{repo}/security-advisories/{ghsa_id}" - ], - listGlobalAdvisories: ["GET /advisories"], - listOrgRepositoryAdvisories: ["GET /orgs/{org}/security-advisories"], - listRepositoryAdvisories: ["GET /repos/{owner}/{repo}/security-advisories"], - updateRepositoryAdvisory: [ - "PATCH /repos/{owner}/{repo}/security-advisories/{ghsa_id}" - ] - }, - teams: { - addOrUpdateMembershipForUserInOrg: [ - "PUT /orgs/{org}/teams/{team_slug}/memberships/{username}" - ], - addOrUpdateRepoPermissionsInOrg: [ - "PUT /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}" - ], - checkPermissionsForRepoInOrg: [ - "GET /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}" - ], - create: ["POST /orgs/{org}/teams"], - createDiscussionCommentInOrg: [ - "POST /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments" - ], - createDiscussionInOrg: ["POST /orgs/{org}/teams/{team_slug}/discussions"], - deleteDiscussionCommentInOrg: [ - "DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}" - ], - deleteDiscussionInOrg: [ - "DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}" - ], - deleteInOrg: ["DELETE /orgs/{org}/teams/{team_slug}"], - getByName: ["GET /orgs/{org}/teams/{team_slug}"], - getDiscussionCommentInOrg: [ - "GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}" - ], - getDiscussionInOrg: [ - "GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}" - ], - getMembershipForUserInOrg: [ - "GET /orgs/{org}/teams/{team_slug}/memberships/{username}" - ], - list: ["GET /orgs/{org}/teams"], - listChildInOrg: ["GET /orgs/{org}/teams/{team_slug}/teams"], - listDiscussionCommentsInOrg: [ - "GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments" - ], - listDiscussionsInOrg: ["GET /orgs/{org}/teams/{team_slug}/discussions"], - listForAuthenticatedUser: ["GET /user/teams"], - listMembersInOrg: ["GET /orgs/{org}/teams/{team_slug}/members"], - listPendingInvitationsInOrg: [ - "GET /orgs/{org}/teams/{team_slug}/invitations" - ], - listReposInOrg: ["GET /orgs/{org}/teams/{team_slug}/repos"], - removeMembershipForUserInOrg: [ - "DELETE /orgs/{org}/teams/{team_slug}/memberships/{username}" - ], - removeRepoInOrg: [ - "DELETE /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}" - ], - updateDiscussionCommentInOrg: [ - "PATCH /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}" - ], - updateDiscussionInOrg: [ - "PATCH /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}" - ], - updateInOrg: ["PATCH /orgs/{org}/teams/{team_slug}"] + // 2. Run the appropriate set of steps from the following list: + // https://datatracker.ietf.org/doc/html/rfc6455#section-6.1 + // https://datatracker.ietf.org/doc/html/rfc6455#section-5.2 + + if (!isEstablished(this.#handler.readyState) || isClosing(this.#handler.readyState)) { + return + } + + // If data is a string + if (typeof data === 'string') { + // If the WebSocket connection is established and the WebSocket + // closing handshake has not yet started, then the user agent + // must send a WebSocket Message comprised of the data argument + // using a text frame opcode; if the data cannot be sent, e.g. + // because it would need to be buffered but the buffer is full, + // the user agent must flag the WebSocket as full and then close + // the WebSocket connection. Any invocation of this method with a + // string argument that does not throw an exception must increase + // the bufferedAmount attribute by the number of bytes needed to + // express the argument as UTF-8. + + const buffer = Buffer.from(data) + + this.#bufferedAmount += buffer.byteLength + this.#sendQueue.add(buffer, () => { + this.#bufferedAmount -= buffer.byteLength + }, sendHints.text) + } else if (isArrayBuffer(data)) { + // If the WebSocket connection is established, and the WebSocket + // closing handshake has not yet started, then the user agent must + // send a WebSocket Message comprised of data using a binary frame + // opcode; if the data cannot be sent, e.g. because it would need + // to be buffered but the buffer is full, the user agent must flag + // the WebSocket as full and then close the WebSocket connection. + // The data to be sent is the data stored in the buffer described + // by the ArrayBuffer object. Any invocation of this method with an + // ArrayBuffer argument that does not throw an exception must + // increase the bufferedAmount attribute by the length of the + // ArrayBuffer in bytes. + + this.#bufferedAmount += data.byteLength + this.#sendQueue.add(data, () => { + this.#bufferedAmount -= data.byteLength + }, sendHints.arrayBuffer) + } else if (ArrayBuffer.isView(data)) { + // If the WebSocket connection is established, and the WebSocket + // closing handshake has not yet started, then the user agent must + // send a WebSocket Message comprised of data using a binary frame + // opcode; if the data cannot be sent, e.g. because it would need to + // be buffered but the buffer is full, the user agent must flag the + // WebSocket as full and then close the WebSocket connection. The + // data to be sent is the data stored in the section of the buffer + // described by the ArrayBuffer object that data references. Any + // invocation of this method with this kind of argument that does + // not throw an exception must increase the bufferedAmount attribute + // by the length of data’s buffer in bytes. + + this.#bufferedAmount += data.byteLength + this.#sendQueue.add(data, () => { + this.#bufferedAmount -= data.byteLength + }, sendHints.typedArray) + } else if (webidl.is.Blob(data)) { + // If the WebSocket connection is established, and the WebSocket + // closing handshake has not yet started, then the user agent must + // send a WebSocket Message comprised of data using a binary frame + // opcode; if the data cannot be sent, e.g. because it would need to + // be buffered but the buffer is full, the user agent must flag the + // WebSocket as full and then close the WebSocket connection. The data + // to be sent is the raw data represented by the Blob object. Any + // invocation of this method with a Blob argument that does not throw + // an exception must increase the bufferedAmount attribute by the size + // of the Blob object’s raw data, in bytes. + + this.#bufferedAmount += data.size + this.#sendQueue.add(data, () => { + this.#bufferedAmount -= data.size + }, sendHints.blob) + } + } + + get readyState () { + webidl.brandCheck(this, WebSocket) + + // The readyState getter steps are to return this's ready state. + return this.#handler.readyState + } + + get bufferedAmount () { + webidl.brandCheck(this, WebSocket) + + return this.#bufferedAmount + } + + get url () { + webidl.brandCheck(this, WebSocket) + + // The url getter steps are to return this's url, serialized. + return URLSerializer(this.#url) + } + + get extensions () { + webidl.brandCheck(this, WebSocket) + + return this.#extensions + } + + get protocol () { + webidl.brandCheck(this, WebSocket) + + return this.#protocol + } + + get onopen () { + webidl.brandCheck(this, WebSocket) + + return this.#events.open + } + + set onopen (fn) { + webidl.brandCheck(this, WebSocket) + + if (this.#events.open) { + this.removeEventListener('open', this.#events.open) + } + + const listener = webidl.converters.EventHandlerNonNull(fn) + + if (listener !== null) { + this.addEventListener('open', listener) + this.#events.open = fn + } else { + this.#events.open = null + } + } + + get onerror () { + webidl.brandCheck(this, WebSocket) + + return this.#events.error + } + + set onerror (fn) { + webidl.brandCheck(this, WebSocket) + + if (this.#events.error) { + this.removeEventListener('error', this.#events.error) + } + + const listener = webidl.converters.EventHandlerNonNull(fn) + + if (listener !== null) { + this.addEventListener('error', listener) + this.#events.error = fn + } else { + this.#events.error = null + } + } + + get onclose () { + webidl.brandCheck(this, WebSocket) + + return this.#events.close + } + + set onclose (fn) { + webidl.brandCheck(this, WebSocket) + + if (this.#events.close) { + this.removeEventListener('close', this.#events.close) + } + + const listener = webidl.converters.EventHandlerNonNull(fn) + + if (listener !== null) { + this.addEventListener('close', listener) + this.#events.close = fn + } else { + this.#events.close = null + } + } + + get onmessage () { + webidl.brandCheck(this, WebSocket) + + return this.#events.message + } + + set onmessage (fn) { + webidl.brandCheck(this, WebSocket) + + if (this.#events.message) { + this.removeEventListener('message', this.#events.message) + } + + const listener = webidl.converters.EventHandlerNonNull(fn) + + if (listener !== null) { + this.addEventListener('message', listener) + this.#events.message = fn + } else { + this.#events.message = null + } + } + + get binaryType () { + webidl.brandCheck(this, WebSocket) + + return this.#binaryType + } + + set binaryType (type) { + webidl.brandCheck(this, WebSocket) + + if (type !== 'blob' && type !== 'arraybuffer') { + this.#binaryType = 'blob' + } else { + this.#binaryType = type + } + } + + /** + * @see https://websockets.spec.whatwg.org/#feedback-from-the-protocol + */ + #onConnectionEstablished (response, parsedExtensions) { + // processResponse is called when the "response’s header list has been received and initialized." + // once this happens, the connection is open + this.#handler.socket = response.socket + + const parser = new ByteParser(this.#handler, parsedExtensions) + parser.on('drain', () => this.#handler.onParserDrain()) + parser.on('error', (err) => this.#handler.onParserError(err)) + + this.#parser = parser + this.#sendQueue = new SendQueue(response.socket) + + // 1. Change the ready state to OPEN (1). + this.#handler.readyState = states.OPEN + + // 2. Change the extensions attribute’s value to the extensions in use, if + // it is not the null value. + // https://datatracker.ietf.org/doc/html/rfc6455#section-9.1 + const extensions = response.headersList.get('sec-websocket-extensions') + + if (extensions !== null) { + this.#extensions = extensions + } + + // 3. Change the protocol attribute’s value to the subprotocol in use, if + // it is not the null value. + // https://datatracker.ietf.org/doc/html/rfc6455#section-1.9 + const protocol = response.headersList.get('sec-websocket-protocol') + + if (protocol !== null) { + this.#protocol = protocol + } + + // 4. Fire an event named open at the WebSocket object. + fireEvent('open', this) + + if (channels.open.hasSubscribers) { + // Convert headers to a plain object for the event + const headers = response.headersList.entries + channels.open.publish({ + address: response.socket.address(), + protocol: this.#protocol, + extensions: this.#extensions, + websocket: this, + handshakeResponse: { + status: response.status, + statusText: response.statusText, + headers + } + }) + } + } + + #onMessage (type, data) { + // 1. If ready state is not OPEN (1), then return. + if (this.#handler.readyState !== states.OPEN) { + return + } + + // 2. Let dataForEvent be determined by switching on type and binary type: + let dataForEvent + + if (type === opcodes.TEXT) { + // -> type indicates that the data is Text + // a new DOMString containing data + try { + dataForEvent = utf8Decode(data) + } catch { + failWebsocketConnection(this.#handler, 1007, 'Received invalid UTF-8 in text frame.') + return + } + } else if (type === opcodes.BINARY) { + if (this.#binaryType === 'blob') { + // -> type indicates that the data is Binary and binary type is "blob" + // a new Blob object, created in the relevant Realm of the WebSocket + // object, that represents data as its raw data + dataForEvent = new Blob([data]) + } else { + // -> type indicates that the data is Binary and binary type is "arraybuffer" + // a new ArrayBuffer object, created in the relevant Realm of the + // WebSocket object, whose contents are data + dataForEvent = toArrayBuffer(data) + } + } + + // 3. Fire an event named message at the WebSocket object, using MessageEvent, + // with the origin attribute initialized to the serialization of the WebSocket + // object’s url's origin, and the data attribute initialized to dataForEvent. + fireEvent('message', this, createFastMessageEvent, { + origin: this.#url.origin, + data: dataForEvent + }) + } + + #onParserDrain () { + this.#handler.socket.resume() + } + + /** + * @see https://websockets.spec.whatwg.org/#feedback-from-the-protocol + * @see https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.4 + */ + #onSocketClose () { + // If the TCP connection was closed after the + // WebSocket closing handshake was completed, the WebSocket connection + // is said to have been closed _cleanly_. + const wasClean = + this.#handler.closeState.has(sentCloseFrameState.SENT) && + this.#handler.closeState.has(sentCloseFrameState.RECEIVED) + + let code = 1005 + let reason = '' + + const result = this.#parser?.closingInfo + + if (result && !result.error) { + code = result.code ?? 1005 + reason = result.reason + } + + // 1. Change the ready state to CLOSED (3). + this.#handler.readyState = states.CLOSED + + // 2. If the user agent was required to fail the WebSocket + // connection, or if the WebSocket connection was closed + // after being flagged as full, fire an event named error + // at the WebSocket object. + if (!this.#handler.closeState.has(sentCloseFrameState.RECEIVED)) { + // If _The WebSocket + // Connection is Closed_ and no Close control frame was received by the + // endpoint (such as could occur if the underlying transport connection + // is lost), _The WebSocket Connection Close Code_ is considered to be + // 1006. + code = 1006 + + fireEvent('error', this, (type, init) => new ErrorEvent(type, init), { + error: new TypeError(reason) + }) + } + + // 3. Fire an event named close at the WebSocket object, + // using CloseEvent, with the wasClean attribute + // initialized to true if the connection closed cleanly + // and false otherwise, the code attribute initialized to + // the WebSocket connection close code, and the reason + // attribute initialized to the result of applying UTF-8 + // decode without BOM to the WebSocket connection close + // reason. + // TODO: process.nextTick + fireEvent('close', this, (type, init) => new CloseEvent(type, init), { + wasClean, code, reason + }) + + if (channels.close.hasSubscribers) { + channels.close.publish({ + websocket: this, + code, + reason + }) + } + } + + /** + * @param {WebSocket} ws + * @param {Buffer|undefined} buffer + */ + static ping (ws, buffer) { + if (Buffer.isBuffer(buffer)) { + if (buffer.length > 125) { + throw new TypeError('A PING frame cannot have a body larger than 125 bytes.') + } + } else if (buffer !== undefined) { + throw new TypeError('Expected buffer payload') + } + + // An endpoint MAY send a Ping frame any time after the connection is + // established and before the connection is closed. + const readyState = ws.#handler.readyState + + if (isEstablished(readyState) && !isClosing(readyState) && !isClosed(readyState)) { + const frame = new WebsocketFrameSend(buffer) + ws.#handler.socket.write(frame.createFrame(opcodes.PING)) + } + } +} + +const { ping } = WebSocket +Reflect.deleteProperty(WebSocket, 'ping') + +// https://websockets.spec.whatwg.org/#dom-websocket-connecting +WebSocket.CONNECTING = WebSocket.prototype.CONNECTING = states.CONNECTING +// https://websockets.spec.whatwg.org/#dom-websocket-open +WebSocket.OPEN = WebSocket.prototype.OPEN = states.OPEN +// https://websockets.spec.whatwg.org/#dom-websocket-closing +WebSocket.CLOSING = WebSocket.prototype.CLOSING = states.CLOSING +// https://websockets.spec.whatwg.org/#dom-websocket-closed +WebSocket.CLOSED = WebSocket.prototype.CLOSED = states.CLOSED + +Object.defineProperties(WebSocket.prototype, { + CONNECTING: staticPropertyDescriptors, + OPEN: staticPropertyDescriptors, + CLOSING: staticPropertyDescriptors, + CLOSED: staticPropertyDescriptors, + url: kEnumerableProperty, + readyState: kEnumerableProperty, + bufferedAmount: kEnumerableProperty, + onopen: kEnumerableProperty, + onerror: kEnumerableProperty, + onclose: kEnumerableProperty, + close: kEnumerableProperty, + onmessage: kEnumerableProperty, + binaryType: kEnumerableProperty, + send: kEnumerableProperty, + extensions: kEnumerableProperty, + protocol: kEnumerableProperty, + [Symbol.toStringTag]: { + value: 'WebSocket', + writable: false, + enumerable: false, + configurable: true + } +}) + +Object.defineProperties(WebSocket, { + CONNECTING: staticPropertyDescriptors, + OPEN: staticPropertyDescriptors, + CLOSING: staticPropertyDescriptors, + CLOSED: staticPropertyDescriptors +}) + +webidl.converters['sequence'] = webidl.sequenceConverter( + webidl.converters.DOMString +) + +webidl.converters['DOMString or sequence'] = function (V, prefix, argument) { + if (webidl.util.Type(V) === webidl.util.Types.OBJECT && Symbol.iterator in V) { + return webidl.converters['sequence'](V) + } + + return webidl.converters.DOMString(V, prefix, argument) +} + +// This implements the proposal made in https://github.com/whatwg/websockets/issues/42 +webidl.converters.WebSocketInit = webidl.dictionaryConverter([ + { + key: 'protocols', + converter: webidl.converters['DOMString or sequence'], + defaultValue: () => [] }, - users: { - addEmailForAuthenticated: [ - "POST /user/emails", - {}, - { renamed: ["users", "addEmailForAuthenticatedUser"] } - ], - addEmailForAuthenticatedUser: ["POST /user/emails"], - addSocialAccountForAuthenticatedUser: ["POST /user/social_accounts"], - block: ["PUT /user/blocks/{username}"], - checkBlocked: ["GET /user/blocks/{username}"], - checkFollowingForUser: ["GET /users/{username}/following/{target_user}"], - checkPersonIsFollowedByAuthenticated: ["GET /user/following/{username}"], - createGpgKeyForAuthenticated: [ - "POST /user/gpg_keys", - {}, - { renamed: ["users", "createGpgKeyForAuthenticatedUser"] } - ], - createGpgKeyForAuthenticatedUser: ["POST /user/gpg_keys"], - createPublicSshKeyForAuthenticated: [ - "POST /user/keys", - {}, - { renamed: ["users", "createPublicSshKeyForAuthenticatedUser"] } - ], - createPublicSshKeyForAuthenticatedUser: ["POST /user/keys"], - createSshSigningKeyForAuthenticatedUser: ["POST /user/ssh_signing_keys"], - deleteAttestationsBulk: [ - "POST /users/{username}/attestations/delete-request" - ], - deleteAttestationsById: [ - "DELETE /users/{username}/attestations/{attestation_id}" - ], - deleteAttestationsBySubjectDigest: [ - "DELETE /users/{username}/attestations/digest/{subject_digest}" - ], - deleteEmailForAuthenticated: [ - "DELETE /user/emails", - {}, - { renamed: ["users", "deleteEmailForAuthenticatedUser"] } - ], - deleteEmailForAuthenticatedUser: ["DELETE /user/emails"], - deleteGpgKeyForAuthenticated: [ - "DELETE /user/gpg_keys/{gpg_key_id}", - {}, - { renamed: ["users", "deleteGpgKeyForAuthenticatedUser"] } - ], - deleteGpgKeyForAuthenticatedUser: ["DELETE /user/gpg_keys/{gpg_key_id}"], - deletePublicSshKeyForAuthenticated: [ - "DELETE /user/keys/{key_id}", - {}, - { renamed: ["users", "deletePublicSshKeyForAuthenticatedUser"] } - ], - deletePublicSshKeyForAuthenticatedUser: ["DELETE /user/keys/{key_id}"], - deleteSocialAccountForAuthenticatedUser: ["DELETE /user/social_accounts"], - deleteSshSigningKeyForAuthenticatedUser: [ - "DELETE /user/ssh_signing_keys/{ssh_signing_key_id}" - ], - follow: ["PUT /user/following/{username}"], - getAuthenticated: ["GET /user"], - getById: ["GET /user/{account_id}"], - getByUsername: ["GET /users/{username}"], - getContextForUser: ["GET /users/{username}/hovercard"], - getGpgKeyForAuthenticated: [ - "GET /user/gpg_keys/{gpg_key_id}", - {}, - { renamed: ["users", "getGpgKeyForAuthenticatedUser"] } - ], - getGpgKeyForAuthenticatedUser: ["GET /user/gpg_keys/{gpg_key_id}"], - getPublicSshKeyForAuthenticated: [ - "GET /user/keys/{key_id}", - {}, - { renamed: ["users", "getPublicSshKeyForAuthenticatedUser"] } - ], - getPublicSshKeyForAuthenticatedUser: ["GET /user/keys/{key_id}"], - getSshSigningKeyForAuthenticatedUser: [ - "GET /user/ssh_signing_keys/{ssh_signing_key_id}" - ], - list: ["GET /users"], - listAttestations: ["GET /users/{username}/attestations/{subject_digest}"], - listAttestationsBulk: [ - "POST /users/{username}/attestations/bulk-list{?per_page,before,after}" - ], - listBlockedByAuthenticated: [ - "GET /user/blocks", - {}, - { renamed: ["users", "listBlockedByAuthenticatedUser"] } - ], - listBlockedByAuthenticatedUser: ["GET /user/blocks"], - listEmailsForAuthenticated: [ - "GET /user/emails", - {}, - { renamed: ["users", "listEmailsForAuthenticatedUser"] } - ], - listEmailsForAuthenticatedUser: ["GET /user/emails"], - listFollowedByAuthenticated: [ - "GET /user/following", - {}, - { renamed: ["users", "listFollowedByAuthenticatedUser"] } - ], - listFollowedByAuthenticatedUser: ["GET /user/following"], - listFollowersForAuthenticatedUser: ["GET /user/followers"], - listFollowersForUser: ["GET /users/{username}/followers"], - listFollowingForUser: ["GET /users/{username}/following"], - listGpgKeysForAuthenticated: [ - "GET /user/gpg_keys", - {}, - { renamed: ["users", "listGpgKeysForAuthenticatedUser"] } - ], - listGpgKeysForAuthenticatedUser: ["GET /user/gpg_keys"], - listGpgKeysForUser: ["GET /users/{username}/gpg_keys"], - listPublicEmailsForAuthenticated: [ - "GET /user/public_emails", - {}, - { renamed: ["users", "listPublicEmailsForAuthenticatedUser"] } - ], - listPublicEmailsForAuthenticatedUser: ["GET /user/public_emails"], - listPublicKeysForUser: ["GET /users/{username}/keys"], - listPublicSshKeysForAuthenticated: [ - "GET /user/keys", - {}, - { renamed: ["users", "listPublicSshKeysForAuthenticatedUser"] } - ], - listPublicSshKeysForAuthenticatedUser: ["GET /user/keys"], - listSocialAccountsForAuthenticatedUser: ["GET /user/social_accounts"], - listSocialAccountsForUser: ["GET /users/{username}/social_accounts"], - listSshSigningKeysForAuthenticatedUser: ["GET /user/ssh_signing_keys"], - listSshSigningKeysForUser: ["GET /users/{username}/ssh_signing_keys"], - setPrimaryEmailVisibilityForAuthenticated: [ - "PATCH /user/email/visibility", - {}, - { renamed: ["users", "setPrimaryEmailVisibilityForAuthenticatedUser"] } - ], - setPrimaryEmailVisibilityForAuthenticatedUser: [ - "PATCH /user/email/visibility" - ], - unblock: ["DELETE /user/blocks/{username}"], - unfollow: ["DELETE /user/following/{username}"], - updateAuthenticated: ["PATCH /user"] + { + key: 'dispatcher', + converter: webidl.converters.any, + defaultValue: () => getGlobalDispatcher() + }, + { + key: 'headers', + converter: webidl.nullableConverter(webidl.converters.HeadersInit) + } +]) + +webidl.converters['DOMString or sequence or WebSocketInit'] = function (V) { + if (webidl.util.Type(V) === webidl.util.Types.OBJECT && !(Symbol.iterator in V)) { + return webidl.converters.WebSocketInit(V) + } + + return { protocols: webidl.converters['DOMString or sequence'](V) } +} + +webidl.converters.WebSocketSendData = function (V) { + if (webidl.util.Type(V) === webidl.util.Types.OBJECT) { + if (webidl.is.Blob(V)) { + return V + } + + if (webidl.is.BufferSource(V)) { + return V + } + } + + return webidl.converters.USVString(V) +} + +module.exports = { + WebSocket, + ping +} + + +/***/ }), + +/***/ 9676: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const isWindows = process.platform === 'win32' || + process.env.OSTYPE === 'cygwin' || + process.env.OSTYPE === 'msys' + +const path = __nccwpck_require__(6928) +const COLON = isWindows ? ';' : ':' +const isexe = __nccwpck_require__(3494) + +const getNotFoundError = (cmd) => + Object.assign(new Error(`not found: ${cmd}`), { code: 'ENOENT' }) + +const getPathInfo = (cmd, opt) => { + const colon = opt.colon || COLON + + // If it has a slash, then we don't bother searching the pathenv. + // just check the file itself, and that's it. + const pathEnv = cmd.match(/\//) || isWindows && cmd.match(/\\/) ? [''] + : ( + [ + // windows always checks the cwd first + ...(isWindows ? [process.cwd()] : []), + ...(opt.path || process.env.PATH || + /* istanbul ignore next: very unusual */ '').split(colon), + ] + ) + const pathExtExe = isWindows + ? opt.pathExt || process.env.PATHEXT || '.EXE;.CMD;.BAT;.COM' + : '' + const pathExt = isWindows ? pathExtExe.split(colon) : [''] + + if (isWindows) { + if (cmd.indexOf('.') !== -1 && pathExt[0] !== '') + pathExt.unshift('') + } + + return { + pathEnv, + pathExt, + pathExtExe, + } +} + +const which = (cmd, opt, cb) => { + if (typeof opt === 'function') { + cb = opt + opt = {} + } + if (!opt) + opt = {} + + const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt) + const found = [] + + const step = i => new Promise((resolve, reject) => { + if (i === pathEnv.length) + return opt.all && found.length ? resolve(found) + : reject(getNotFoundError(cmd)) + + const ppRaw = pathEnv[i] + const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw + + const pCmd = path.join(pathPart, cmd) + const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd + : pCmd + + resolve(subStep(p, i, 0)) + }) + + const subStep = (p, i, ii) => new Promise((resolve, reject) => { + if (ii === pathExt.length) + return resolve(step(i + 1)) + const ext = pathExt[ii] + isexe(p + ext, { pathExt: pathExtExe }, (er, is) => { + if (!er && is) { + if (opt.all) + found.push(p + ext) + else + return resolve(p + ext) + } + return resolve(subStep(p, i, ii + 1)) + }) + }) + + return cb ? step(0).then(res => cb(null, res), cb) : step(0) +} + +const whichSync = (cmd, opt) => { + opt = opt || {} + + const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt) + const found = [] + + for (let i = 0; i < pathEnv.length; i ++) { + const ppRaw = pathEnv[i] + const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw + + const pCmd = path.join(pathPart, cmd) + const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd + : pCmd + + for (let j = 0; j < pathExt.length; j ++) { + const cur = p + pathExt[j] + try { + const is = isexe.sync(cur, { pathExt: pathExtExe }) + if (is) { + if (opt.all) + found.push(cur) + else + return cur + } + } catch (ex) {} + } + } + + if (opt.all && found.length) + return found + + if (opt.nothrow) + return null + + throw getNotFoundError(cmd) +} + +module.exports = which +which.sync = whichSync + + +/***/ }), + +/***/ 9492: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.createFileSystemAdapter = exports.FILE_SYSTEM_ADAPTER = void 0; +const fs = __nccwpck_require__(9896); +exports.FILE_SYSTEM_ADAPTER = { + lstat: fs.lstat, + stat: fs.stat, + lstatSync: fs.lstatSync, + statSync: fs.statSync, + readdir: fs.readdir, + readdirSync: fs.readdirSync +}; +function createFileSystemAdapter(fsMethods) { + if (fsMethods === undefined) { + return exports.FILE_SYSTEM_ADAPTER; + } + return Object.assign(Object.assign({}, exports.FILE_SYSTEM_ADAPTER), fsMethods); +} +exports.createFileSystemAdapter = createFileSystemAdapter; + + +/***/ }), + +/***/ 1827: +/***/ ((__unused_webpack_module, exports) => { + + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.IS_SUPPORT_READDIR_WITH_FILE_TYPES = void 0; +const NODE_PROCESS_VERSION_PARTS = process.versions.node.split('.'); +if (NODE_PROCESS_VERSION_PARTS[0] === undefined || NODE_PROCESS_VERSION_PARTS[1] === undefined) { + throw new Error(`Unexpected behavior. The 'process.versions.node' variable has invalid value: ${process.versions.node}`); +} +const MAJOR_VERSION = Number.parseInt(NODE_PROCESS_VERSION_PARTS[0], 10); +const MINOR_VERSION = Number.parseInt(NODE_PROCESS_VERSION_PARTS[1], 10); +const SUPPORTED_MAJOR_VERSION = 10; +const SUPPORTED_MINOR_VERSION = 10; +const IS_MATCHED_BY_MAJOR = MAJOR_VERSION > SUPPORTED_MAJOR_VERSION; +const IS_MATCHED_BY_MAJOR_AND_MINOR = MAJOR_VERSION === SUPPORTED_MAJOR_VERSION && MINOR_VERSION >= SUPPORTED_MINOR_VERSION; +/** + * IS `true` for Node.js 10.10 and greater. + */ +exports.IS_SUPPORT_READDIR_WITH_FILE_TYPES = IS_MATCHED_BY_MAJOR || IS_MATCHED_BY_MAJOR_AND_MINOR; + + +/***/ }), + +/***/ 2770: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Settings = exports.scandirSync = exports.scandir = void 0; +const async = __nccwpck_require__(6991); +const sync = __nccwpck_require__(4308); +const settings_1 = __nccwpck_require__(3233); +exports.Settings = settings_1.default; +function scandir(path, optionsOrSettingsOrCallback, callback) { + if (typeof optionsOrSettingsOrCallback === 'function') { + async.read(path, getSettings(), optionsOrSettingsOrCallback); + return; + } + async.read(path, getSettings(optionsOrSettingsOrCallback), callback); +} +exports.scandir = scandir; +function scandirSync(path, optionsOrSettings) { + const settings = getSettings(optionsOrSettings); + return sync.read(path, settings); +} +exports.scandirSync = scandirSync; +function getSettings(settingsOrOptions = {}) { + if (settingsOrOptions instanceof settings_1.default) { + return settingsOrOptions; + } + return new settings_1.default(settingsOrOptions); +} + + +/***/ }), + +/***/ 6991: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.readdir = exports.readdirWithFileTypes = exports.read = void 0; +const fsStat = __nccwpck_require__(3824); +const rpl = __nccwpck_require__(9571); +const constants_1 = __nccwpck_require__(1827); +const utils = __nccwpck_require__(6828); +const common = __nccwpck_require__(9142); +function read(directory, settings, callback) { + if (!settings.stats && constants_1.IS_SUPPORT_READDIR_WITH_FILE_TYPES) { + readdirWithFileTypes(directory, settings, callback); + return; + } + readdir(directory, settings, callback); +} +exports.read = read; +function readdirWithFileTypes(directory, settings, callback) { + settings.fs.readdir(directory, { withFileTypes: true }, (readdirError, dirents) => { + if (readdirError !== null) { + callFailureCallback(callback, readdirError); + return; + } + const entries = dirents.map((dirent) => ({ + dirent, + name: dirent.name, + path: common.joinPathSegments(directory, dirent.name, settings.pathSegmentSeparator) + })); + if (!settings.followSymbolicLinks) { + callSuccessCallback(callback, entries); + return; + } + const tasks = entries.map((entry) => makeRplTaskEntry(entry, settings)); + rpl(tasks, (rplError, rplEntries) => { + if (rplError !== null) { + callFailureCallback(callback, rplError); + return; + } + callSuccessCallback(callback, rplEntries); + }); + }); +} +exports.readdirWithFileTypes = readdirWithFileTypes; +function makeRplTaskEntry(entry, settings) { + return (done) => { + if (!entry.dirent.isSymbolicLink()) { + done(null, entry); + return; + } + settings.fs.stat(entry.path, (statError, stats) => { + if (statError !== null) { + if (settings.throwErrorOnBrokenSymbolicLink) { + done(statError); + return; + } + done(null, entry); + return; + } + entry.dirent = utils.fs.createDirentFromStats(entry.name, stats); + done(null, entry); + }); + }; +} +function readdir(directory, settings, callback) { + settings.fs.readdir(directory, (readdirError, names) => { + if (readdirError !== null) { + callFailureCallback(callback, readdirError); + return; + } + const tasks = names.map((name) => { + const path = common.joinPathSegments(directory, name, settings.pathSegmentSeparator); + return (done) => { + fsStat.stat(path, settings.fsStatSettings, (error, stats) => { + if (error !== null) { + done(error); + return; + } + const entry = { + name, + path, + dirent: utils.fs.createDirentFromStats(name, stats) + }; + if (settings.stats) { + entry.stats = stats; + } + done(null, entry); + }); + }; + }); + rpl(tasks, (rplError, entries) => { + if (rplError !== null) { + callFailureCallback(callback, rplError); + return; + } + callSuccessCallback(callback, entries); + }); + }); +} +exports.readdir = readdir; +function callFailureCallback(callback, error) { + callback(error); +} +function callSuccessCallback(callback, result) { + callback(null, result); +} + + +/***/ }), + +/***/ 9142: +/***/ ((__unused_webpack_module, exports) => { + + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.joinPathSegments = void 0; +function joinPathSegments(a, b, separator) { + /** + * The correct handling of cases when the first segment is a root (`/`, `C:/`) or UNC path (`//?/C:/`). + */ + if (a.endsWith(separator)) { + return a + b; + } + return a + separator + b; +} +exports.joinPathSegments = joinPathSegments; + + +/***/ }), + +/***/ 4308: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.readdir = exports.readdirWithFileTypes = exports.read = void 0; +const fsStat = __nccwpck_require__(3824); +const constants_1 = __nccwpck_require__(1827); +const utils = __nccwpck_require__(6828); +const common = __nccwpck_require__(9142); +function read(directory, settings) { + if (!settings.stats && constants_1.IS_SUPPORT_READDIR_WITH_FILE_TYPES) { + return readdirWithFileTypes(directory, settings); + } + return readdir(directory, settings); +} +exports.read = read; +function readdirWithFileTypes(directory, settings) { + const dirents = settings.fs.readdirSync(directory, { withFileTypes: true }); + return dirents.map((dirent) => { + const entry = { + dirent, + name: dirent.name, + path: common.joinPathSegments(directory, dirent.name, settings.pathSegmentSeparator) + }; + if (entry.dirent.isSymbolicLink() && settings.followSymbolicLinks) { + try { + const stats = settings.fs.statSync(entry.path); + entry.dirent = utils.fs.createDirentFromStats(entry.name, stats); + } + catch (error) { + if (settings.throwErrorOnBrokenSymbolicLink) { + throw error; + } + } + } + return entry; + }); +} +exports.readdirWithFileTypes = readdirWithFileTypes; +function readdir(directory, settings) { + const names = settings.fs.readdirSync(directory); + return names.map((name) => { + const entryPath = common.joinPathSegments(directory, name, settings.pathSegmentSeparator); + const stats = fsStat.statSync(entryPath, settings.fsStatSettings); + const entry = { + name, + path: entryPath, + dirent: utils.fs.createDirentFromStats(name, stats) + }; + if (settings.stats) { + entry.stats = stats; + } + return entry; + }); +} +exports.readdir = readdir; + + +/***/ }), + +/***/ 3233: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + + +Object.defineProperty(exports, "__esModule", ({ value: true })); +const path = __nccwpck_require__(6928); +const fsStat = __nccwpck_require__(3824); +const fs = __nccwpck_require__(9492); +class Settings { + constructor(_options = {}) { + this._options = _options; + this.followSymbolicLinks = this._getValue(this._options.followSymbolicLinks, false); + this.fs = fs.createFileSystemAdapter(this._options.fs); + this.pathSegmentSeparator = this._getValue(this._options.pathSegmentSeparator, path.sep); + this.stats = this._getValue(this._options.stats, false); + this.throwErrorOnBrokenSymbolicLink = this._getValue(this._options.throwErrorOnBrokenSymbolicLink, true); + this.fsStatSettings = new fsStat.Settings({ + followSymbolicLink: this.followSymbolicLinks, + fs: this.fs, + throwErrorOnBrokenSymbolicLink: this.throwErrorOnBrokenSymbolicLink + }); + } + _getValue(option, value) { + return option !== null && option !== void 0 ? option : value; + } +} +exports["default"] = Settings; + + +/***/ }), + +/***/ 5221: +/***/ ((__unused_webpack_module, exports) => { + + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.createDirentFromStats = void 0; +class DirentFromStats { + constructor(name, stats) { + this.name = name; + this.isBlockDevice = stats.isBlockDevice.bind(stats); + this.isCharacterDevice = stats.isCharacterDevice.bind(stats); + this.isDirectory = stats.isDirectory.bind(stats); + this.isFIFO = stats.isFIFO.bind(stats); + this.isFile = stats.isFile.bind(stats); + this.isSocket = stats.isSocket.bind(stats); + this.isSymbolicLink = stats.isSymbolicLink.bind(stats); + } +} +function createDirentFromStats(name, stats) { + return new DirentFromStats(name, stats); +} +exports.createDirentFromStats = createDirentFromStats; + + +/***/ }), + +/***/ 6828: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.fs = void 0; +const fs = __nccwpck_require__(5221); +exports.fs = fs; + + +/***/ }), + +/***/ 5994: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.createFileSystemAdapter = exports.FILE_SYSTEM_ADAPTER = void 0; +const fs = __nccwpck_require__(9896); +exports.FILE_SYSTEM_ADAPTER = { + lstat: fs.lstat, + stat: fs.stat, + lstatSync: fs.lstatSync, + statSync: fs.statSync +}; +function createFileSystemAdapter(fsMethods) { + if (fsMethods === undefined) { + return exports.FILE_SYSTEM_ADAPTER; + } + return Object.assign(Object.assign({}, exports.FILE_SYSTEM_ADAPTER), fsMethods); +} +exports.createFileSystemAdapter = createFileSystemAdapter; + + +/***/ }), + +/***/ 3824: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.statSync = exports.stat = exports.Settings = void 0; +const async = __nccwpck_require__(2085); +const sync = __nccwpck_require__(2598); +const settings_1 = __nccwpck_require__(8975); +exports.Settings = settings_1.default; +function stat(path, optionsOrSettingsOrCallback, callback) { + if (typeof optionsOrSettingsOrCallback === 'function') { + async.read(path, getSettings(), optionsOrSettingsOrCallback); + return; + } + async.read(path, getSettings(optionsOrSettingsOrCallback), callback); +} +exports.stat = stat; +function statSync(path, optionsOrSettings) { + const settings = getSettings(optionsOrSettings); + return sync.read(path, settings); +} +exports.statSync = statSync; +function getSettings(settingsOrOptions = {}) { + if (settingsOrOptions instanceof settings_1.default) { + return settingsOrOptions; + } + return new settings_1.default(settingsOrOptions); +} + + +/***/ }), + +/***/ 2085: +/***/ ((__unused_webpack_module, exports) => { + + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.read = void 0; +function read(path, settings, callback) { + settings.fs.lstat(path, (lstatError, lstat) => { + if (lstatError !== null) { + callFailureCallback(callback, lstatError); + return; + } + if (!lstat.isSymbolicLink() || !settings.followSymbolicLink) { + callSuccessCallback(callback, lstat); + return; + } + settings.fs.stat(path, (statError, stat) => { + if (statError !== null) { + if (settings.throwErrorOnBrokenSymbolicLink) { + callFailureCallback(callback, statError); + return; + } + callSuccessCallback(callback, lstat); + return; + } + if (settings.markSymbolicLink) { + stat.isSymbolicLink = () => true; + } + callSuccessCallback(callback, stat); + }); + }); +} +exports.read = read; +function callFailureCallback(callback, error) { + callback(error); +} +function callSuccessCallback(callback, result) { + callback(null, result); +} + + +/***/ }), + +/***/ 2598: +/***/ ((__unused_webpack_module, exports) => { + + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.read = void 0; +function read(path, settings) { + const lstat = settings.fs.lstatSync(path); + if (!lstat.isSymbolicLink() || !settings.followSymbolicLink) { + return lstat; + } + try { + const stat = settings.fs.statSync(path); + if (settings.markSymbolicLink) { + stat.isSymbolicLink = () => true; + } + return stat; + } + catch (error) { + if (!settings.throwErrorOnBrokenSymbolicLink) { + return lstat; + } + throw error; + } +} +exports.read = read; + + +/***/ }), + +/***/ 8975: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + + +Object.defineProperty(exports, "__esModule", ({ value: true })); +const fs = __nccwpck_require__(5994); +class Settings { + constructor(_options = {}) { + this._options = _options; + this.followSymbolicLink = this._getValue(this._options.followSymbolicLink, true); + this.fs = fs.createFileSystemAdapter(this._options.fs); + this.markSymbolicLink = this._getValue(this._options.markSymbolicLink, false); + this.throwErrorOnBrokenSymbolicLink = this._getValue(this._options.throwErrorOnBrokenSymbolicLink, true); + } + _getValue(option, value) { + return option !== null && option !== void 0 ? option : value; + } +} +exports["default"] = Settings; + + +/***/ }), + +/***/ 2552: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Settings = exports.walkStream = exports.walkSync = exports.walk = void 0; +const async_1 = __nccwpck_require__(9997); +const stream_1 = __nccwpck_require__(4697); +const sync_1 = __nccwpck_require__(638); +const settings_1 = __nccwpck_require__(4039); +exports.Settings = settings_1.default; +function walk(directory, optionsOrSettingsOrCallback, callback) { + if (typeof optionsOrSettingsOrCallback === 'function') { + new async_1.default(directory, getSettings()).read(optionsOrSettingsOrCallback); + return; + } + new async_1.default(directory, getSettings(optionsOrSettingsOrCallback)).read(callback); +} +exports.walk = walk; +function walkSync(directory, optionsOrSettings) { + const settings = getSettings(optionsOrSettings); + const provider = new sync_1.default(directory, settings); + return provider.read(); +} +exports.walkSync = walkSync; +function walkStream(directory, optionsOrSettings) { + const settings = getSettings(optionsOrSettings); + const provider = new stream_1.default(directory, settings); + return provider.read(); +} +exports.walkStream = walkStream; +function getSettings(settingsOrOptions = {}) { + if (settingsOrOptions instanceof settings_1.default) { + return settingsOrOptions; + } + return new settings_1.default(settingsOrOptions); +} + + +/***/ }), + +/***/ 9997: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + + +Object.defineProperty(exports, "__esModule", ({ value: true })); +const async_1 = __nccwpck_require__(4387); +class AsyncProvider { + constructor(_root, _settings) { + this._root = _root; + this._settings = _settings; + this._reader = new async_1.default(this._root, this._settings); + this._storage = []; + } + read(callback) { + this._reader.onError((error) => { + callFailureCallback(callback, error); + }); + this._reader.onEntry((entry) => { + this._storage.push(entry); + }); + this._reader.onEnd(() => { + callSuccessCallback(callback, this._storage); + }); + this._reader.read(); + } +} +exports["default"] = AsyncProvider; +function callFailureCallback(callback, error) { + callback(error); +} +function callSuccessCallback(callback, entries) { + callback(null, entries); +} + + +/***/ }), + +/***/ 4697: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + + +Object.defineProperty(exports, "__esModule", ({ value: true })); +const stream_1 = __nccwpck_require__(2203); +const async_1 = __nccwpck_require__(4387); +class StreamProvider { + constructor(_root, _settings) { + this._root = _root; + this._settings = _settings; + this._reader = new async_1.default(this._root, this._settings); + this._stream = new stream_1.Readable({ + objectMode: true, + read: () => { }, + destroy: () => { + if (!this._reader.isDestroyed) { + this._reader.destroy(); + } + } + }); + } + read() { + this._reader.onError((error) => { + this._stream.emit('error', error); + }); + this._reader.onEntry((entry) => { + this._stream.push(entry); + }); + this._reader.onEnd(() => { + this._stream.push(null); + }); + this._reader.read(); + return this._stream; + } +} +exports["default"] = StreamProvider; + + +/***/ }), + +/***/ 638: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + + +Object.defineProperty(exports, "__esModule", ({ value: true })); +const sync_1 = __nccwpck_require__(2800); +class SyncProvider { + constructor(_root, _settings) { + this._root = _root; + this._settings = _settings; + this._reader = new sync_1.default(this._root, this._settings); + } + read() { + return this._reader.read(); + } +} +exports["default"] = SyncProvider; + + +/***/ }), + +/***/ 4387: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + + +Object.defineProperty(exports, "__esModule", ({ value: true })); +const events_1 = __nccwpck_require__(4434); +const fsScandir = __nccwpck_require__(2770); +const fastq = __nccwpck_require__(4187); +const common = __nccwpck_require__(4178); +const reader_1 = __nccwpck_require__(2776); +class AsyncReader extends reader_1.default { + constructor(_root, _settings) { + super(_root, _settings); + this._settings = _settings; + this._scandir = fsScandir.scandir; + this._emitter = new events_1.EventEmitter(); + this._queue = fastq(this._worker.bind(this), this._settings.concurrency); + this._isFatalError = false; + this._isDestroyed = false; + this._queue.drain = () => { + if (!this._isFatalError) { + this._emitter.emit('end'); + } + }; + } + read() { + this._isFatalError = false; + this._isDestroyed = false; + setImmediate(() => { + this._pushToQueue(this._root, this._settings.basePath); + }); + return this._emitter; + } + get isDestroyed() { + return this._isDestroyed; + } + destroy() { + if (this._isDestroyed) { + throw new Error('The reader is already destroyed'); + } + this._isDestroyed = true; + this._queue.killAndDrain(); + } + onEntry(callback) { + this._emitter.on('entry', callback); + } + onError(callback) { + this._emitter.once('error', callback); + } + onEnd(callback) { + this._emitter.once('end', callback); + } + _pushToQueue(directory, base) { + const queueItem = { directory, base }; + this._queue.push(queueItem, (error) => { + if (error !== null) { + this._handleError(error); + } + }); + } + _worker(item, done) { + this._scandir(item.directory, this._settings.fsScandirSettings, (error, entries) => { + if (error !== null) { + done(error, undefined); + return; + } + for (const entry of entries) { + this._handleEntry(entry, item.base); + } + done(null, undefined); + }); + } + _handleError(error) { + if (this._isDestroyed || !common.isFatalError(this._settings, error)) { + return; + } + this._isFatalError = true; + this._isDestroyed = true; + this._emitter.emit('error', error); + } + _handleEntry(entry, base) { + if (this._isDestroyed || this._isFatalError) { + return; + } + const fullpath = entry.path; + if (base !== undefined) { + entry.path = common.joinPathSegments(base, entry.name, this._settings.pathSegmentSeparator); + } + if (common.isAppliedFilter(this._settings.entryFilter, entry)) { + this._emitEntry(entry); + } + if (entry.dirent.isDirectory() && common.isAppliedFilter(this._settings.deepFilter, entry)) { + this._pushToQueue(fullpath, base === undefined ? undefined : entry.path); + } + } + _emitEntry(entry) { + this._emitter.emit('entry', entry); + } +} +exports["default"] = AsyncReader; + + +/***/ }), + +/***/ 4178: +/***/ ((__unused_webpack_module, exports) => { + + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.joinPathSegments = exports.replacePathSegmentSeparator = exports.isAppliedFilter = exports.isFatalError = void 0; +function isFatalError(settings, error) { + if (settings.errorFilter === null) { + return true; + } + return !settings.errorFilter(error); +} +exports.isFatalError = isFatalError; +function isAppliedFilter(filter, value) { + return filter === null || filter(value); +} +exports.isAppliedFilter = isAppliedFilter; +function replacePathSegmentSeparator(filepath, separator) { + return filepath.split(/[/\\]/).join(separator); +} +exports.replacePathSegmentSeparator = replacePathSegmentSeparator; +function joinPathSegments(a, b, separator) { + if (a === '') { + return b; + } + /** + * The correct handling of cases when the first segment is a root (`/`, `C:/`) or UNC path (`//?/C:/`). + */ + if (a.endsWith(separator)) { + return a + b; + } + return a + separator + b; +} +exports.joinPathSegments = joinPathSegments; + + +/***/ }), + +/***/ 2776: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + + +Object.defineProperty(exports, "__esModule", ({ value: true })); +const common = __nccwpck_require__(4178); +class Reader { + constructor(_root, _settings) { + this._root = _root; + this._settings = _settings; + this._root = common.replacePathSegmentSeparator(_root, _settings.pathSegmentSeparator); + } +} +exports["default"] = Reader; + + +/***/ }), + +/***/ 2800: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + + +Object.defineProperty(exports, "__esModule", ({ value: true })); +const fsScandir = __nccwpck_require__(2770); +const common = __nccwpck_require__(4178); +const reader_1 = __nccwpck_require__(2776); +class SyncReader extends reader_1.default { + constructor() { + super(...arguments); + this._scandir = fsScandir.scandirSync; + this._storage = []; + this._queue = new Set(); + } + read() { + this._pushToQueue(this._root, this._settings.basePath); + this._handleQueue(); + return this._storage; + } + _pushToQueue(directory, base) { + this._queue.add({ directory, base }); + } + _handleQueue() { + for (const item of this._queue.values()) { + this._handleDirectory(item.directory, item.base); + } + } + _handleDirectory(directory, base) { + try { + const entries = this._scandir(directory, this._settings.fsScandirSettings); + for (const entry of entries) { + this._handleEntry(entry, base); + } + } + catch (error) { + this._handleError(error); + } + } + _handleError(error) { + if (!common.isFatalError(this._settings, error)) { + return; + } + throw error; + } + _handleEntry(entry, base) { + const fullpath = entry.path; + if (base !== undefined) { + entry.path = common.joinPathSegments(base, entry.name, this._settings.pathSegmentSeparator); + } + if (common.isAppliedFilter(this._settings.entryFilter, entry)) { + this._pushToStorage(entry); + } + if (entry.dirent.isDirectory() && common.isAppliedFilter(this._settings.deepFilter, entry)) { + this._pushToQueue(fullpath, base === undefined ? undefined : entry.path); + } + } + _pushToStorage(entry) { + this._storage.push(entry); + } +} +exports["default"] = SyncReader; + + +/***/ }), + +/***/ 4039: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + + +Object.defineProperty(exports, "__esModule", ({ value: true })); +const path = __nccwpck_require__(6928); +const fsScandir = __nccwpck_require__(2770); +class Settings { + constructor(_options = {}) { + this._options = _options; + this.basePath = this._getValue(this._options.basePath, undefined); + this.concurrency = this._getValue(this._options.concurrency, Number.POSITIVE_INFINITY); + this.deepFilter = this._getValue(this._options.deepFilter, null); + this.entryFilter = this._getValue(this._options.entryFilter, null); + this.errorFilter = this._getValue(this._options.errorFilter, null); + this.pathSegmentSeparator = this._getValue(this._options.pathSegmentSeparator, path.sep); + this.fsScandirSettings = new fsScandir.Settings({ + followSymbolicLinks: this._options.followSymbolicLinks, + fs: this._options.fs, + pathSegmentSeparator: this._options.pathSegmentSeparator, + stats: this._options.stats, + throwErrorOnBrokenSymbolicLink: this._options.throwErrorOnBrokenSymbolicLink + }); + } + _getValue(option, value) { + return option !== null && option !== void 0 ? option : value; + } +} +exports["default"] = Settings; + + +/***/ }), + +/***/ 2613: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("assert"); + +/***/ }), + +/***/ 181: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("buffer"); + +/***/ }), + +/***/ 5317: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("child_process"); + +/***/ }), + +/***/ 4434: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("events"); + +/***/ }), + +/***/ 9896: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("fs"); + +/***/ }), + +/***/ 8611: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("http"); + +/***/ }), + +/***/ 5692: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("https"); + +/***/ }), + +/***/ 9278: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("net"); + +/***/ }), + +/***/ 4589: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:assert"); + +/***/ }), + +/***/ 6698: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:async_hooks"); + +/***/ }), + +/***/ 4573: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:buffer"); + +/***/ }), + +/***/ 7540: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:console"); + +/***/ }), + +/***/ 7598: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:crypto"); + +/***/ }), + +/***/ 3053: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:diagnostics_channel"); + +/***/ }), + +/***/ 610: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:dns"); + +/***/ }), + +/***/ 8474: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:events"); + +/***/ }), + +/***/ 1455: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:fs/promises"); + +/***/ }), + +/***/ 7067: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:http"); + +/***/ }), + +/***/ 2467: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:http2"); + +/***/ }), + +/***/ 7030: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:net"); + +/***/ }), + +/***/ 6760: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:path"); + +/***/ }), + +/***/ 643: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:perf_hooks"); + +/***/ }), + +/***/ 1792: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:querystring"); + +/***/ }), + +/***/ 99: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:sqlite"); + +/***/ }), + +/***/ 7075: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:stream"); + +/***/ }), + +/***/ 7997: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:timers"); + +/***/ }), + +/***/ 1692: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:tls"); + +/***/ }), + +/***/ 3136: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:url"); + +/***/ }), + +/***/ 7975: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:util"); + +/***/ }), + +/***/ 3429: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:util/types"); + +/***/ }), + +/***/ 5919: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:worker_threads"); + +/***/ }), + +/***/ 8522: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:zlib"); + +/***/ }), + +/***/ 857: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("os"); + +/***/ }), + +/***/ 6928: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("path"); + +/***/ }), + +/***/ 2203: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("stream"); + +/***/ }), + +/***/ 3193: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("string_decoder"); + +/***/ }), + +/***/ 4756: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("tls"); + +/***/ }), + +/***/ 9023: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("util"); + +/***/ }), + +/***/ 5232: +/***/ ((module) => { + +var __webpack_unused_export__; + + +const NullObject = function NullObject () { } +NullObject.prototype = Object.create(null) + +/** + * RegExp to match *( ";" parameter ) in RFC 7231 sec 3.1.1.1 + * + * parameter = token "=" ( token / quoted-string ) + * token = 1*tchar + * tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" + * / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~" + * / DIGIT / ALPHA + * ; any VCHAR, except delimiters + * quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE + * qdtext = HTAB / SP / %x21 / %x23-5B / %x5D-7E / obs-text + * obs-text = %x80-FF + * quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text ) + */ +const paramRE = /; *([!#$%&'*+.^\w`|~-]+)=("(?:[\v\u0020\u0021\u0023-\u005b\u005d-\u007e\u0080-\u00ff]|\\[\v\u0020-\u00ff])*"|[!#$%&'*+.^\w`|~-]+) */gu + +/** + * RegExp to match quoted-pair in RFC 7230 sec 3.2.6 + * + * quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text ) + * obs-text = %x80-FF + */ +const quotedPairRE = /\\([\v\u0020-\u00ff])/gu + +/** + * RegExp to match type in RFC 7231 sec 3.1.1.1 + * + * media-type = type "/" subtype + * type = token + * subtype = token + */ +const mediaTypeRE = /^[!#$%&'*+.^\w|~-]+\/[!#$%&'*+.^\w|~-]+$/u + +// default ContentType to prevent repeated object creation +const defaultContentType = { type: '', parameters: new NullObject() } +Object.freeze(defaultContentType.parameters) +Object.freeze(defaultContentType) + +/** + * Parse media type to object. + * + * @param {string|object} header + * @return {Object} + * @public + */ + +function parse (header) { + if (typeof header !== 'string') { + throw new TypeError('argument header is required and must be a string') + } + + let index = header.indexOf(';') + const type = index !== -1 + ? header.slice(0, index).trim() + : header.trim() + + if (mediaTypeRE.test(type) === false) { + throw new TypeError('invalid media type') + } + + const result = { + type: type.toLowerCase(), + parameters: new NullObject() + } + + // parse parameters + if (index === -1) { + return result + } + + let key + let match + let value + + paramRE.lastIndex = index + + while ((match = paramRE.exec(header))) { + if (match.index !== index) { + throw new TypeError('invalid parameter format') + } + + index += match[0].length + key = match[1].toLowerCase() + value = match[2] + + if (value[0] === '"') { + // remove quotes and escapes + value = value + .slice(1, value.length - 1) + + quotedPairRE.test(value) && (value = value.replace(quotedPairRE, '$1')) + } + + result.parameters[key] = value + } + + if (index !== header.length) { + throw new TypeError('invalid parameter format') + } + + return result +} + +function safeParse (header) { + if (typeof header !== 'string') { + return defaultContentType + } + + let index = header.indexOf(';') + const type = index !== -1 + ? header.slice(0, index).trim() + : header.trim() + + if (mediaTypeRE.test(type) === false) { + return defaultContentType + } + + const result = { + type: type.toLowerCase(), + parameters: new NullObject() + } + + // parse parameters + if (index === -1) { + return result + } + + let key + let match + let value + + paramRE.lastIndex = index + + while ((match = paramRE.exec(header))) { + if (match.index !== index) { + return defaultContentType + } + + index += match[0].length + key = match[1].toLowerCase() + value = match[2] + + if (value[0] === '"') { + // remove quotes and escapes + value = value + .slice(1, value.length - 1) + + quotedPairRE.test(value) && (value = value.replace(quotedPairRE, '$1')) + } + + result.parameters[key] = value + } + + if (index !== header.length) { + return defaultContentType } + + return result +} + +__webpack_unused_export__ = { parse, safeParse } +__webpack_unused_export__ = parse +module.exports.xL = safeParse +__webpack_unused_export__ = defaultContentType + + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __nccwpck_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ id: moduleId, +/******/ loaded: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ var threw = true; +/******/ try { +/******/ __webpack_modules__[moduleId](module, module.exports, __nccwpck_require__); +/******/ threw = false; +/******/ } finally { +/******/ if(threw) delete __webpack_module_cache__[moduleId]; +/******/ } +/******/ +/******/ // Flag the module as loaded +/******/ module.loaded = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/compat get default export */ +/******/ (() => { +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __nccwpck_require__.n = (module) => { +/******/ var getter = module && module.__esModule ? +/******/ () => (module['default']) : +/******/ () => (module); +/******/ __nccwpck_require__.d(getter, { a: getter }); +/******/ return getter; +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/create fake namespace object */ +/******/ (() => { +/******/ var getProto = Object.getPrototypeOf ? (obj) => (Object.getPrototypeOf(obj)) : (obj) => (obj.__proto__); +/******/ var leafPrototypes; +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 16: return value when it's Promise-like +/******/ // mode & 8|1: behave like require +/******/ __nccwpck_require__.t = function(value, mode) { +/******/ if(mode & 1) value = this(value); +/******/ if(mode & 8) return value; +/******/ if(typeof value === 'object' && value) { +/******/ if((mode & 4) && value.__esModule) return value; +/******/ if((mode & 16) && typeof value.then === 'function') return value; +/******/ } +/******/ var ns = Object.create(null); +/******/ __nccwpck_require__.r(ns); +/******/ var def = {}; +/******/ leafPrototypes = leafPrototypes || [null, getProto({}), getProto([]), getProto(getProto)]; +/******/ for(var current = mode & 2 && value; typeof current == 'object' && !~leafPrototypes.indexOf(current); current = getProto(current)) { +/******/ Object.getOwnPropertyNames(current).forEach((key) => (def[key] = () => (value[key]))); +/******/ } +/******/ def['default'] = () => (value); +/******/ __nccwpck_require__.d(ns, def); +/******/ return ns; +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/define property getters */ +/******/ (() => { +/******/ // define getter functions for harmony exports +/******/ __nccwpck_require__.d = (exports, definition) => { +/******/ for(var key in definition) { +/******/ if(__nccwpck_require__.o(definition, key) && !__nccwpck_require__.o(exports, key)) { +/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); +/******/ } +/******/ } +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/hasOwnProperty shorthand */ +/******/ (() => { +/******/ __nccwpck_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) +/******/ })(); +/******/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __nccwpck_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/node module decorator */ +/******/ (() => { +/******/ __nccwpck_require__.nmd = (module) => { +/******/ module.paths = []; +/******/ if (!module.children) module.children = []; +/******/ return module; +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/compat */ +/******/ +/******/ if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = new URL('.', import.meta.url).pathname.slice(import.meta.url.match(/^file:\/\/\/\w:/) ? 1 : 0, -1) + "/"; +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; + +// EXTERNAL MODULE: ../../../Library/pnpm/store/v10/links/@/shelljs/0.10.0/cfd77dda0092e058d43297d23efa7c6fae07c73ff7dce2f90ac8ddeb06cca124/node_modules/shelljs/shell.js +var shell = __nccwpck_require__(9834); +var shell_default = /*#__PURE__*/__nccwpck_require__.n(shell); +// EXTERNAL MODULE: ../../../Library/pnpm/store/v10/links/@/semver/7.7.4/43c96ee44548fbe1a157e320193bbd1b85d71efe50396c7a69997dc2c9d81760/node_modules/semver/index.js +var node_modules_semver = __nccwpck_require__(1737); +var semver_default = /*#__PURE__*/__nccwpck_require__.n(node_modules_semver); +// EXTERNAL MODULE: external "os" +var external_os_ = __nccwpck_require__(857); +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@actions/core/3.0.0/3fcceda85205d927f36e6c5a6b901a7f45509694db31f7c9a281d76b3d23161d/node_modules/@actions/core/lib/utils.js +// We use any as a valid input type +/* eslint-disable @typescript-eslint/no-explicit-any */ +/** + * Sanitizes an input into a string so it can be passed into issueCommand safely + * @param input input to sanitize into a string + */ +function utils_toCommandValue(input) { + if (input === null || input === undefined) { + return ''; + } + else if (typeof input === 'string' || input instanceof String) { + return input; + } + return JSON.stringify(input); +} +/** + * + * @param annotationProperties + * @returns The command properties to send with the actual annotation command + * See IssueCommandProperties: https://github.com/actions/runner/blob/main/src/Runner.Worker/ActionCommandManager.cs#L646 + */ +function utils_toCommandProperties(annotationProperties) { + if (!Object.keys(annotationProperties).length) { + return {}; + } + return { + title: annotationProperties.title, + file: annotationProperties.file, + line: annotationProperties.startLine, + endLine: annotationProperties.endLine, + col: annotationProperties.startColumn, + endColumn: annotationProperties.endColumn + }; +} +//# sourceMappingURL=utils.js.map +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@actions/core/3.0.0/3fcceda85205d927f36e6c5a6b901a7f45509694db31f7c9a281d76b3d23161d/node_modules/@actions/core/lib/command.js + + +/** + * Issues a command to the GitHub Actions runner + * + * @param command - The command name to issue + * @param properties - Additional properties for the command (key-value pairs) + * @param message - The message to include with the command + * @remarks + * This function outputs a specially formatted string to stdout that the Actions + * runner interprets as a command. These commands can control workflow behavior, + * set outputs, create annotations, mask values, and more. + * + * Command Format: + * ::name key=value,key=value::message + * + * @example + * ```typescript + * // Issue a warning annotation + * issueCommand('warning', {}, 'This is a warning message'); + * // Output: ::warning::This is a warning message + * + * // Set an environment variable + * issueCommand('set-env', { name: 'MY_VAR' }, 'some value'); + * // Output: ::set-env name=MY_VAR::some value + * + * // Add a secret mask + * issueCommand('add-mask', {}, 'secretValue123'); + * // Output: ::add-mask::secretValue123 + * ``` + * + * @internal + * This is an internal utility function that powers the public API functions + * such as setSecret, warning, error, and exportVariable. + */ +function command_issueCommand(command, properties, message) { + const cmd = new Command(command, properties, message); + process.stdout.write(cmd.toString() + external_os_.EOL); +} +function command_issue(name, message = '') { + command_issueCommand(name, {}, message); +} +const CMD_STRING = '::'; +class Command { + constructor(command, properties, message) { + if (!command) { + command = 'missing.command'; + } + this.command = command; + this.properties = properties; + this.message = message; + } + toString() { + let cmdStr = CMD_STRING + this.command; + if (this.properties && Object.keys(this.properties).length > 0) { + cmdStr += ' '; + let first = true; + for (const key in this.properties) { + if (this.properties.hasOwnProperty(key)) { + const val = this.properties[key]; + if (val) { + if (first) { + first = false; + } + else { + cmdStr += ','; + } + cmdStr += `${key}=${escapeProperty(val)}`; + } + } + } + } + cmdStr += `${CMD_STRING}${escapeData(this.message)}`; + return cmdStr; + } +} +function escapeData(s) { + return utils_toCommandValue(s) + .replace(/%/g, '%25') + .replace(/\r/g, '%0D') + .replace(/\n/g, '%0A'); +} +function escapeProperty(s) { + return utils_toCommandValue(s) + .replace(/%/g, '%25') + .replace(/\r/g, '%0D') + .replace(/\n/g, '%0A') + .replace(/:/g, '%3A') + .replace(/,/g, '%2C'); +} +//# sourceMappingURL=command.js.map +;// CONCATENATED MODULE: external "crypto" +const external_crypto_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("crypto"); +// EXTERNAL MODULE: external "fs" +var external_fs_ = __nccwpck_require__(9896); +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@actions/core/3.0.0/3fcceda85205d927f36e6c5a6b901a7f45509694db31f7c9a281d76b3d23161d/node_modules/@actions/core/lib/file-command.js +// For internal use, subject to change. +// We use any as a valid input type +/* eslint-disable @typescript-eslint/no-explicit-any */ + + + + +function file_command_issueFileCommand(command, message) { + const filePath = process.env[`GITHUB_${command}`]; + if (!filePath) { + throw new Error(`Unable to find environment variable for file command ${command}`); + } + if (!external_fs_.existsSync(filePath)) { + throw new Error(`Missing file at path: ${filePath}`); + } + external_fs_.appendFileSync(filePath, `${utils_toCommandValue(message)}${external_os_.EOL}`, { + encoding: 'utf8' + }); +} +function file_command_prepareKeyValueMessage(key, value) { + const delimiter = `ghadelimiter_${crypto.randomUUID()}`; + const convertedValue = toCommandValue(value); + // These should realistically never happen, but just in case someone finds a + // way to exploit uuid generation let's not allow keys or values that contain + // the delimiter. + if (key.includes(delimiter)) { + throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`); + } + if (convertedValue.includes(delimiter)) { + throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`); + } + return `${key}<<${delimiter}${os.EOL}${convertedValue}${os.EOL}${delimiter}`; +} +//# sourceMappingURL=file-command.js.map +// EXTERNAL MODULE: external "path" +var external_path_ = __nccwpck_require__(6928); +// EXTERNAL MODULE: external "http" +var external_http_ = __nccwpck_require__(8611); +var external_http_namespaceObject = /*#__PURE__*/__nccwpck_require__.t(external_http_, 2); +// EXTERNAL MODULE: external "https" +var external_https_ = __nccwpck_require__(5692); +var external_https_namespaceObject = /*#__PURE__*/__nccwpck_require__.t(external_https_, 2); +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@actions/http-client/4.0.0/01d3d6dbb3f6506778199e0ea46a81616bb33abcd562e788285f40959592eaff/node_modules/@actions/http-client/lib/proxy.js +function getProxyUrl(reqUrl) { + const usingSsl = reqUrl.protocol === 'https:'; + if (checkBypass(reqUrl)) { + return undefined; + } + const proxyVar = (() => { + if (usingSsl) { + return process.env['https_proxy'] || process.env['HTTPS_PROXY']; + } + else { + return process.env['http_proxy'] || process.env['HTTP_PROXY']; + } + })(); + if (proxyVar) { + try { + return new DecodedURL(proxyVar); + } + catch (_a) { + if (!proxyVar.startsWith('http://') && !proxyVar.startsWith('https://')) + return new DecodedURL(`http://${proxyVar}`); + } + } + else { + return undefined; + } +} +function checkBypass(reqUrl) { + if (!reqUrl.hostname) { + return false; + } + const reqHost = reqUrl.hostname; + if (isLoopbackAddress(reqHost)) { + return true; + } + const noProxy = process.env['no_proxy'] || process.env['NO_PROXY'] || ''; + if (!noProxy) { + return false; + } + // Determine the request port + let reqPort; + if (reqUrl.port) { + reqPort = Number(reqUrl.port); + } + else if (reqUrl.protocol === 'http:') { + reqPort = 80; + } + else if (reqUrl.protocol === 'https:') { + reqPort = 443; + } + // Format the request hostname and hostname with port + const upperReqHosts = [reqUrl.hostname.toUpperCase()]; + if (typeof reqPort === 'number') { + upperReqHosts.push(`${upperReqHosts[0]}:${reqPort}`); + } + // Compare request host against noproxy + for (const upperNoProxyItem of noProxy + .split(',') + .map(x => x.trim().toUpperCase()) + .filter(x => x)) { + if (upperNoProxyItem === '*' || + upperReqHosts.some(x => x === upperNoProxyItem || + x.endsWith(`.${upperNoProxyItem}`) || + (upperNoProxyItem.startsWith('.') && + x.endsWith(`${upperNoProxyItem}`)))) { + return true; + } + } + return false; +} +function isLoopbackAddress(host) { + const hostLower = host.toLowerCase(); + return (hostLower === 'localhost' || + hostLower.startsWith('127.') || + hostLower.startsWith('[::1]') || + hostLower.startsWith('[0:0:0:0:0:0:0:1]')); +} +class DecodedURL extends URL { + constructor(url, base) { + super(url, base); + this._decodedUsername = decodeURIComponent(super.username); + this._decodedPassword = decodeURIComponent(super.password); + } + get username() { + return this._decodedUsername; + } + get password() { + return this._decodedPassword; + } +} +//# sourceMappingURL=proxy.js.map +// EXTERNAL MODULE: ../../../Library/pnpm/store/v10/links/@/tunnel/0.0.6/8545ac3dea55c77af3ce7152eaf2c4edb65d40e6d2f08d3f28f24a69132cd002/node_modules/tunnel/index.js +var tunnel = __nccwpck_require__(406); +// EXTERNAL MODULE: ../../../Library/pnpm/store/v10/links/@/undici/6.23.0/0dd78ceeba8aef9d5a21c5f02bcc0a9cbe4b8038019f9aa3cd1335b7e4957330/node_modules/undici/index.js +var undici = __nccwpck_require__(6486); +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@actions/http-client/4.0.0/01d3d6dbb3f6506778199e0ea46a81616bb33abcd562e788285f40959592eaff/node_modules/@actions/http-client/lib/index.js +/* eslint-disable @typescript-eslint/no-explicit-any */ +var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; + + + + + +var HttpCodes; +(function (HttpCodes) { + HttpCodes[HttpCodes["OK"] = 200] = "OK"; + HttpCodes[HttpCodes["MultipleChoices"] = 300] = "MultipleChoices"; + HttpCodes[HttpCodes["MovedPermanently"] = 301] = "MovedPermanently"; + HttpCodes[HttpCodes["ResourceMoved"] = 302] = "ResourceMoved"; + HttpCodes[HttpCodes["SeeOther"] = 303] = "SeeOther"; + HttpCodes[HttpCodes["NotModified"] = 304] = "NotModified"; + HttpCodes[HttpCodes["UseProxy"] = 305] = "UseProxy"; + HttpCodes[HttpCodes["SwitchProxy"] = 306] = "SwitchProxy"; + HttpCodes[HttpCodes["TemporaryRedirect"] = 307] = "TemporaryRedirect"; + HttpCodes[HttpCodes["PermanentRedirect"] = 308] = "PermanentRedirect"; + HttpCodes[HttpCodes["BadRequest"] = 400] = "BadRequest"; + HttpCodes[HttpCodes["Unauthorized"] = 401] = "Unauthorized"; + HttpCodes[HttpCodes["PaymentRequired"] = 402] = "PaymentRequired"; + HttpCodes[HttpCodes["Forbidden"] = 403] = "Forbidden"; + HttpCodes[HttpCodes["NotFound"] = 404] = "NotFound"; + HttpCodes[HttpCodes["MethodNotAllowed"] = 405] = "MethodNotAllowed"; + HttpCodes[HttpCodes["NotAcceptable"] = 406] = "NotAcceptable"; + HttpCodes[HttpCodes["ProxyAuthenticationRequired"] = 407] = "ProxyAuthenticationRequired"; + HttpCodes[HttpCodes["RequestTimeout"] = 408] = "RequestTimeout"; + HttpCodes[HttpCodes["Conflict"] = 409] = "Conflict"; + HttpCodes[HttpCodes["Gone"] = 410] = "Gone"; + HttpCodes[HttpCodes["TooManyRequests"] = 429] = "TooManyRequests"; + HttpCodes[HttpCodes["InternalServerError"] = 500] = "InternalServerError"; + HttpCodes[HttpCodes["NotImplemented"] = 501] = "NotImplemented"; + HttpCodes[HttpCodes["BadGateway"] = 502] = "BadGateway"; + HttpCodes[HttpCodes["ServiceUnavailable"] = 503] = "ServiceUnavailable"; + HttpCodes[HttpCodes["GatewayTimeout"] = 504] = "GatewayTimeout"; +})(HttpCodes || (HttpCodes = {})); +var Headers; +(function (Headers) { + Headers["Accept"] = "accept"; + Headers["ContentType"] = "content-type"; +})(Headers || (Headers = {})); +var MediaTypes; +(function (MediaTypes) { + MediaTypes["ApplicationJson"] = "application/json"; +})(MediaTypes || (MediaTypes = {})); +/** + * Returns the proxy URL, depending upon the supplied url and proxy environment variables. + * @param serverUrl The server URL where the request will be sent. For example, https://api.github.com + */ +function lib_getProxyUrl(serverUrl) { + const proxyUrl = pm.getProxyUrl(new URL(serverUrl)); + return proxyUrl ? proxyUrl.href : ''; +} +const HttpRedirectCodes = [ + HttpCodes.MovedPermanently, + HttpCodes.ResourceMoved, + HttpCodes.SeeOther, + HttpCodes.TemporaryRedirect, + HttpCodes.PermanentRedirect +]; +const HttpResponseRetryCodes = [ + HttpCodes.BadGateway, + HttpCodes.ServiceUnavailable, + HttpCodes.GatewayTimeout +]; +const RetryableHttpVerbs = ['OPTIONS', 'GET', 'DELETE', 'HEAD']; +const ExponentialBackoffCeiling = 10; +const ExponentialBackoffTimeSlice = 5; +class HttpClientError extends Error { + constructor(message, statusCode) { + super(message); + this.name = 'HttpClientError'; + this.statusCode = statusCode; + Object.setPrototypeOf(this, HttpClientError.prototype); + } +} +class HttpClientResponse { + constructor(message) { + this.message = message; + } + readBody() { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () { + let output = Buffer.alloc(0); + this.message.on('data', (chunk) => { + output = Buffer.concat([output, chunk]); + }); + this.message.on('end', () => { + resolve(output.toString()); + }); + })); + }); + } + readBodyBuffer() { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () { + const chunks = []; + this.message.on('data', (chunk) => { + chunks.push(chunk); + }); + this.message.on('end', () => { + resolve(Buffer.concat(chunks)); + }); + })); + }); + } +} +function isHttps(requestUrl) { + const parsedUrl = new URL(requestUrl); + return parsedUrl.protocol === 'https:'; +} +class lib_HttpClient { + constructor(userAgent, handlers, requestOptions) { + this._ignoreSslError = false; + this._allowRedirects = true; + this._allowRedirectDowngrade = false; + this._maxRedirects = 50; + this._allowRetries = false; + this._maxRetries = 1; + this._keepAlive = false; + this._disposed = false; + this.userAgent = this._getUserAgentWithOrchestrationId(userAgent); + this.handlers = handlers || []; + this.requestOptions = requestOptions; + if (requestOptions) { + if (requestOptions.ignoreSslError != null) { + this._ignoreSslError = requestOptions.ignoreSslError; + } + this._socketTimeout = requestOptions.socketTimeout; + if (requestOptions.allowRedirects != null) { + this._allowRedirects = requestOptions.allowRedirects; + } + if (requestOptions.allowRedirectDowngrade != null) { + this._allowRedirectDowngrade = requestOptions.allowRedirectDowngrade; + } + if (requestOptions.maxRedirects != null) { + this._maxRedirects = Math.max(requestOptions.maxRedirects, 0); + } + if (requestOptions.keepAlive != null) { + this._keepAlive = requestOptions.keepAlive; + } + if (requestOptions.allowRetries != null) { + this._allowRetries = requestOptions.allowRetries; + } + if (requestOptions.maxRetries != null) { + this._maxRetries = requestOptions.maxRetries; + } + } + } + options(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('OPTIONS', requestUrl, null, additionalHeaders || {}); + }); + } + get(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('GET', requestUrl, null, additionalHeaders || {}); + }); + } + del(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('DELETE', requestUrl, null, additionalHeaders || {}); + }); + } + post(requestUrl, data, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('POST', requestUrl, data, additionalHeaders || {}); + }); + } + patch(requestUrl, data, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('PATCH', requestUrl, data, additionalHeaders || {}); + }); + } + put(requestUrl, data, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('PUT', requestUrl, data, additionalHeaders || {}); + }); + } + head(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('HEAD', requestUrl, null, additionalHeaders || {}); + }); + } + sendStream(verb, requestUrl, stream, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request(verb, requestUrl, stream, additionalHeaders); + }); + } + /** + * Gets a typed object from an endpoint + * Be aware that not found returns a null. Other errors (4xx, 5xx) reject the promise + */ + getJson(requestUrl_1) { + return __awaiter(this, arguments, void 0, function* (requestUrl, additionalHeaders = {}) { + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + const res = yield this.get(requestUrl, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + postJson(requestUrl_1, obj_1) { + return __awaiter(this, arguments, void 0, function* (requestUrl, obj, additionalHeaders = {}) { + const data = JSON.stringify(obj, null, 2); + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + additionalHeaders[Headers.ContentType] = + this._getExistingOrDefaultContentTypeHeader(additionalHeaders, MediaTypes.ApplicationJson); + const res = yield this.post(requestUrl, data, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + putJson(requestUrl_1, obj_1) { + return __awaiter(this, arguments, void 0, function* (requestUrl, obj, additionalHeaders = {}) { + const data = JSON.stringify(obj, null, 2); + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + additionalHeaders[Headers.ContentType] = + this._getExistingOrDefaultContentTypeHeader(additionalHeaders, MediaTypes.ApplicationJson); + const res = yield this.put(requestUrl, data, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + patchJson(requestUrl_1, obj_1) { + return __awaiter(this, arguments, void 0, function* (requestUrl, obj, additionalHeaders = {}) { + const data = JSON.stringify(obj, null, 2); + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + additionalHeaders[Headers.ContentType] = + this._getExistingOrDefaultContentTypeHeader(additionalHeaders, MediaTypes.ApplicationJson); + const res = yield this.patch(requestUrl, data, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + /** + * Makes a raw http request. + * All other methods such as get, post, patch, and request ultimately call this. + * Prefer get, del, post and patch + */ + request(verb, requestUrl, data, headers) { + return __awaiter(this, void 0, void 0, function* () { + if (this._disposed) { + throw new Error('Client has already been disposed.'); + } + const parsedUrl = new URL(requestUrl); + let info = this._prepareRequest(verb, parsedUrl, headers); + // Only perform retries on reads since writes may not be idempotent. + const maxTries = this._allowRetries && RetryableHttpVerbs.includes(verb) + ? this._maxRetries + 1 + : 1; + let numTries = 0; + let response; + do { + response = yield this.requestRaw(info, data); + // Check if it's an authentication challenge + if (response && + response.message && + response.message.statusCode === HttpCodes.Unauthorized) { + let authenticationHandler; + for (const handler of this.handlers) { + if (handler.canHandleAuthentication(response)) { + authenticationHandler = handler; + break; + } + } + if (authenticationHandler) { + return authenticationHandler.handleAuthentication(this, info, data); + } + else { + // We have received an unauthorized response but have no handlers to handle it. + // Let the response return to the caller. + return response; + } + } + let redirectsRemaining = this._maxRedirects; + while (response.message.statusCode && + HttpRedirectCodes.includes(response.message.statusCode) && + this._allowRedirects && + redirectsRemaining > 0) { + const redirectUrl = response.message.headers['location']; + if (!redirectUrl) { + // if there's no location to redirect to, we won't + break; + } + const parsedRedirectUrl = new URL(redirectUrl); + if (parsedUrl.protocol === 'https:' && + parsedUrl.protocol !== parsedRedirectUrl.protocol && + !this._allowRedirectDowngrade) { + throw new Error('Redirect from HTTPS to HTTP protocol. This downgrade is not allowed for security reasons. If you want to allow this behavior, set the allowRedirectDowngrade option to true.'); + } + // we need to finish reading the response before reassigning response + // which will leak the open socket. + yield response.readBody(); + // strip authorization header if redirected to a different hostname + if (parsedRedirectUrl.hostname !== parsedUrl.hostname) { + for (const header in headers) { + // header names are case insensitive + if (header.toLowerCase() === 'authorization') { + delete headers[header]; + } + } + } + // let's make the request with the new redirectUrl + info = this._prepareRequest(verb, parsedRedirectUrl, headers); + response = yield this.requestRaw(info, data); + redirectsRemaining--; + } + if (!response.message.statusCode || + !HttpResponseRetryCodes.includes(response.message.statusCode)) { + // If not a retry code, return immediately instead of retrying + return response; + } + numTries += 1; + if (numTries < maxTries) { + yield response.readBody(); + yield this._performExponentialBackoff(numTries); + } + } while (numTries < maxTries); + return response; + }); + } + /** + * Needs to be called if keepAlive is set to true in request options. + */ + dispose() { + if (this._agent) { + this._agent.destroy(); + } + this._disposed = true; + } + /** + * Raw request. + * @param info + * @param data + */ + requestRaw(info, data) { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve, reject) => { + function callbackForResult(err, res) { + if (err) { + reject(err); + } + else if (!res) { + // If `err` is not passed, then `res` must be passed. + reject(new Error('Unknown error')); + } + else { + resolve(res); + } + } + this.requestRawWithCallback(info, data, callbackForResult); + }); + }); + } + /** + * Raw request with callback. + * @param info + * @param data + * @param onResult + */ + requestRawWithCallback(info, data, onResult) { + if (typeof data === 'string') { + if (!info.options.headers) { + info.options.headers = {}; + } + info.options.headers['Content-Length'] = Buffer.byteLength(data, 'utf8'); + } + let callbackCalled = false; + function handleResult(err, res) { + if (!callbackCalled) { + callbackCalled = true; + onResult(err, res); + } + } + const req = info.httpModule.request(info.options, (msg) => { + const res = new HttpClientResponse(msg); + handleResult(undefined, res); + }); + let socket; + req.on('socket', sock => { + socket = sock; + }); + // If we ever get disconnected, we want the socket to timeout eventually + req.setTimeout(this._socketTimeout || 3 * 60000, () => { + if (socket) { + socket.end(); + } + handleResult(new Error(`Request timeout: ${info.options.path}`)); + }); + req.on('error', function (err) { + // err has statusCode property + // res should have headers + handleResult(err); + }); + if (data && typeof data === 'string') { + req.write(data, 'utf8'); + } + if (data && typeof data !== 'string') { + data.on('close', function () { + req.end(); + }); + data.pipe(req); + } + else { + req.end(); + } + } + /** + * Gets an http agent. This function is useful when you need an http agent that handles + * routing through a proxy server - depending upon the url and proxy environment variables. + * @param serverUrl The server URL where the request will be sent. For example, https://api.github.com + */ + getAgent(serverUrl) { + const parsedUrl = new URL(serverUrl); + return this._getAgent(parsedUrl); + } + getAgentDispatcher(serverUrl) { + const parsedUrl = new URL(serverUrl); + const proxyUrl = getProxyUrl(parsedUrl); + const useProxy = proxyUrl && proxyUrl.hostname; + if (!useProxy) { + return; + } + return this._getProxyAgentDispatcher(parsedUrl, proxyUrl); + } + _prepareRequest(method, requestUrl, headers) { + const info = {}; + info.parsedUrl = requestUrl; + const usingSsl = info.parsedUrl.protocol === 'https:'; + info.httpModule = usingSsl ? external_https_namespaceObject : external_http_namespaceObject; + const defaultPort = usingSsl ? 443 : 80; + info.options = {}; + info.options.host = info.parsedUrl.hostname; + info.options.port = info.parsedUrl.port + ? parseInt(info.parsedUrl.port) + : defaultPort; + info.options.path = + (info.parsedUrl.pathname || '') + (info.parsedUrl.search || ''); + info.options.method = method; + info.options.headers = this._mergeHeaders(headers); + if (this.userAgent != null) { + info.options.headers['user-agent'] = this.userAgent; + } + info.options.agent = this._getAgent(info.parsedUrl); + // gives handlers an opportunity to participate + if (this.handlers) { + for (const handler of this.handlers) { + handler.prepareRequest(info.options); + } + } + return info; + } + _mergeHeaders(headers) { + if (this.requestOptions && this.requestOptions.headers) { + return Object.assign({}, lowercaseKeys(this.requestOptions.headers), lowercaseKeys(headers || {})); + } + return lowercaseKeys(headers || {}); + } + /** + * Gets an existing header value or returns a default. + * Handles converting number header values to strings since HTTP headers must be strings. + * Note: This returns string | string[] since some headers can have multiple values. + * For headers that must always be a single string (like Content-Type), use the + * specialized _getExistingOrDefaultContentTypeHeader method instead. + */ + _getExistingOrDefaultHeader(additionalHeaders, header, _default) { + let clientHeader; + if (this.requestOptions && this.requestOptions.headers) { + const headerValue = lowercaseKeys(this.requestOptions.headers)[header]; + if (headerValue) { + clientHeader = + typeof headerValue === 'number' ? headerValue.toString() : headerValue; + } + } + const additionalValue = additionalHeaders[header]; + if (additionalValue !== undefined) { + return typeof additionalValue === 'number' + ? additionalValue.toString() + : additionalValue; + } + if (clientHeader !== undefined) { + return clientHeader; + } + return _default; + } + /** + * Specialized version of _getExistingOrDefaultHeader for Content-Type header. + * Always returns a single string (not an array) since Content-Type should be a single value. + * Converts arrays to comma-separated strings and numbers to strings to ensure type safety. + * This was split from _getExistingOrDefaultHeader to provide stricter typing for callers + * that assign the result to places expecting a string (e.g., additionalHeaders[Headers.ContentType]). + */ + _getExistingOrDefaultContentTypeHeader(additionalHeaders, _default) { + let clientHeader; + if (this.requestOptions && this.requestOptions.headers) { + const headerValue = lowercaseKeys(this.requestOptions.headers)[Headers.ContentType]; + if (headerValue) { + if (typeof headerValue === 'number') { + clientHeader = String(headerValue); + } + else if (Array.isArray(headerValue)) { + clientHeader = headerValue.join(', '); + } + else { + clientHeader = headerValue; + } + } + } + const additionalValue = additionalHeaders[Headers.ContentType]; + // Return the first non-undefined value, converting numbers or arrays to strings if necessary + if (additionalValue !== undefined) { + if (typeof additionalValue === 'number') { + return String(additionalValue); + } + else if (Array.isArray(additionalValue)) { + return additionalValue.join(', '); + } + else { + return additionalValue; + } + } + if (clientHeader !== undefined) { + return clientHeader; + } + return _default; + } + _getAgent(parsedUrl) { + let agent; + const proxyUrl = getProxyUrl(parsedUrl); + const useProxy = proxyUrl && proxyUrl.hostname; + if (this._keepAlive && useProxy) { + agent = this._proxyAgent; + } + if (!useProxy) { + agent = this._agent; + } + // if agent is already assigned use that agent. + if (agent) { + return agent; + } + const usingSsl = parsedUrl.protocol === 'https:'; + let maxSockets = 100; + if (this.requestOptions) { + maxSockets = this.requestOptions.maxSockets || external_http_.globalAgent.maxSockets; + } + // This is `useProxy` again, but we need to check `proxyURl` directly for TypeScripts's flow analysis. + if (proxyUrl && proxyUrl.hostname) { + const agentOptions = { + maxSockets, + keepAlive: this._keepAlive, + proxy: Object.assign(Object.assign({}, ((proxyUrl.username || proxyUrl.password) && { + proxyAuth: `${proxyUrl.username}:${proxyUrl.password}` + })), { host: proxyUrl.hostname, port: proxyUrl.port }) + }; + let tunnelAgent; + const overHttps = proxyUrl.protocol === 'https:'; + if (usingSsl) { + tunnelAgent = overHttps ? tunnel.httpsOverHttps : tunnel.httpsOverHttp; + } + else { + tunnelAgent = overHttps ? tunnel.httpOverHttps : tunnel.httpOverHttp; + } + agent = tunnelAgent(agentOptions); + this._proxyAgent = agent; + } + // if tunneling agent isn't assigned create a new agent + if (!agent) { + const options = { keepAlive: this._keepAlive, maxSockets }; + agent = usingSsl ? new external_https_.Agent(options) : new external_http_.Agent(options); + this._agent = agent; + } + if (usingSsl && this._ignoreSslError) { + // we don't want to set NODE_TLS_REJECT_UNAUTHORIZED=0 since that will affect request for entire process + // http.RequestOptions doesn't expose a way to modify RequestOptions.agent.options + // we have to cast it to any and change it directly + agent.options = Object.assign(agent.options || {}, { + rejectUnauthorized: false + }); + } + return agent; + } + _getProxyAgentDispatcher(parsedUrl, proxyUrl) { + let proxyAgent; + if (this._keepAlive) { + proxyAgent = this._proxyAgentDispatcher; + } + // if agent is already assigned use that agent. + if (proxyAgent) { + return proxyAgent; + } + const usingSsl = parsedUrl.protocol === 'https:'; + proxyAgent = new undici/* ProxyAgent */.kT(Object.assign({ uri: proxyUrl.href, pipelining: !this._keepAlive ? 0 : 1 }, ((proxyUrl.username || proxyUrl.password) && { + token: `Basic ${Buffer.from(`${proxyUrl.username}:${proxyUrl.password}`).toString('base64')}` + }))); + this._proxyAgentDispatcher = proxyAgent; + if (usingSsl && this._ignoreSslError) { + // we don't want to set NODE_TLS_REJECT_UNAUTHORIZED=0 since that will affect request for entire process + // http.RequestOptions doesn't expose a way to modify RequestOptions.agent.options + // we have to cast it to any and change it directly + proxyAgent.options = Object.assign(proxyAgent.options.requestTls || {}, { + rejectUnauthorized: false + }); + } + return proxyAgent; + } + _getUserAgentWithOrchestrationId(userAgent) { + const baseUserAgent = userAgent || 'actions/http-client'; + const orchId = process.env['ACTIONS_ORCHESTRATION_ID']; + if (orchId) { + // Sanitize the orchestration ID to ensure it contains only valid characters + // Valid characters: 0-9, a-z, _, -, . + const sanitizedId = orchId.replace(/[^a-z0-9_.-]/gi, '_'); + return `${baseUserAgent} actions_orchestration_id/${sanitizedId}`; + } + return baseUserAgent; + } + _performExponentialBackoff(retryNumber) { + return __awaiter(this, void 0, void 0, function* () { + retryNumber = Math.min(ExponentialBackoffCeiling, retryNumber); + const ms = ExponentialBackoffTimeSlice * Math.pow(2, retryNumber); + return new Promise(resolve => setTimeout(() => resolve(), ms)); + }); + } + _processResponse(res, options) { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () { + const statusCode = res.message.statusCode || 0; + const response = { + statusCode, + result: null, + headers: {} + }; + // not found leads to null obj returned + if (statusCode === HttpCodes.NotFound) { + resolve(response); + } + // get the result from the body + function dateTimeDeserializer(key, value) { + if (typeof value === 'string') { + const a = new Date(value); + if (!isNaN(a.valueOf())) { + return a; + } + } + return value; + } + let obj; + let contents; + try { + contents = yield res.readBody(); + if (contents && contents.length > 0) { + if (options && options.deserializeDates) { + obj = JSON.parse(contents, dateTimeDeserializer); + } + else { + obj = JSON.parse(contents); + } + response.result = obj; + } + response.headers = res.message.headers; + } + catch (err) { + // Invalid resource (contents not json); leaving result obj null + } + // note that 3xx redirects are handled by the http layer. + if (statusCode > 299) { + let msg; + // if exception/error in body, attempt to get better error + if (obj && obj.message) { + msg = obj.message; + } + else if (contents && contents.length > 0) { + // it may be the case that the exception is in the body message as string + msg = contents; + } + else { + msg = `Failed request: (${statusCode})`; + } + const err = new HttpClientError(msg, statusCode); + err.result = response.result; + reject(err); + } + else { + resolve(response); + } + })); + }); + } +} +const lowercaseKeys = (obj) => Object.keys(obj).reduce((c, k) => ((c[k.toLowerCase()] = obj[k]), c), {}); +//# sourceMappingURL=index.js.map +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@actions/http-client/4.0.0/01d3d6dbb3f6506778199e0ea46a81616bb33abcd562e788285f40959592eaff/node_modules/@actions/http-client/lib/auth.js +var auth_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class BasicCredentialHandler { + constructor(username, password) { + this.username = username; + this.password = password; + } + prepareRequest(options) { + if (!options.headers) { + throw Error('The request has no headers'); + } + options.headers['Authorization'] = `Basic ${Buffer.from(`${this.username}:${this.password}`).toString('base64')}`; + } + // This handler cannot handle 401 + canHandleAuthentication() { + return false; + } + handleAuthentication() { + return auth_awaiter(this, void 0, void 0, function* () { + throw new Error('not implemented'); + }); + } +} +class auth_BearerCredentialHandler { + constructor(token) { + this.token = token; + } + // currently implements pre-authorization + // TODO: support preAuth = false where it hooks on 401 + prepareRequest(options) { + if (!options.headers) { + throw Error('The request has no headers'); + } + options.headers['Authorization'] = `Bearer ${this.token}`; + } + // This handler cannot handle 401 + canHandleAuthentication() { + return false; + } + handleAuthentication() { + return auth_awaiter(this, void 0, void 0, function* () { + throw new Error('not implemented'); + }); + } +} +class PersonalAccessTokenCredentialHandler { + constructor(token) { + this.token = token; + } + // currently implements pre-authorization + // TODO: support preAuth = false where it hooks on 401 + prepareRequest(options) { + if (!options.headers) { + throw Error('The request has no headers'); + } + options.headers['Authorization'] = `Basic ${Buffer.from(`PAT:${this.token}`).toString('base64')}`; + } + // This handler cannot handle 401 + canHandleAuthentication() { + return false; + } + handleAuthentication() { + return auth_awaiter(this, void 0, void 0, function* () { + throw new Error('not implemented'); + }); + } +} +//# sourceMappingURL=auth.js.map +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@actions/core/3.0.0/3fcceda85205d927f36e6c5a6b901a7f45509694db31f7c9a281d76b3d23161d/node_modules/@actions/core/lib/oidc-utils.js +var oidc_utils_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; + + + +class oidc_utils_OidcClient { + static createHttpClient(allowRetry = true, maxRetry = 10) { + const requestOptions = { + allowRetries: allowRetry, + maxRetries: maxRetry + }; + return new HttpClient('actions/oidc-client', [new BearerCredentialHandler(oidc_utils_OidcClient.getRequestToken())], requestOptions); + } + static getRequestToken() { + const token = process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN']; + if (!token) { + throw new Error('Unable to get ACTIONS_ID_TOKEN_REQUEST_TOKEN env variable'); + } + return token; + } + static getIDTokenUrl() { + const runtimeUrl = process.env['ACTIONS_ID_TOKEN_REQUEST_URL']; + if (!runtimeUrl) { + throw new Error('Unable to get ACTIONS_ID_TOKEN_REQUEST_URL env variable'); + } + return runtimeUrl; + } + static getCall(id_token_url) { + return oidc_utils_awaiter(this, void 0, void 0, function* () { + var _a; + const httpclient = oidc_utils_OidcClient.createHttpClient(); + const res = yield httpclient + .getJson(id_token_url) + .catch(error => { + throw new Error(`Failed to get ID Token. \n + Error Code : ${error.statusCode}\n + Error Message: ${error.message}`); + }); + const id_token = (_a = res.result) === null || _a === void 0 ? void 0 : _a.value; + if (!id_token) { + throw new Error('Response json body do not have ID Token field'); + } + return id_token; + }); + } + static getIDToken(audience) { + return oidc_utils_awaiter(this, void 0, void 0, function* () { + try { + // New ID Token is requested from action service + let id_token_url = oidc_utils_OidcClient.getIDTokenUrl(); + if (audience) { + const encodedAudience = encodeURIComponent(audience); + id_token_url = `${id_token_url}&audience=${encodedAudience}`; + } + debug(`ID token url is ${id_token_url}`); + const id_token = yield oidc_utils_OidcClient.getCall(id_token_url); + setSecret(id_token); + return id_token; + } + catch (error) { + throw new Error(`Error message: ${error.message}`); + } + }); + } +} +//# sourceMappingURL=oidc-utils.js.map +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@actions/core/3.0.0/3fcceda85205d927f36e6c5a6b901a7f45509694db31f7c9a281d76b3d23161d/node_modules/@actions/core/lib/summary.js +var summary_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; + + +const { access, appendFile, writeFile } = external_fs_.promises; +const SUMMARY_ENV_VAR = 'GITHUB_STEP_SUMMARY'; +const SUMMARY_DOCS_URL = 'https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary'; +class Summary { + constructor() { + this._buffer = ''; + } + /** + * Finds the summary file path from the environment, rejects if env var is not found or file does not exist + * Also checks r/w permissions. + * + * @returns step summary file path + */ + filePath() { + return summary_awaiter(this, void 0, void 0, function* () { + if (this._filePath) { + return this._filePath; + } + const pathFromEnv = process.env[SUMMARY_ENV_VAR]; + if (!pathFromEnv) { + throw new Error(`Unable to find environment variable for $${SUMMARY_ENV_VAR}. Check if your runtime environment supports job summaries.`); + } + try { + yield access(pathFromEnv, external_fs_.constants.R_OK | external_fs_.constants.W_OK); + } + catch (_a) { + throw new Error(`Unable to access summary file: '${pathFromEnv}'. Check if the file has correct read/write permissions.`); + } + this._filePath = pathFromEnv; + return this._filePath; + }); + } + /** + * Wraps content in an HTML tag, adding any HTML attributes + * + * @param {string} tag HTML tag to wrap + * @param {string | null} content content within the tag + * @param {[attribute: string]: string} attrs key-value list of HTML attributes to add + * + * @returns {string} content wrapped in HTML element + */ + wrap(tag, content, attrs = {}) { + const htmlAttrs = Object.entries(attrs) + .map(([key, value]) => ` ${key}="${value}"`) + .join(''); + if (!content) { + return `<${tag}${htmlAttrs}>`; + } + return `<${tag}${htmlAttrs}>${content}`; + } + /** + * Writes text in the buffer to the summary buffer file and empties buffer. Will append by default. + * + * @param {SummaryWriteOptions} [options] (optional) options for write operation + * + * @returns {Promise} summary instance + */ + write(options) { + return summary_awaiter(this, void 0, void 0, function* () { + const overwrite = !!(options === null || options === void 0 ? void 0 : options.overwrite); + const filePath = yield this.filePath(); + const writeFunc = overwrite ? writeFile : appendFile; + yield writeFunc(filePath, this._buffer, { encoding: 'utf8' }); + return this.emptyBuffer(); + }); + } + /** + * Clears the summary buffer and wipes the summary file + * + * @returns {Summary} summary instance + */ + clear() { + return summary_awaiter(this, void 0, void 0, function* () { + return this.emptyBuffer().write({ overwrite: true }); + }); + } + /** + * Returns the current summary buffer as a string + * + * @returns {string} string of summary buffer + */ + stringify() { + return this._buffer; + } + /** + * If the summary buffer is empty + * + * @returns {boolen} true if the buffer is empty + */ + isEmptyBuffer() { + return this._buffer.length === 0; + } + /** + * Resets the summary buffer without writing to summary file + * + * @returns {Summary} summary instance + */ + emptyBuffer() { + this._buffer = ''; + return this; + } + /** + * Adds raw text to the summary buffer + * + * @param {string} text content to add + * @param {boolean} [addEOL=false] (optional) append an EOL to the raw text (default: false) + * + * @returns {Summary} summary instance + */ + addRaw(text, addEOL = false) { + this._buffer += text; + return addEOL ? this.addEOL() : this; + } + /** + * Adds the operating system-specific end-of-line marker to the buffer + * + * @returns {Summary} summary instance + */ + addEOL() { + return this.addRaw(external_os_.EOL); + } + /** + * Adds an HTML codeblock to the summary buffer + * + * @param {string} code content to render within fenced code block + * @param {string} lang (optional) language to syntax highlight code + * + * @returns {Summary} summary instance + */ + addCodeBlock(code, lang) { + const attrs = Object.assign({}, (lang && { lang })); + const element = this.wrap('pre', this.wrap('code', code), attrs); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML list to the summary buffer + * + * @param {string[]} items list of items to render + * @param {boolean} [ordered=false] (optional) if the rendered list should be ordered or not (default: false) + * + * @returns {Summary} summary instance + */ + addList(items, ordered = false) { + const tag = ordered ? 'ol' : 'ul'; + const listItems = items.map(item => this.wrap('li', item)).join(''); + const element = this.wrap(tag, listItems); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML table to the summary buffer + * + * @param {SummaryTableCell[]} rows table rows + * + * @returns {Summary} summary instance + */ + addTable(rows) { + const tableBody = rows + .map(row => { + const cells = row + .map(cell => { + if (typeof cell === 'string') { + return this.wrap('td', cell); + } + const { header, data, colspan, rowspan } = cell; + const tag = header ? 'th' : 'td'; + const attrs = Object.assign(Object.assign({}, (colspan && { colspan })), (rowspan && { rowspan })); + return this.wrap(tag, data, attrs); + }) + .join(''); + return this.wrap('tr', cells); + }) + .join(''); + const element = this.wrap('table', tableBody); + return this.addRaw(element).addEOL(); + } + /** + * Adds a collapsable HTML details element to the summary buffer + * + * @param {string} label text for the closed state + * @param {string} content collapsable content + * + * @returns {Summary} summary instance + */ + addDetails(label, content) { + const element = this.wrap('details', this.wrap('summary', label) + content); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML image tag to the summary buffer + * + * @param {string} src path to the image you to embed + * @param {string} alt text description of the image + * @param {SummaryImageOptions} options (optional) addition image attributes + * + * @returns {Summary} summary instance + */ + addImage(src, alt, options) { + const { width, height } = options || {}; + const attrs = Object.assign(Object.assign({}, (width && { width })), (height && { height })); + const element = this.wrap('img', null, Object.assign({ src, alt }, attrs)); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML section heading element + * + * @param {string} text heading text + * @param {number | string} [level=1] (optional) the heading level, default: 1 + * + * @returns {Summary} summary instance + */ + addHeading(text, level) { + const tag = `h${level}`; + const allowedTag = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'].includes(tag) + ? tag + : 'h1'; + const element = this.wrap(allowedTag, text); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML thematic break (
) to the summary buffer + * + * @returns {Summary} summary instance + */ + addSeparator() { + const element = this.wrap('hr', null); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML line break (
) to the summary buffer + * + * @returns {Summary} summary instance + */ + addBreak() { + const element = this.wrap('br', null); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML blockquote to the summary buffer + * + * @param {string} text quote text + * @param {string} cite (optional) citation url + * + * @returns {Summary} summary instance + */ + addQuote(text, cite) { + const attrs = Object.assign({}, (cite && { cite })); + const element = this.wrap('blockquote', text, attrs); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML anchor tag to the summary buffer + * + * @param {string} text link text/content + * @param {string} href hyperlink + * + * @returns {Summary} summary instance + */ + addLink(text, href) { + const element = this.wrap('a', text, { href }); + return this.addRaw(element).addEOL(); + } +} +const _summary = new Summary(); +/** + * @deprecated use `core.summary` + */ +const markdownSummary = (/* unused pure expression or super */ null && (_summary)); +const summary = (/* unused pure expression or super */ null && (_summary)); +//# sourceMappingURL=summary.js.map +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@actions/core/3.0.0/3fcceda85205d927f36e6c5a6b901a7f45509694db31f7c9a281d76b3d23161d/node_modules/@actions/core/lib/path-utils.js + +/** + * toPosixPath converts the given path to the posix form. On Windows, \\ will be + * replaced with /. + * + * @param pth. Path to transform. + * @return string Posix path. + */ +function toPosixPath(pth) { + return pth.replace(/[\\]/g, '/'); +} +/** + * toWin32Path converts the given path to the win32 form. On Linux, / will be + * replaced with \\. + * + * @param pth. Path to transform. + * @return string Win32 path. + */ +function toWin32Path(pth) { + return pth.replace(/[/]/g, '\\'); +} +/** + * toPlatformPath converts the given path to a platform-specific path. It does + * this by replacing instances of / and \ with the platform-specific path + * separator. + * + * @param pth The path to platformize. + * @return string The platform-specific path. + */ +function toPlatformPath(pth) { + return pth.replace(/[/\\]/g, path.sep); +} +//# sourceMappingURL=path-utils.js.map +// EXTERNAL MODULE: external "string_decoder" +var external_string_decoder_ = __nccwpck_require__(3193); +// EXTERNAL MODULE: external "events" +var external_events_ = __nccwpck_require__(4434); +// EXTERNAL MODULE: external "child_process" +var external_child_process_ = __nccwpck_require__(5317); +// EXTERNAL MODULE: external "assert" +var external_assert_ = __nccwpck_require__(2613); +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@actions/io/3.0.2/dc304d1665f651833e0b47cd9de52e0109bf6a13f48e889eb49a546875e95c7f/node_modules/@actions/io/lib/io-util.js +var io_util_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; + + +const { chmod, copyFile, lstat, mkdir, open: io_util_open, readdir, rename, rm, rmdir, stat, symlink, unlink } = external_fs_.promises; +// export const {open} = 'fs' +const IS_WINDOWS = process.platform === 'win32'; +/** + * Custom implementation of readlink to ensure Windows junctions + * maintain trailing backslash for backward compatibility with Node.js < 24 + * + * In Node.js 20, Windows junctions (directory symlinks) always returned paths + * with trailing backslashes. Node.js 24 removed this behavior, which breaks + * code that relied on this format for path operations. + * + * This implementation restores the Node 20 behavior by adding a trailing + * backslash to all junction results on Windows. + */ +function readlink(fsPath) { + return io_util_awaiter(this, void 0, void 0, function* () { + const result = yield external_fs_.promises.readlink(fsPath); + // On Windows, restore Node 20 behavior: add trailing backslash to all results + // since junctions on Windows are always directory links + if (IS_WINDOWS && !result.endsWith('\\')) { + return `${result}\\`; + } + return result; + }); +} +// See https://github.com/nodejs/node/blob/d0153aee367422d0858105abec186da4dff0a0c5/deps/uv/include/uv/win.h#L691 +const UV_FS_O_EXLOCK = 0x10000000; +const READONLY = external_fs_.constants.O_RDONLY; +function exists(fsPath) { + return io_util_awaiter(this, void 0, void 0, function* () { + try { + yield stat(fsPath); + } + catch (err) { + if (err.code === 'ENOENT') { + return false; + } + throw err; + } + return true; + }); +} +function isDirectory(fsPath_1) { + return io_util_awaiter(this, arguments, void 0, function* (fsPath, useStat = false) { + const stats = useStat ? yield stat(fsPath) : yield lstat(fsPath); + return stats.isDirectory(); + }); +} +/** + * On OSX/Linux, true if path starts with '/'. On Windows, true for paths like: + * \, \hello, \\hello\share, C:, and C:\hello (and corresponding alternate separator cases). + */ +function isRooted(p) { + p = normalizeSeparators(p); + if (!p) { + throw new Error('isRooted() parameter "p" cannot be empty'); + } + if (IS_WINDOWS) { + return (p.startsWith('\\') || /^[A-Z]:/i.test(p) // e.g. \ or \hello or \\hello + ); // e.g. C: or C:\hello + } + return p.startsWith('/'); +} +/** + * Best effort attempt to determine whether a file exists and is executable. + * @param filePath file path to check + * @param extensions additional file extensions to try + * @return if file exists and is executable, returns the file path. otherwise empty string. + */ +function tryGetExecutablePath(filePath, extensions) { + return io_util_awaiter(this, void 0, void 0, function* () { + let stats = undefined; + try { + // test file exists + stats = yield stat(filePath); + } + catch (err) { + if (err.code !== 'ENOENT') { + // eslint-disable-next-line no-console + console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`); + } + } + if (stats && stats.isFile()) { + if (IS_WINDOWS) { + // on Windows, test for valid extension + const upperExt = external_path_.extname(filePath).toUpperCase(); + if (extensions.some(validExt => validExt.toUpperCase() === upperExt)) { + return filePath; + } + } + else { + if (isUnixExecutable(stats)) { + return filePath; + } + } + } + // try each extension + const originalFilePath = filePath; + for (const extension of extensions) { + filePath = originalFilePath + extension; + stats = undefined; + try { + stats = yield stat(filePath); + } + catch (err) { + if (err.code !== 'ENOENT') { + // eslint-disable-next-line no-console + console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`); + } + } + if (stats && stats.isFile()) { + if (IS_WINDOWS) { + // preserve the case of the actual file (since an extension was appended) + try { + const directory = external_path_.dirname(filePath); + const upperName = external_path_.basename(filePath).toUpperCase(); + for (const actualName of yield readdir(directory)) { + if (upperName === actualName.toUpperCase()) { + filePath = external_path_.join(directory, actualName); + break; + } + } + } + catch (err) { + // eslint-disable-next-line no-console + console.log(`Unexpected error attempting to determine the actual case of the file '${filePath}': ${err}`); + } + return filePath; + } + else { + if (isUnixExecutable(stats)) { + return filePath; + } + } + } + } + return ''; + }); +} +function normalizeSeparators(p) { + p = p || ''; + if (IS_WINDOWS) { + // convert slashes on Windows + p = p.replace(/\//g, '\\'); + // remove redundant slashes + return p.replace(/\\\\+/g, '\\'); + } + // remove redundant slashes + return p.replace(/\/\/+/g, '/'); +} +// on Mac/Linux, test the execute bit +// R W X R W X R W X +// 256 128 64 32 16 8 4 2 1 +function isUnixExecutable(stats) { + return ((stats.mode & 1) > 0 || + ((stats.mode & 8) > 0 && + process.getgid !== undefined && + stats.gid === process.getgid()) || + ((stats.mode & 64) > 0 && + process.getuid !== undefined && + stats.uid === process.getuid())); +} +// Get the path of cmd.exe in windows +function getCmdPath() { + var _a; + return (_a = process.env['COMSPEC']) !== null && _a !== void 0 ? _a : `cmd.exe`; +} +//# sourceMappingURL=io-util.js.map +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@actions/io/3.0.2/dc304d1665f651833e0b47cd9de52e0109bf6a13f48e889eb49a546875e95c7f/node_modules/@actions/io/lib/io.js +var io_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; + + + +/** + * Copies a file or folder. + * Based off of shelljs - https://github.com/shelljs/shelljs/blob/9237f66c52e5daa40458f94f9565e18e8132f5a6/src/cp.js + * + * @param source source path + * @param dest destination path + * @param options optional. See CopyOptions. + */ +function io_cp(source_1, dest_1) { + return io_awaiter(this, arguments, void 0, function* (source, dest, options = {}) { + const { force, recursive, copySourceDirectory } = readCopyOptions(options); + const destStat = (yield exists(dest)) ? yield stat(dest) : null; + // Dest is an existing file, but not forcing + if (destStat && destStat.isFile() && !force) { + return; + } + // If dest is an existing directory, should copy inside. + const newDest = destStat && destStat.isDirectory() && copySourceDirectory + ? external_path_.join(dest, external_path_.basename(source)) + : dest; + if (!(yield exists(source))) { + throw new Error(`no such file or directory: ${source}`); + } + const sourceStat = yield stat(source); + if (sourceStat.isDirectory()) { + if (!recursive) { + throw new Error(`Failed to copy. ${source} is a directory, but tried to copy without recursive flag.`); + } + else { + yield cpDirRecursive(source, newDest, 0, force); + } + } + else { + if (external_path_.relative(source, newDest) === '') { + // a file cannot be copied to itself + throw new Error(`'${newDest}' and '${source}' are the same file`); + } + yield io_copyFile(source, newDest, force); + } + }); +} +/** + * Moves a path. + * + * @param source source path + * @param dest destination path + * @param options optional. See MoveOptions. + */ +function mv(source_1, dest_1) { + return io_awaiter(this, arguments, void 0, function* (source, dest, options = {}) { + if (yield ioUtil.exists(dest)) { + let destExists = true; + if (yield ioUtil.isDirectory(dest)) { + // If dest is directory copy src into dest + dest = path.join(dest, path.basename(source)); + destExists = yield ioUtil.exists(dest); + } + if (destExists) { + if (options.force == null || options.force) { + yield rmRF(dest); + } + else { + throw new Error('Destination already exists'); + } + } + } + yield mkdirP(path.dirname(dest)); + yield ioUtil.rename(source, dest); + }); +} +/** + * Remove a path recursively with force + * + * @param inputPath path to remove + */ +function rmRF(inputPath) { + return io_awaiter(this, void 0, void 0, function* () { + if (IS_WINDOWS) { + // Check for invalid characters + // https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file + if (/[*"<>|]/.test(inputPath)) { + throw new Error('File path must not contain `*`, `"`, `<`, `>` or `|` on Windows'); + } + } + try { + // note if path does not exist, error is silent + yield rm(inputPath, { + force: true, + maxRetries: 3, + recursive: true, + retryDelay: 300 + }); + } + catch (err) { + throw new Error(`File was unable to be removed ${err}`); + } + }); +} +/** + * Make a directory. Creates the full path with folders in between + * Will throw if it fails + * + * @param fsPath path to create + * @returns Promise + */ +function mkdirP(fsPath) { + return io_awaiter(this, void 0, void 0, function* () { + (0,external_assert_.ok)(fsPath, 'a path argument must be provided'); + yield mkdir(fsPath, { recursive: true }); + }); +} +/** + * Returns path of a tool had the tool actually been invoked. Resolves via paths. + * If you check and the tool does not exist, it will throw. + * + * @param tool name of the tool + * @param check whether to check if tool exists + * @returns Promise path to tool + */ +function which(tool, check) { + return io_awaiter(this, void 0, void 0, function* () { + if (!tool) { + throw new Error("parameter 'tool' is required"); + } + // recursive when check=true + if (check) { + const result = yield which(tool, false); + if (!result) { + if (IS_WINDOWS) { + throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also verify the file has a valid extension for an executable file.`); + } + else { + throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also check the file mode to verify the file is executable.`); + } + } + return result; + } + const matches = yield findInPath(tool); + if (matches && matches.length > 0) { + return matches[0]; + } + return ''; + }); +} +/** + * Returns a list of all occurrences of the given tool on the system path. + * + * @returns Promise the paths of the tool + */ +function findInPath(tool) { + return io_awaiter(this, void 0, void 0, function* () { + if (!tool) { + throw new Error("parameter 'tool' is required"); + } + // build the list of extensions to try + const extensions = []; + if (IS_WINDOWS && process.env['PATHEXT']) { + for (const extension of process.env['PATHEXT'].split(external_path_.delimiter)) { + if (extension) { + extensions.push(extension); + } + } + } + // if it's rooted, return it if exists. otherwise return empty. + if (isRooted(tool)) { + const filePath = yield tryGetExecutablePath(tool, extensions); + if (filePath) { + return [filePath]; + } + return []; + } + // if any path separators, return empty + if (tool.includes(external_path_.sep)) { + return []; + } + // build the list of directories + // + // Note, technically "where" checks the current directory on Windows. From a toolkit perspective, + // it feels like we should not do this. Checking the current directory seems like more of a use + // case of a shell, and the which() function exposed by the toolkit should strive for consistency + // across platforms. + const directories = []; + if (process.env.PATH) { + for (const p of process.env.PATH.split(external_path_.delimiter)) { + if (p) { + directories.push(p); + } + } + } + // find all matches + const matches = []; + for (const directory of directories) { + const filePath = yield tryGetExecutablePath(external_path_.join(directory, tool), extensions); + if (filePath) { + matches.push(filePath); + } + } + return matches; + }); +} +function readCopyOptions(options) { + const force = options.force == null ? true : options.force; + const recursive = Boolean(options.recursive); + const copySourceDirectory = options.copySourceDirectory == null + ? true + : Boolean(options.copySourceDirectory); + return { force, recursive, copySourceDirectory }; +} +function cpDirRecursive(sourceDir, destDir, currentDepth, force) { + return io_awaiter(this, void 0, void 0, function* () { + // Ensure there is not a run away recursive copy + if (currentDepth >= 255) + return; + currentDepth++; + yield mkdirP(destDir); + const files = yield readdir(sourceDir); + for (const fileName of files) { + const srcFile = `${sourceDir}/${fileName}`; + const destFile = `${destDir}/${fileName}`; + const srcFileStat = yield lstat(srcFile); + if (srcFileStat.isDirectory()) { + // Recurse + yield cpDirRecursive(srcFile, destFile, currentDepth, force); + } + else { + yield io_copyFile(srcFile, destFile, force); + } + } + // Change the mode for the newly created directory + yield chmod(destDir, (yield stat(sourceDir)).mode); + }); +} +// Buffered file copy +function io_copyFile(srcFile, destFile, force) { + return io_awaiter(this, void 0, void 0, function* () { + if ((yield lstat(srcFile)).isSymbolicLink()) { + // unlink/re-link it + try { + yield lstat(destFile); + yield unlink(destFile); + } + catch (e) { + // Try to override file permission + if (e.code === 'EPERM') { + yield chmod(destFile, '0666'); + yield unlink(destFile); + } + // other errors = it doesn't exist, no work to do + } + // Copy over symlink + const symlinkFull = yield readlink(srcFile); + yield symlink(symlinkFull, destFile, IS_WINDOWS ? 'junction' : null); + } + else if (!(yield exists(destFile)) || force) { + yield copyFile(srcFile, destFile); + } + }); +} +//# sourceMappingURL=io.js.map +;// CONCATENATED MODULE: external "timers" +const external_timers_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("timers"); +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@actions/exec/3.0.0/530e2f35971783f1666d0f5e5823d8fd663ed254c8ebbee4acd04b167b0622b6/node_modules/@actions/exec/lib/toolrunner.js +var toolrunner_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; + + + + + + + +/* eslint-disable @typescript-eslint/unbound-method */ +const toolrunner_IS_WINDOWS = process.platform === 'win32'; +/* + * Class for running command line tools. Handles quoting and arg parsing in a platform agnostic way. + */ +class ToolRunner extends external_events_.EventEmitter { + constructor(toolPath, args, options) { + super(); + if (!toolPath) { + throw new Error("Parameter 'toolPath' cannot be null or empty."); + } + this.toolPath = toolPath; + this.args = args || []; + this.options = options || {}; + } + _debug(message) { + if (this.options.listeners && this.options.listeners.debug) { + this.options.listeners.debug(message); + } + } + _getCommandString(options, noPrefix) { + const toolPath = this._getSpawnFileName(); + const args = this._getSpawnArgs(options); + let cmd = noPrefix ? '' : '[command]'; // omit prefix when piped to a second tool + if (toolrunner_IS_WINDOWS) { + // Windows + cmd file + if (this._isCmdFile()) { + cmd += toolPath; + for (const a of args) { + cmd += ` ${a}`; + } + } + // Windows + verbatim + else if (options.windowsVerbatimArguments) { + cmd += `"${toolPath}"`; + for (const a of args) { + cmd += ` ${a}`; + } + } + // Windows (regular) + else { + cmd += this._windowsQuoteCmdArg(toolPath); + for (const a of args) { + cmd += ` ${this._windowsQuoteCmdArg(a)}`; + } + } + } + else { + // OSX/Linux - this can likely be improved with some form of quoting. + // creating processes on Unix is fundamentally different than Windows. + // on Unix, execvp() takes an arg array. + cmd += toolPath; + for (const a of args) { + cmd += ` ${a}`; + } + } + return cmd; + } + _processLineBuffer(data, strBuffer, onLine) { + try { + let s = strBuffer + data.toString(); + let n = s.indexOf(external_os_.EOL); + while (n > -1) { + const line = s.substring(0, n); + onLine(line); + // the rest of the string ... + s = s.substring(n + external_os_.EOL.length); + n = s.indexOf(external_os_.EOL); + } + return s; + } + catch (err) { + // streaming lines to console is best effort. Don't fail a build. + this._debug(`error processing line. Failed with error ${err}`); + return ''; + } + } + _getSpawnFileName() { + if (toolrunner_IS_WINDOWS) { + if (this._isCmdFile()) { + return process.env['COMSPEC'] || 'cmd.exe'; + } + } + return this.toolPath; + } + _getSpawnArgs(options) { + if (toolrunner_IS_WINDOWS) { + if (this._isCmdFile()) { + let argline = `/D /S /C "${this._windowsQuoteCmdArg(this.toolPath)}`; + for (const a of this.args) { + argline += ' '; + argline += options.windowsVerbatimArguments + ? a + : this._windowsQuoteCmdArg(a); + } + argline += '"'; + return [argline]; + } + } + return this.args; + } + _endsWith(str, end) { + return str.endsWith(end); + } + _isCmdFile() { + const upperToolPath = this.toolPath.toUpperCase(); + return (this._endsWith(upperToolPath, '.CMD') || + this._endsWith(upperToolPath, '.BAT')); + } + _windowsQuoteCmdArg(arg) { + // for .exe, apply the normal quoting rules that libuv applies + if (!this._isCmdFile()) { + return this._uvQuoteCmdArg(arg); + } + // otherwise apply quoting rules specific to the cmd.exe command line parser. + // the libuv rules are generic and are not designed specifically for cmd.exe + // command line parser. + // + // for a detailed description of the cmd.exe command line parser, refer to + // http://stackoverflow.com/questions/4094699/how-does-the-windows-command-interpreter-cmd-exe-parse-scripts/7970912#7970912 + // need quotes for empty arg + if (!arg) { + return '""'; + } + // determine whether the arg needs to be quoted + const cmdSpecialChars = [ + ' ', + '\t', + '&', + '(', + ')', + '[', + ']', + '{', + '}', + '^', + '=', + ';', + '!', + "'", + '+', + ',', + '`', + '~', + '|', + '<', + '>', + '"' + ]; + let needsQuotes = false; + for (const char of arg) { + if (cmdSpecialChars.some(x => x === char)) { + needsQuotes = true; + break; + } + } + // short-circuit if quotes not needed + if (!needsQuotes) { + return arg; + } + // the following quoting rules are very similar to the rules that by libuv applies. + // + // 1) wrap the string in quotes + // + // 2) double-up quotes - i.e. " => "" + // + // this is different from the libuv quoting rules. libuv replaces " with \", which unfortunately + // doesn't work well with a cmd.exe command line. + // + // note, replacing " with "" also works well if the arg is passed to a downstream .NET console app. + // for example, the command line: + // foo.exe "myarg:""my val""" + // is parsed by a .NET console app into an arg array: + // [ "myarg:\"my val\"" ] + // which is the same end result when applying libuv quoting rules. although the actual + // command line from libuv quoting rules would look like: + // foo.exe "myarg:\"my val\"" + // + // 3) double-up slashes that precede a quote, + // e.g. hello \world => "hello \world" + // hello\"world => "hello\\""world" + // hello\\"world => "hello\\\\""world" + // hello world\ => "hello world\\" + // + // technically this is not required for a cmd.exe command line, or the batch argument parser. + // the reasons for including this as a .cmd quoting rule are: + // + // a) this is optimized for the scenario where the argument is passed from the .cmd file to an + // external program. many programs (e.g. .NET console apps) rely on the slash-doubling rule. + // + // b) it's what we've been doing previously (by deferring to node default behavior) and we + // haven't heard any complaints about that aspect. + // + // note, a weakness of the quoting rules chosen here, is that % is not escaped. in fact, % cannot be + // escaped when used on the command line directly - even though within a .cmd file % can be escaped + // by using %%. + // + // the saving grace is, on the command line, %var% is left as-is if var is not defined. this contrasts + // the line parsing rules within a .cmd file, where if var is not defined it is replaced with nothing. + // + // one option that was explored was replacing % with ^% - i.e. %var% => ^%var^%. this hack would + // often work, since it is unlikely that var^ would exist, and the ^ character is removed when the + // variable is used. the problem, however, is that ^ is not removed when %* is used to pass the args + // to an external program. + // + // an unexplored potential solution for the % escaping problem, is to create a wrapper .cmd file. + // % can be escaped within a .cmd file. + let reverse = '"'; + let quoteHit = true; + for (let i = arg.length; i > 0; i--) { + // walk the string in reverse + reverse += arg[i - 1]; + if (quoteHit && arg[i - 1] === '\\') { + reverse += '\\'; // double the slash + } + else if (arg[i - 1] === '"') { + quoteHit = true; + reverse += '"'; // double the quote + } + else { + quoteHit = false; + } + } + reverse += '"'; + return reverse.split('').reverse().join(''); + } + _uvQuoteCmdArg(arg) { + // Tool runner wraps child_process.spawn() and needs to apply the same quoting as + // Node in certain cases where the undocumented spawn option windowsVerbatimArguments + // is used. + // + // Since this function is a port of quote_cmd_arg from Node 4.x (technically, lib UV, + // see https://github.com/nodejs/node/blob/v4.x/deps/uv/src/win/process.c for details), + // pasting copyright notice from Node within this function: + // + // Copyright Joyent, Inc. and other Node contributors. All rights reserved. + // + // 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. + if (!arg) { + // Need double quotation for empty argument + return '""'; + } + if (!arg.includes(' ') && !arg.includes('\t') && !arg.includes('"')) { + // No quotation needed + return arg; + } + if (!arg.includes('"') && !arg.includes('\\')) { + // No embedded double quotes or backslashes, so I can just wrap + // quote marks around the whole thing. + return `"${arg}"`; + } + // Expected input/output: + // input : hello"world + // output: "hello\"world" + // input : hello""world + // output: "hello\"\"world" + // input : hello\world + // output: hello\world + // input : hello\\world + // output: hello\\world + // input : hello\"world + // output: "hello\\\"world" + // input : hello\\"world + // output: "hello\\\\\"world" + // input : hello world\ + // output: "hello world\\" - note the comment in libuv actually reads "hello world\" + // but it appears the comment is wrong, it should be "hello world\\" + let reverse = '"'; + let quoteHit = true; + for (let i = arg.length; i > 0; i--) { + // walk the string in reverse + reverse += arg[i - 1]; + if (quoteHit && arg[i - 1] === '\\') { + reverse += '\\'; + } + else if (arg[i - 1] === '"') { + quoteHit = true; + reverse += '\\'; + } + else { + quoteHit = false; + } + } + reverse += '"'; + return reverse.split('').reverse().join(''); + } + _cloneExecOptions(options) { + options = options || {}; + const result = { + cwd: options.cwd || process.cwd(), + env: options.env || process.env, + silent: options.silent || false, + windowsVerbatimArguments: options.windowsVerbatimArguments || false, + failOnStdErr: options.failOnStdErr || false, + ignoreReturnCode: options.ignoreReturnCode || false, + delay: options.delay || 10000 + }; + result.outStream = options.outStream || process.stdout; + result.errStream = options.errStream || process.stderr; + return result; + } + _getSpawnOptions(options, toolPath) { + options = options || {}; + const result = {}; + result.cwd = options.cwd; + result.env = options.env; + result['windowsVerbatimArguments'] = + options.windowsVerbatimArguments || this._isCmdFile(); + if (options.windowsVerbatimArguments) { + result.argv0 = `"${toolPath}"`; + } + return result; + } + /** + * Exec a tool. + * Output will be streamed to the live console. + * Returns promise with return code + * + * @param tool path to tool to exec + * @param options optional exec options. See ExecOptions + * @returns number + */ + exec() { + return toolrunner_awaiter(this, void 0, void 0, function* () { + // root the tool path if it is unrooted and contains relative pathing + if (!isRooted(this.toolPath) && + (this.toolPath.includes('/') || + (toolrunner_IS_WINDOWS && this.toolPath.includes('\\')))) { + // prefer options.cwd if it is specified, however options.cwd may also need to be rooted + this.toolPath = external_path_.resolve(process.cwd(), this.options.cwd || process.cwd(), this.toolPath); + } + // if the tool is only a file name, then resolve it from the PATH + // otherwise verify it exists (add extension on Windows if necessary) + this.toolPath = yield which(this.toolPath, true); + return new Promise((resolve, reject) => toolrunner_awaiter(this, void 0, void 0, function* () { + this._debug(`exec tool: ${this.toolPath}`); + this._debug('arguments:'); + for (const arg of this.args) { + this._debug(` ${arg}`); + } + const optionsNonNull = this._cloneExecOptions(this.options); + if (!optionsNonNull.silent && optionsNonNull.outStream) { + optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + external_os_.EOL); + } + const state = new ExecState(optionsNonNull, this.toolPath); + state.on('debug', (message) => { + this._debug(message); + }); + if (this.options.cwd && !(yield exists(this.options.cwd))) { + return reject(new Error(`The cwd: ${this.options.cwd} does not exist!`)); + } + const fileName = this._getSpawnFileName(); + const cp = external_child_process_.spawn(fileName, this._getSpawnArgs(optionsNonNull), this._getSpawnOptions(this.options, fileName)); + let stdbuffer = ''; + if (cp.stdout) { + cp.stdout.on('data', (data) => { + if (this.options.listeners && this.options.listeners.stdout) { + this.options.listeners.stdout(data); + } + if (!optionsNonNull.silent && optionsNonNull.outStream) { + optionsNonNull.outStream.write(data); + } + stdbuffer = this._processLineBuffer(data, stdbuffer, (line) => { + if (this.options.listeners && this.options.listeners.stdline) { + this.options.listeners.stdline(line); + } + }); + }); + } + let errbuffer = ''; + if (cp.stderr) { + cp.stderr.on('data', (data) => { + state.processStderr = true; + if (this.options.listeners && this.options.listeners.stderr) { + this.options.listeners.stderr(data); + } + if (!optionsNonNull.silent && + optionsNonNull.errStream && + optionsNonNull.outStream) { + const s = optionsNonNull.failOnStdErr + ? optionsNonNull.errStream + : optionsNonNull.outStream; + s.write(data); + } + errbuffer = this._processLineBuffer(data, errbuffer, (line) => { + if (this.options.listeners && this.options.listeners.errline) { + this.options.listeners.errline(line); + } + }); + }); + } + cp.on('error', (err) => { + state.processError = err.message; + state.processExited = true; + state.processClosed = true; + state.CheckComplete(); + }); + cp.on('exit', (code) => { + state.processExitCode = code; + state.processExited = true; + this._debug(`Exit code ${code} received from tool '${this.toolPath}'`); + state.CheckComplete(); + }); + cp.on('close', (code) => { + state.processExitCode = code; + state.processExited = true; + state.processClosed = true; + this._debug(`STDIO streams have closed for tool '${this.toolPath}'`); + state.CheckComplete(); + }); + state.on('done', (error, exitCode) => { + if (stdbuffer.length > 0) { + this.emit('stdline', stdbuffer); + } + if (errbuffer.length > 0) { + this.emit('errline', errbuffer); + } + cp.removeAllListeners(); + if (error) { + reject(error); + } + else { + resolve(exitCode); + } + }); + if (this.options.input) { + if (!cp.stdin) { + throw new Error('child process missing stdin'); + } + cp.stdin.end(this.options.input); + } + })); + }); + } +} +/** + * Convert an arg string to an array of args. Handles escaping + * + * @param argString string of arguments + * @returns string[] array of arguments + */ +function argStringToArray(argString) { + const args = []; + let inQuotes = false; + let escaped = false; + let arg = ''; + function append(c) { + // we only escape double quotes. + if (escaped && c !== '"') { + arg += '\\'; + } + arg += c; + escaped = false; + } + for (let i = 0; i < argString.length; i++) { + const c = argString.charAt(i); + if (c === '"') { + if (!escaped) { + inQuotes = !inQuotes; + } + else { + append(c); + } + continue; + } + if (c === '\\' && escaped) { + append(c); + continue; + } + if (c === '\\' && inQuotes) { + escaped = true; + continue; + } + if (c === ' ' && !inQuotes) { + if (arg.length > 0) { + args.push(arg); + arg = ''; + } + continue; + } + append(c); + } + if (arg.length > 0) { + args.push(arg.trim()); + } + return args; +} +class ExecState extends external_events_.EventEmitter { + constructor(options, toolPath) { + super(); + this.processClosed = false; // tracks whether the process has exited and stdio is closed + this.processError = ''; + this.processExitCode = 0; + this.processExited = false; // tracks whether the process has exited + this.processStderr = false; // tracks whether stderr was written to + this.delay = 10000; // 10 seconds + this.done = false; + this.timeout = null; + if (!toolPath) { + throw new Error('toolPath must not be empty'); + } + this.options = options; + this.toolPath = toolPath; + if (options.delay) { + this.delay = options.delay; + } + } + CheckComplete() { + if (this.done) { + return; + } + if (this.processClosed) { + this._setResult(); + } + else if (this.processExited) { + this.timeout = (0,external_timers_namespaceObject.setTimeout)(ExecState.HandleTimeout, this.delay, this); + } + } + _debug(message) { + this.emit('debug', message); + } + _setResult() { + // determine whether there is an error + let error; + if (this.processExited) { + if (this.processError) { + error = new Error(`There was an error when attempting to execute the process '${this.toolPath}'. This may indicate the process failed to start. Error: ${this.processError}`); + } + else if (this.processExitCode !== 0 && !this.options.ignoreReturnCode) { + error = new Error(`The process '${this.toolPath}' failed with exit code ${this.processExitCode}`); + } + else if (this.processStderr && this.options.failOnStdErr) { + error = new Error(`The process '${this.toolPath}' failed because one or more lines were written to the STDERR stream`); + } + } + // clear the timeout + if (this.timeout) { + clearTimeout(this.timeout); + this.timeout = null; + } + this.done = true; + this.emit('done', error, this.processExitCode); + } + static HandleTimeout(state) { + if (state.done) { + return; + } + if (!state.processClosed && state.processExited) { + const message = `The STDIO streams did not close within ${state.delay / 1000} seconds of the exit event from process '${state.toolPath}'. This may indicate a child process inherited the STDIO streams and has not yet exited.`; + state._debug(message); + } + state._setResult(); + } +} +//# sourceMappingURL=toolrunner.js.map +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@actions/exec/3.0.0/530e2f35971783f1666d0f5e5823d8fd663ed254c8ebbee4acd04b167b0622b6/node_modules/@actions/exec/lib/exec.js +var exec_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; + + +/** + * Exec a command. + * Output will be streamed to the live console. + * Returns promise with return code + * + * @param commandLine command to execute (can include additional args). Must be correctly escaped. + * @param args optional arguments for tool. Escaping is handled by the lib. + * @param options optional exec options. See ExecOptions + * @returns Promise exit code + */ +function exec_exec(commandLine, args, options) { + return exec_awaiter(this, void 0, void 0, function* () { + const commandArgs = argStringToArray(commandLine); + if (commandArgs.length === 0) { + throw new Error(`Parameter 'commandLine' cannot be null or empty.`); + } + // Path to tool to execute should be first arg + const toolPath = commandArgs[0]; + args = commandArgs.slice(1).concat(args || []); + const runner = new ToolRunner(toolPath, args, options); + return runner.exec(); + }); +} +/** + * Exec a command and get the output. + * Output will be streamed to the live console. + * Returns promise with the exit code and collected stdout and stderr + * + * @param commandLine command to execute (can include additional args). Must be correctly escaped. + * @param args optional arguments for tool. Escaping is handled by the lib. + * @param options optional exec options. See ExecOptions + * @returns Promise exit code, stdout, and stderr + */ +function getExecOutput(commandLine, args, options) { + return exec_awaiter(this, void 0, void 0, function* () { + var _a, _b; + let stdout = ''; + let stderr = ''; + //Using string decoder covers the case where a mult-byte character is split + const stdoutDecoder = new StringDecoder('utf8'); + const stderrDecoder = new StringDecoder('utf8'); + const originalStdoutListener = (_a = options === null || options === void 0 ? void 0 : options.listeners) === null || _a === void 0 ? void 0 : _a.stdout; + const originalStdErrListener = (_b = options === null || options === void 0 ? void 0 : options.listeners) === null || _b === void 0 ? void 0 : _b.stderr; + const stdErrListener = (data) => { + stderr += stderrDecoder.write(data); + if (originalStdErrListener) { + originalStdErrListener(data); + } + }; + const stdOutListener = (data) => { + stdout += stdoutDecoder.write(data); + if (originalStdoutListener) { + originalStdoutListener(data); + } + }; + const listeners = Object.assign(Object.assign({}, options === null || options === void 0 ? void 0 : options.listeners), { stdout: stdOutListener, stderr: stdErrListener }); + const exitCode = yield exec_exec(commandLine, args, Object.assign(Object.assign({}, options), { listeners })); + //flush any remaining characters + stdout += stdoutDecoder.end(); + stderr += stderrDecoder.end(); + return { + exitCode, + stdout, + stderr + }; + }); +} +//# sourceMappingURL=exec.js.map +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@actions/core/3.0.0/3fcceda85205d927f36e6c5a6b901a7f45509694db31f7c9a281d76b3d23161d/node_modules/@actions/core/lib/platform.js +var platform_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; + + +const getWindowsInfo = () => platform_awaiter(void 0, void 0, void 0, function* () { + const { stdout: version } = yield exec.getExecOutput('powershell -command "(Get-CimInstance -ClassName Win32_OperatingSystem).Version"', undefined, { + silent: true + }); + const { stdout: name } = yield exec.getExecOutput('powershell -command "(Get-CimInstance -ClassName Win32_OperatingSystem).Caption"', undefined, { + silent: true + }); + return { + name: name.trim(), + version: version.trim() + }; +}); +const getMacOsInfo = () => platform_awaiter(void 0, void 0, void 0, function* () { + var _a, _b, _c, _d; + const { stdout } = yield exec.getExecOutput('sw_vers', undefined, { + silent: true + }); + const version = (_b = (_a = stdout.match(/ProductVersion:\s*(.+)/)) === null || _a === void 0 ? void 0 : _a[1]) !== null && _b !== void 0 ? _b : ''; + const name = (_d = (_c = stdout.match(/ProductName:\s*(.+)/)) === null || _c === void 0 ? void 0 : _c[1]) !== null && _d !== void 0 ? _d : ''; + return { + name, + version + }; +}); +const getLinuxInfo = () => platform_awaiter(void 0, void 0, void 0, function* () { + const { stdout } = yield exec.getExecOutput('lsb_release', ['-i', '-r', '-s'], { + silent: true + }); + const [name, version] = stdout.trim().split('\n'); + return { + name, + version + }; +}); +const platform = external_os_.platform(); +const arch = external_os_.arch(); +const isWindows = platform === 'win32'; +const isMacOS = platform === 'darwin'; +const isLinux = platform === 'linux'; +function getDetails() { + return platform_awaiter(this, void 0, void 0, function* () { + return Object.assign(Object.assign({}, (yield (isWindows + ? getWindowsInfo() + : isMacOS + ? getMacOsInfo() + : getLinuxInfo()))), { platform, + arch, + isWindows, + isMacOS, + isLinux }); + }); +} +//# sourceMappingURL=platform.js.map +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@actions/core/3.0.0/3fcceda85205d927f36e6c5a6b901a7f45509694db31f7c9a281d76b3d23161d/node_modules/@actions/core/lib/core.js +var core_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; + + + + + + +/** + * The code to exit an action + */ +var ExitCode; +(function (ExitCode) { + /** + * A code indicating that the action was successful + */ + ExitCode[ExitCode["Success"] = 0] = "Success"; + /** + * A code indicating that the action was a failure + */ + ExitCode[ExitCode["Failure"] = 1] = "Failure"; +})(ExitCode || (ExitCode = {})); +//----------------------------------------------------------------------- +// Variables +//----------------------------------------------------------------------- +/** + * Sets env variable for this action and future actions in the job + * @param name the name of the variable to set + * @param val the value of the variable. Non-string values will be converted to a string via JSON.stringify + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function exportVariable(name, val) { + const convertedVal = toCommandValue(val); + process.env[name] = convertedVal; + const filePath = process.env['GITHUB_ENV'] || ''; + if (filePath) { + return issueFileCommand('ENV', prepareKeyValueMessage(name, val)); + } + issueCommand('set-env', { name }, convertedVal); +} +/** + * Registers a secret which will get masked from logs + * + * @param secret - Value of the secret to be masked + * @remarks + * This function instructs the Actions runner to mask the specified value in any + * logs produced during the workflow run. Once registered, the secret value will + * be replaced with asterisks (***) whenever it appears in console output, logs, + * or error messages. + * + * This is useful for protecting sensitive information such as: + * - API keys + * - Access tokens + * - Authentication credentials + * - URL parameters containing signatures (SAS tokens) + * + * Note that masking only affects future logs; any previous appearances of the + * secret in logs before calling this function will remain unmasked. + * + * @example + * ```typescript + * // Register an API token as a secret + * const apiToken = "abc123xyz456"; + * setSecret(apiToken); + * + * // Now any logs containing this value will show *** instead + * console.log(`Using token: ${apiToken}`); // Outputs: "Using token: ***" + * ``` + */ +function core_setSecret(secret) { + issueCommand('add-mask', {}, secret); +} +/** + * Prepends inputPath to the PATH (for this action and future actions) + * @param inputPath + */ +function addPath(inputPath) { + const filePath = process.env['GITHUB_PATH'] || ''; + if (filePath) { + file_command_issueFileCommand('PATH', inputPath); + } + else { + command_issueCommand('add-path', {}, inputPath); + } + process.env['PATH'] = `${inputPath}${external_path_.delimiter}${process.env['PATH']}`; +} +/** + * Gets the value of an input. + * Unless trimWhitespace is set to false in InputOptions, the value is also trimmed. + * Returns an empty string if the value is not defined. + * + * @param name name of the input to get + * @param options optional. See InputOptions. + * @returns string + */ +function getInput(name, options) { + const val = process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] || ''; + if (options && options.required && !val) { + throw new Error(`Input required and not supplied: ${name}`); + } + if (options && options.trimWhitespace === false) { + return val; + } + return val.trim(); +} +/** + * Gets the values of an multiline input. Each value is also trimmed. + * + * @param name name of the input to get + * @param options optional. See InputOptions. + * @returns string[] + * + */ +function getMultilineInput(name, options) { + const inputs = getInput(name, options) + .split('\n') + .filter(x => x !== ''); + if (options && options.trimWhitespace === false) { + return inputs; + } + return inputs.map(input => input.trim()); +} +/** + * Gets the input value of the boolean type in the YAML 1.2 "core schema" specification. + * Support boolean input list: `true | True | TRUE | false | False | FALSE` . + * The return value is also in boolean type. + * ref: https://yaml.org/spec/1.2/spec.html#id2804923 + * + * @param name name of the input to get + * @param options optional. See InputOptions. + * @returns boolean + */ +function getBooleanInput(name, options) { + const trueValue = ['true', 'True', 'TRUE']; + const falseValue = ['false', 'False', 'FALSE']; + const val = getInput(name, options); + if (trueValue.includes(val)) + return true; + if (falseValue.includes(val)) + return false; + throw new TypeError(`Input does not meet YAML 1.2 "Core Schema" specification: ${name}\n` + + `Support boolean input list: \`true | True | TRUE | false | False | FALSE\``); +} +/** + * Sets the value of an output. + * + * @param name name of the output to set + * @param value value to store. Non-string values will be converted to a string via JSON.stringify + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function setOutput(name, value) { + const filePath = process.env['GITHUB_OUTPUT'] || ''; + if (filePath) { + return issueFileCommand('OUTPUT', prepareKeyValueMessage(name, value)); + } + process.stdout.write(os.EOL); + issueCommand('set-output', { name }, toCommandValue(value)); +} +/** + * Enables or disables the echoing of commands into stdout for the rest of the step. + * Echoing is disabled by default if ACTIONS_STEP_DEBUG is not set. + * + */ +function setCommandEcho(enabled) { + issue('echo', enabled ? 'on' : 'off'); +} +//----------------------------------------------------------------------- +// Results +//----------------------------------------------------------------------- +/** + * Sets the action status to failed. + * When the action exits it will be with an exit code of 1 + * @param message add error issue message + */ +function setFailed(message) { + process.exitCode = ExitCode.Failure; + error(message); +} +//----------------------------------------------------------------------- +// Logging Commands +//----------------------------------------------------------------------- +/** + * Gets whether Actions Step Debug is on or not + */ +function isDebug() { + return process.env['RUNNER_DEBUG'] === '1'; +} +/** + * Writes debug message to user log + * @param message debug message + */ +function core_debug(message) { + command_issueCommand('debug', {}, message); +} +/** + * Adds an error issue + * @param message error issue message. Errors will be converted to string via toString() + * @param properties optional properties to add to the annotation. + */ +function error(message, properties = {}) { + command_issueCommand('error', utils_toCommandProperties(properties), message instanceof Error ? message.toString() : message); +} +/** + * Adds a warning issue + * @param message warning issue message. Errors will be converted to string via toString() + * @param properties optional properties to add to the annotation. + */ +function warning(message, properties = {}) { + command_issueCommand('warning', utils_toCommandProperties(properties), message instanceof Error ? message.toString() : message); +} +/** + * Adds a notice issue + * @param message notice issue message. Errors will be converted to string via toString() + * @param properties optional properties to add to the annotation. + */ +function notice(message, properties = {}) { + issueCommand('notice', toCommandProperties(properties), message instanceof Error ? message.toString() : message); +} +/** + * Writes info to log with console.log. + * @param message info message + */ +function info(message) { + process.stdout.write(message + external_os_.EOL); +} +/** + * Begin an output group. + * + * Output until the next `groupEnd` will be foldable in this group + * + * @param name The name of the output group + */ +function startGroup(name) { + issue('group', name); +} +/** + * End an output group. + */ +function endGroup() { + issue('endgroup'); +} +/** + * Wrap an asynchronous function call in a group. + * + * Returns the same type as the function itself. + * + * @param name The name of the group + * @param fn The function to wrap in the group + */ +function group(name, fn) { + return core_awaiter(this, void 0, void 0, function* () { + startGroup(name); + let result; + try { + result = yield fn(); + } + finally { + endGroup(); + } + return result; + }); +} +//----------------------------------------------------------------------- +// Wrapper action state +//----------------------------------------------------------------------- +/** + * Saves state for current action, the state can only be retrieved by this action's post job execution. + * + * @param name name of the state to store + * @param value value to store. Non-string values will be converted to a string via JSON.stringify + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function saveState(name, value) { + const filePath = process.env['GITHUB_STATE'] || ''; + if (filePath) { + return issueFileCommand('STATE', prepareKeyValueMessage(name, value)); + } + issueCommand('save-state', { name }, toCommandValue(value)); +} +/** + * Gets the value of an state set by this action's main execution. + * + * @param name name of the state to get + * @returns string + */ +function getState(name) { + return process.env[`STATE_${name}`] || ''; +} +function getIDToken(aud) { + return core_awaiter(this, void 0, void 0, function* () { + return yield OidcClient.getIDToken(aud); + }); +} +/** + * Summary exports + */ + +/** + * @deprecated use core.summary + */ + +/** + * Path exports + */ + +/** + * Platform utilities exports + */ + +//# sourceMappingURL=core.js.map +;// CONCATENATED MODULE: external "node:process" +const external_node_process_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:process"); +;// CONCATENATED MODULE: external "node:fs" +const external_node_fs_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:fs"); +// EXTERNAL MODULE: external "node:path" +var external_node_path_ = __nccwpck_require__(6760); +// EXTERNAL MODULE: external "node:stream" +var external_node_stream_ = __nccwpck_require__(7075); +// EXTERNAL MODULE: external "node:events" +var external_node_events_ = __nccwpck_require__(8474); +;// CONCATENATED MODULE: external "node:stream/promises" +const promises_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:stream/promises"); +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@sindresorhus/merge-streams/4.0.0/8e693ab70e031a19d1b7bae684db249220a2cb4faf41f63d8ac2c81a3ef13edb/node_modules/@sindresorhus/merge-streams/index.js + + + + +function mergeStreams(streams) { + if (!Array.isArray(streams)) { + throw new TypeError(`Expected an array, got \`${typeof streams}\`.`); + } + + for (const stream of streams) { + validateStream(stream); + } + + const objectMode = streams.some(({readableObjectMode}) => readableObjectMode); + const highWaterMark = getHighWaterMark(streams, objectMode); + const passThroughStream = new MergedStream({ + objectMode, + writableHighWaterMark: highWaterMark, + readableHighWaterMark: highWaterMark, + }); + + for (const stream of streams) { + passThroughStream.add(stream); + } + + return passThroughStream; +} + +const getHighWaterMark = (streams, objectMode) => { + if (streams.length === 0) { + return (0,external_node_stream_.getDefaultHighWaterMark)(objectMode); + } + + const highWaterMarks = streams + .filter(({readableObjectMode}) => readableObjectMode === objectMode) + .map(({readableHighWaterMark}) => readableHighWaterMark); + return Math.max(...highWaterMarks); +}; + +class MergedStream extends external_node_stream_.PassThrough { + #streams = new Set([]); + #ended = new Set([]); + #aborted = new Set([]); + #onFinished; + #unpipeEvent = Symbol('unpipe'); + #streamPromises = new WeakMap(); + + add(stream) { + validateStream(stream); + + if (this.#streams.has(stream)) { + return; + } + + this.#streams.add(stream); + + this.#onFinished ??= onMergedStreamFinished(this, this.#streams, this.#unpipeEvent); + const streamPromise = endWhenStreamsDone({ + passThroughStream: this, + stream, + streams: this.#streams, + ended: this.#ended, + aborted: this.#aborted, + onFinished: this.#onFinished, + unpipeEvent: this.#unpipeEvent, + }); + this.#streamPromises.set(stream, streamPromise); + + stream.pipe(this, {end: false}); + } + + async remove(stream) { + validateStream(stream); + + if (!this.#streams.has(stream)) { + return false; + } + + const streamPromise = this.#streamPromises.get(stream); + if (streamPromise === undefined) { + return false; + } + + this.#streamPromises.delete(stream); + + stream.unpipe(this); + await streamPromise; + return true; + } +} + +const onMergedStreamFinished = async (passThroughStream, streams, unpipeEvent) => { + updateMaxListeners(passThroughStream, PASSTHROUGH_LISTENERS_COUNT); + const controller = new AbortController(); + + try { + await Promise.race([ + onMergedStreamEnd(passThroughStream, controller), + onInputStreamsUnpipe(passThroughStream, streams, unpipeEvent, controller), + ]); + } finally { + controller.abort(); + updateMaxListeners(passThroughStream, -PASSTHROUGH_LISTENERS_COUNT); + } +}; + +const onMergedStreamEnd = async (passThroughStream, {signal}) => { + try { + await (0,promises_namespaceObject.finished)(passThroughStream, {signal, cleanup: true}); + } catch (error) { + errorOrAbortStream(passThroughStream, error); + throw error; + } +}; + +const onInputStreamsUnpipe = async (passThroughStream, streams, unpipeEvent, {signal}) => { + for await (const [unpipedStream] of (0,external_node_events_.on)(passThroughStream, 'unpipe', {signal})) { + if (streams.has(unpipedStream)) { + unpipedStream.emit(unpipeEvent); + } + } +}; + +const validateStream = stream => { + if (typeof stream?.pipe !== 'function') { + throw new TypeError(`Expected a readable stream, got: \`${typeof stream}\`.`); + } +}; + +const endWhenStreamsDone = async ({passThroughStream, stream, streams, ended, aborted, onFinished, unpipeEvent}) => { + updateMaxListeners(passThroughStream, PASSTHROUGH_LISTENERS_PER_STREAM); + const controller = new AbortController(); + + try { + await Promise.race([ + afterMergedStreamFinished(onFinished, stream, controller), + onInputStreamEnd({ + passThroughStream, + stream, + streams, + ended, + aborted, + controller, + }), + onInputStreamUnpipe({ + stream, + streams, + ended, + aborted, + unpipeEvent, + controller, + }), + ]); + } finally { + controller.abort(); + updateMaxListeners(passThroughStream, -PASSTHROUGH_LISTENERS_PER_STREAM); + } + + if (streams.size > 0 && streams.size === ended.size + aborted.size) { + if (ended.size === 0 && aborted.size > 0) { + abortStream(passThroughStream); + } else { + endStream(passThroughStream); + } + } +}; + +const afterMergedStreamFinished = async (onFinished, stream, {signal}) => { + try { + await onFinished; + if (!signal.aborted) { + abortStream(stream); + } + } catch (error) { + if (!signal.aborted) { + errorOrAbortStream(stream, error); + } + } +}; + +const onInputStreamEnd = async ({passThroughStream, stream, streams, ended, aborted, controller: {signal}}) => { + try { + await (0,promises_namespaceObject.finished)(stream, { + signal, + cleanup: true, + readable: true, + writable: false, + }); + if (streams.has(stream)) { + ended.add(stream); + } + } catch (error) { + if (signal.aborted || !streams.has(stream)) { + return; + } + + if (isAbortError(error)) { + aborted.add(stream); + } else { + errorStream(passThroughStream, error); + } + } +}; + +const onInputStreamUnpipe = async ({stream, streams, ended, aborted, unpipeEvent, controller: {signal}}) => { + await (0,external_node_events_.once)(stream, unpipeEvent, {signal}); + + if (!stream.readable) { + return (0,external_node_events_.once)(signal, 'abort', {signal}); + } + + streams.delete(stream); + ended.delete(stream); + aborted.delete(stream); +}; + +const endStream = stream => { + if (stream.writable) { + stream.end(); + } +}; + +const errorOrAbortStream = (stream, error) => { + if (isAbortError(error)) { + abortStream(stream); + } else { + errorStream(stream, error); + } +}; + +// This is the error thrown by `finished()` on `stream.destroy()` +const isAbortError = error => error?.code === 'ERR_STREAM_PREMATURE_CLOSE'; + +const abortStream = stream => { + if (stream.readable || stream.writable) { + stream.destroy(); + } +}; + +// `stream.destroy(error)` crashes the process with `uncaughtException` if no `error` event listener exists on `stream`. +// We take care of error handling on user behalf, so we do not want this to happen. +const errorStream = (stream, error) => { + if (!stream.destroyed) { + stream.once('error', noop); + stream.destroy(error); + } +}; + +const noop = () => {}; + +const updateMaxListeners = (passThroughStream, increment) => { + const maxListeners = passThroughStream.getMaxListeners(); + if (maxListeners !== 0 && maxListeners !== Number.POSITIVE_INFINITY) { + passThroughStream.setMaxListeners(maxListeners + increment); + } +}; + +// Number of times `passThroughStream.on()` is called regardless of streams: +// - once due to `finished(passThroughStream)` +// - once due to `on(passThroughStream)` +const PASSTHROUGH_LISTENERS_COUNT = 2; + +// Number of times `passThroughStream.on()` is called per stream: +// - once due to `stream.pipe(passThroughStream)` +const PASSTHROUGH_LISTENERS_PER_STREAM = 1; + +// EXTERNAL MODULE: ../../../Library/pnpm/store/v10/links/@/fast-glob/3.3.3/4d7c9438b037a74bda80749d8ebeda290d818194756f22a5acf6cc000a4547b8/node_modules/fast-glob/out/index.js +var out = __nccwpck_require__(2206); +// EXTERNAL MODULE: external "node:util" +var external_node_util_ = __nccwpck_require__(7975); +;// CONCATENATED MODULE: external "node:child_process" +const external_node_child_process_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:child_process"); +// EXTERNAL MODULE: external "node:url" +var external_node_url_ = __nccwpck_require__(3136); +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@/unicorn-magic/0.4.0/1557576fdcd95b77d110542b8071399275704dbe8ac6be0eb972573bead0ee0e/node_modules/unicorn-magic/node.js + + + + + +const execFileOriginal = (0,external_node_util_.promisify)(external_node_child_process_namespaceObject.execFile); + +function toPath(urlOrPath) { + return urlOrPath instanceof URL ? (0,external_node_url_.fileURLToPath)(urlOrPath) : urlOrPath; +} + +function rootDirectory(pathInput) { + return path.parse(toPath(pathInput)).root; +} + +function traversePathUp(startPath) { + return { + * [Symbol.iterator]() { + let currentPath = path.resolve(toPath(startPath)); + let previousPath; + + while (previousPath !== currentPath) { + yield currentPath; + previousPath = currentPath; + currentPath = path.resolve(currentPath, '..'); + } + }, + }; +} + +const TEN_MEGABYTES_IN_BYTES = (/* unused pure expression or super */ null && (10 * 1024 * 1024)); + +async function execFile(file, arguments_, options = {}) { + return execFileOriginal(file, arguments_, { + maxBuffer: TEN_MEGABYTES_IN_BYTES, + ...options, + }); +} + +function execFileSync(file, arguments_ = [], options = {}) { + return execFileSyncOriginal(file, arguments_, { + maxBuffer: TEN_MEGABYTES_IN_BYTES, + encoding: 'utf8', + stdio: 'pipe', + ...options, + }); +} + + + +// EXTERNAL MODULE: external "node:fs/promises" +var promises_ = __nccwpck_require__(1455); +// EXTERNAL MODULE: ../../../Library/pnpm/store/v10/links/@/ignore/7.0.5/c0ceec7608eaec6cae63537114b52d466bdcd83c1173d7da9887eeb4960b9d7d/node_modules/ignore/index.js +var ignore = __nccwpck_require__(7261); +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@/is-path-inside/4.0.0/2b16a362dbb8e8b5aa5655981cdb6263c3587d968e31d88cc6f725bd8da90401/node_modules/is-path-inside/index.js + + +function isPathInside(childPath, parentPath) { + const relation = external_node_path_.relative(parentPath, childPath); + + return Boolean( + relation && + relation !== '..' && + !relation.startsWith(`..${external_node_path_.sep}`) && + relation !== external_node_path_.resolve(childPath) + ); +} + +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@/slash/5.1.0/7ff5261a1eca3a95e3cdfe7207843d8babb856765fbfcb593c174be6c0d93c32/node_modules/slash/index.js +function slash(path) { + const isExtendedLengthPath = path.startsWith('\\\\?\\'); + + if (isExtendedLengthPath) { + return path; + } + + return path.replace(/\\/g, '/'); +} + +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@/globby/16.1.0/6bc516675ca718c332e5255dae86ad14f61b2538e1af28896d50d60441df5c38/node_modules/globby/utilities.js + + + + + +const isNegativePattern = pattern => pattern[0] === '!'; + +/** +Normalize an absolute pattern to be relative. + +On Unix, patterns starting with `/` are interpreted as absolute paths from the filesystem root. This causes inconsistent behavior across platforms since Windows uses different path roots (like `C:\`). + +This function strips leading `/` to make patterns relative to cwd, ensuring consistent cross-platform behavior. + +@param {string} pattern - The pattern to normalize. +*/ +const normalizeAbsolutePatternToRelative = pattern => pattern.startsWith('/') ? pattern.slice(1) : pattern; + +const bindFsMethod = (object, methodName) => { + const method = object?.[methodName]; + return typeof method === 'function' ? method.bind(object) : undefined; +}; + +// Only used as a fallback for legacy fs implementations +const promisifyFsMethod = (object, methodName) => { + const method = object?.[methodName]; + if (typeof method !== 'function') { + return undefined; + } + + return (0,external_node_util_.promisify)(method.bind(object)); +}; + +const normalizeDirectoryPatternForFastGlob = pattern => { + if (!pattern.endsWith('/')) { + return pattern; + } + + const trimmedPattern = pattern.replace(/\/+$/u, ''); + if (!trimmedPattern) { + return '/**'; + } + + // Special case for '**/' to avoid producing '**/**/**' + if (trimmedPattern === '**') { + return '**/**'; + } + + const hasLeadingSlash = trimmedPattern.startsWith('/'); + const patternBody = hasLeadingSlash ? trimmedPattern.slice(1) : trimmedPattern; + const hasInnerSlash = patternBody.includes('/'); + const needsRecursivePrefix = !hasLeadingSlash && !hasInnerSlash && !trimmedPattern.startsWith('**/'); + const recursivePrefix = needsRecursivePrefix ? '**/' : ''; + + return `${recursivePrefix}${trimmedPattern}/**`; +}; + +/** +Extract the parent directory prefix from a pattern (e.g., '../' or '../../'). + +Note: Patterns should have trailing slash after '..' (e.g., '../foo' not '..foo'). The directoryToGlob function ensures this in the normal pipeline. + +@param {string} pattern - The pattern to analyze. +@returns {string} The parent directory prefix, or empty string if none. +*/ +const getParentDirectoryPrefix = pattern => { + const normalizedPattern = isNegativePattern(pattern) ? pattern.slice(1) : pattern; + const match = normalizedPattern.match(/^(\.\.\/)+/); + return match ? match[0] : ''; +}; + +/** +Adjust ignore patterns to match the relative base of the main patterns. + +When patterns reference parent directories, ignore patterns starting with globstars need to be adjusted to match from the same base directory. This ensures intuitive behavior where ignore patterns work correctly with parent directory patterns. + +This is analogous to how node-glob normalizes path prefixes (see node-glob issue #309) and how Rust ignore crate strips path prefixes before matching. + +@param {string[]} patterns - The main glob patterns. +@param {string[]} ignorePatterns - The ignore patterns to adjust. +@returns {string[]} Adjusted ignore patterns. +*/ +const adjustIgnorePatternsForParentDirectories = (patterns, ignorePatterns) => { + // Early exit for empty arrays + if (patterns.length === 0 || ignorePatterns.length === 0) { + return ignorePatterns; + } + + // Get parent directory prefixes for all patterns (empty string if no prefix) + const parentPrefixes = patterns.map(pattern => getParentDirectoryPrefix(pattern)); + + // Check if all patterns have the same parent prefix + const firstPrefix = parentPrefixes[0]; + if (!firstPrefix) { + return ignorePatterns; // No parent directories in any pattern + } + + const allSamePrefix = parentPrefixes.every(prefix => prefix === firstPrefix); + if (!allSamePrefix) { + return ignorePatterns; // Mixed bases - don't adjust + } + + // Adjust ignore patterns that start with **/ + return ignorePatterns.map(pattern => { + // Only adjust patterns starting with **/ that don't already have a parent reference + if (pattern.startsWith('**/') && !pattern.startsWith('../')) { + return firstPrefix + pattern; + } + + return pattern; + }); +}; + +/** +Find the git root directory by searching upward for a .git directory. + +@param {string} cwd - The directory to start searching from. +@param {Object} [fsImplementation] - Optional fs implementation. +@returns {string|undefined} The git root directory path, or undefined if not found. +*/ +const getAsyncStatMethod = fsImplementation => + bindFsMethod(fsImplementation?.promises, 'stat') + ?? bindFsMethod(external_node_fs_namespaceObject.promises, 'stat'); + +const getStatSyncMethod = fsImplementation => { + if (fsImplementation) { + return bindFsMethod(fsImplementation, 'statSync'); + } + + return bindFsMethod(external_node_fs_namespaceObject, 'statSync'); +}; + +const pathHasGitDirectory = stats => Boolean(stats?.isDirectory?.() || stats?.isFile?.()); + +const buildPathChain = (startPath, rootPath) => { + const chain = []; + let currentPath = startPath; + + chain.push(currentPath); + + while (currentPath !== rootPath) { + const parentPath = external_node_path_.dirname(currentPath); + if (parentPath === currentPath) { + break; + } + + currentPath = parentPath; + chain.push(currentPath); + } + + return chain; +}; + +const findGitRootInChain = async (paths, statMethod) => { + for (const directory of paths) { + const gitPath = external_node_path_.join(directory, '.git'); + + try { + const stats = await statMethod(gitPath); // eslint-disable-line no-await-in-loop + if (pathHasGitDirectory(stats)) { + return directory; + } + } catch { + // Ignore errors and continue searching + } + } + + return undefined; +}; + +const findGitRootSyncUncached = (cwd, fsImplementation) => { + const statSyncMethod = getStatSyncMethod(fsImplementation); + if (!statSyncMethod) { + return undefined; + } + + const currentPath = external_node_path_.resolve(cwd); + const {root} = external_node_path_.parse(currentPath); + const chain = buildPathChain(currentPath, root); + + for (const directory of chain) { + const gitPath = external_node_path_.join(directory, '.git'); + try { + const stats = statSyncMethod(gitPath); + if (pathHasGitDirectory(stats)) { + return directory; + } + } catch { + // Ignore errors and continue searching + } + } + + return undefined; +}; + +const findGitRootSync = (cwd, fsImplementation) => { + if (typeof cwd !== 'string') { + throw new TypeError('cwd must be a string'); + } + + return findGitRootSyncUncached(cwd, fsImplementation); +}; + +const findGitRootAsyncUncached = async (cwd, fsImplementation) => { + const statMethod = getAsyncStatMethod(fsImplementation); + if (!statMethod) { + return findGitRootSync(cwd, fsImplementation); + } + + const currentPath = external_node_path_.resolve(cwd); + const {root} = external_node_path_.parse(currentPath); + const chain = buildPathChain(currentPath, root); + + return findGitRootInChain(chain, statMethod); +}; + +const findGitRoot = async (cwd, fsImplementation) => { + if (typeof cwd !== 'string') { + throw new TypeError('cwd must be a string'); + } + + return findGitRootAsyncUncached(cwd, fsImplementation); +}; + +/** +Get paths to all .gitignore files from git root to cwd (inclusive). + +@param {string} gitRoot - The git root directory. +@param {string} cwd - The current working directory. +@returns {string[]} Array of .gitignore file paths to search for. +*/ +const isWithinGitRoot = (gitRoot, cwd) => { + const resolvedGitRoot = external_node_path_.resolve(gitRoot); + const resolvedCwd = external_node_path_.resolve(cwd); + return resolvedCwd === resolvedGitRoot || isPathInside(resolvedCwd, resolvedGitRoot); +}; + +const getParentGitignorePaths = (gitRoot, cwd) => { + if (gitRoot && typeof gitRoot !== 'string') { + throw new TypeError('gitRoot must be a string or undefined'); + } + + if (typeof cwd !== 'string') { + throw new TypeError('cwd must be a string'); + } + + // If no gitRoot provided, return empty array + if (!gitRoot) { + return []; + } + + if (!isWithinGitRoot(gitRoot, cwd)) { + return []; + } + + const chain = buildPathChain(external_node_path_.resolve(cwd), external_node_path_.resolve(gitRoot)); + + return [...chain] + .reverse() + .map(directory => external_node_path_.join(directory, '.gitignore')); +}; + +/** +Convert ignore patterns to fast-glob compatible format. +Returns empty array if patterns should be handled by predicate only. + +@param {string[]} patterns - Ignore patterns from .gitignore files +@param {boolean} usingGitRoot - Whether patterns are relative to git root +@param {Function} normalizeDirectoryPatternForFastGlob - Function to normalize directory patterns +@returns {string[]} Patterns safe to pass to fast-glob, or empty array +*/ +const convertPatternsForFastGlob = (patterns, usingGitRoot, normalizeDirectoryPatternForFastGlob) => { + // Determine which patterns are safe to pass to fast-glob + // If there are negation patterns, we can't pass file patterns to fast-glob + // because fast-glob doesn't understand negations and would filter out files + // that should be re-included by negation patterns. + // If we're using git root, patterns are relative to git root not cwd, + // so we can't pass them to fast-glob which expects cwd-relative patterns. + // We only pass patterns to fast-glob if there are NO negations AND we're not using git root. + + if (usingGitRoot) { + return []; // Patterns are relative to git root, not cwd + } + + const result = []; + let hasNegations = false; + + // Single pass to check for negations and collect positive patterns + for (const pattern of patterns) { + if (isNegativePattern(pattern)) { + hasNegations = true; + break; // Early exit on first negation + } + + result.push(normalizeDirectoryPatternForFastGlob(pattern)); + } + + return hasNegations ? [] : result; +}; + +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@/globby/16.1.0/6bc516675ca718c332e5255dae86ad14f61b2538e1af28896d50d60441df5c38/node_modules/globby/ignore.js + + + + + + + + + + + +const defaultIgnoredDirectories = [ + '**/node_modules', + '**/flow-typed', + '**/coverage', + '**/.git', +]; +const ignoreFilesGlobOptions = { + absolute: true, + dot: true, +}; + +const GITIGNORE_FILES_PATTERN = '**/.gitignore'; + +const getReadFileMethod = fsImplementation => + bindFsMethod(fsImplementation?.promises, 'readFile') + ?? bindFsMethod(promises_, 'readFile') + ?? promisifyFsMethod(fsImplementation, 'readFile'); + +const getReadFileSyncMethod = fsImplementation => + bindFsMethod(fsImplementation, 'readFileSync') + ?? bindFsMethod(external_node_fs_namespaceObject, 'readFileSync'); + +const shouldSkipIgnoreFileError = (error, suppressErrors) => { + if (!error) { + return Boolean(suppressErrors); + } + + if (error.code === 'ENOENT' || error.code === 'ENOTDIR') { + return true; + } + + return Boolean(suppressErrors); +}; + +const createIgnoreFileReadError = (filePath, error) => { + if (error instanceof Error) { + error.message = `Failed to read ignore file at ${filePath}: ${error.message}`; + return error; + } + + return new Error(`Failed to read ignore file at ${filePath}: ${String(error)}`); +}; + +const processIgnoreFileCore = (filePath, readMethod, suppressErrors) => { + try { + const content = readMethod(filePath, 'utf8'); + return {filePath, content}; + } catch (error) { + if (shouldSkipIgnoreFileError(error, suppressErrors)) { + return undefined; + } + + throw createIgnoreFileReadError(filePath, error); + } +}; + +const readIgnoreFilesSafely = async (paths, readFileMethod, suppressErrors) => { + const fileResults = await Promise.all(paths.map(async filePath => { + try { + const content = await readFileMethod(filePath, 'utf8'); + return {filePath, content}; + } catch (error) { + if (shouldSkipIgnoreFileError(error, suppressErrors)) { + return undefined; + } + + throw createIgnoreFileReadError(filePath, error); + } + })); + + return fileResults.filter(Boolean); +}; + +const readIgnoreFilesSafelySync = (paths, readFileSyncMethod, suppressErrors) => paths + .map(filePath => processIgnoreFileCore(filePath, readFileSyncMethod, suppressErrors)) + .filter(Boolean); + +const dedupePaths = paths => { + const seen = new Set(); + return paths.filter(filePath => { + if (seen.has(filePath)) { + return false; + } + + seen.add(filePath); + return true; + }); +}; + +const globIgnoreFiles = (globFunction, patterns, normalizedOptions) => globFunction(patterns, { + ...normalizedOptions, + ...ignoreFilesGlobOptions, // Must be last to ensure absolute/dot flags stick +}); + +const getParentIgnorePaths = (gitRoot, normalizedOptions) => gitRoot + ? getParentGitignorePaths(gitRoot, normalizedOptions.cwd) + : []; + +const combineIgnoreFilePaths = (gitRoot, normalizedOptions, childPaths) => dedupePaths([ + ...getParentIgnorePaths(gitRoot, normalizedOptions), + ...childPaths, +]); + +const buildIgnoreResult = (files, normalizedOptions, gitRoot) => { + const baseDir = gitRoot || normalizedOptions.cwd; + const patterns = getPatternsFromIgnoreFiles(files, baseDir); + + return { + patterns, + predicate: createIgnorePredicate(patterns, normalizedOptions.cwd, baseDir), + usingGitRoot: Boolean(gitRoot && gitRoot !== normalizedOptions.cwd), + }; }; -var endpoints_default = Endpoints; -//# sourceMappingURL=endpoints.js.map +// Apply base path to gitignore patterns based on .gitignore spec 2.22.1 +// https://git-scm.com/docs/gitignore#_pattern_format +// See also https://github.com/sindresorhus/globby/issues/146 +const applyBaseToPattern = (pattern, base) => { + if (!base) { + return pattern; + } -;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@octokit/plugin-rest-endpoint-methods/17.0.0/23bcad6a6f09bbdd8bd9193c1b6ebd3b4d7d5c15f3d5d6a119345284a74f0760/node_modules/@octokit/plugin-rest-endpoint-methods/dist-src/endpoints-to-methods.js + const isNegative = isNegativePattern(pattern); + const cleanPattern = isNegative ? pattern.slice(1) : pattern; -const endpointMethodsMap = /* @__PURE__ */ new Map(); -for (const [scope, endpoints] of Object.entries(endpoints_default)) { - for (const [methodName, endpoint] of Object.entries(endpoints)) { - const [route, defaults, decorations] = endpoint; - const [method, url] = route.split(/ /); - const endpointDefaults = Object.assign( - { - method, - url - }, - defaults - ); - if (!endpointMethodsMap.has(scope)) { - endpointMethodsMap.set(scope, /* @__PURE__ */ new Map()); - } - endpointMethodsMap.get(scope).set(methodName, { - scope, - methodName, - endpointDefaults, - decorations - }); - } -} -const handler = { - has({ scope }, methodName) { - return endpointMethodsMap.get(scope).has(methodName); - }, - getOwnPropertyDescriptor(target, methodName) { - return { - value: this.get(target, methodName), - // ensures method is in the cache - configurable: true, - writable: true, - enumerable: true - }; - }, - defineProperty(target, methodName, descriptor) { - Object.defineProperty(target.cache, methodName, descriptor); - return true; - }, - deleteProperty(target, methodName) { - delete target.cache[methodName]; - return true; - }, - ownKeys({ scope }) { - return [...endpointMethodsMap.get(scope).keys()]; - }, - set(target, methodName, value) { - return target.cache[methodName] = value; - }, - get({ octokit, scope, cache }, methodName) { - if (cache[methodName]) { - return cache[methodName]; - } - const method = endpointMethodsMap.get(scope).get(methodName); - if (!method) { - return void 0; - } - const { endpointDefaults, decorations } = method; - if (decorations) { - cache[methodName] = decorate( - octokit, - scope, - methodName, - endpointDefaults, - decorations - ); - } else { - cache[methodName] = octokit.request.defaults(endpointDefaults); - } - return cache[methodName]; - } + // Check if pattern has non-trailing slashes + const slashIndex = cleanPattern.indexOf('/'); + const hasNonTrailingSlash = slashIndex !== -1 && slashIndex !== cleanPattern.length - 1; + + let result; + if (!hasNonTrailingSlash) { + // "If there is no separator at the beginning or middle of the pattern, + // then the pattern may also match at any level below the .gitignore level." + // So patterns like '*.log' or 'temp' or 'build/' (trailing slash) match recursively. + result = external_node_path_.posix.join(base, '**', cleanPattern); + } else if (cleanPattern.startsWith('/')) { + // "If there is a separator at the beginning [...] of the pattern, + // then the pattern is relative to the directory level of the particular .gitignore file itself." + // Leading slash anchors the pattern to the .gitignore's directory. + result = external_node_path_.posix.join(base, cleanPattern.slice(1)); + } else { + // "If there is a separator [...] middle [...] of the pattern, + // then the pattern is relative to the directory level of the particular .gitignore file itself." + // Patterns like 'src/foo' are relative to the .gitignore's directory. + result = external_node_path_.posix.join(base, cleanPattern); + } + + return isNegative ? '!' + result : result; }; -function endpointsToMethods(octokit) { - const newMethods = {}; - for (const scope of endpointMethodsMap.keys()) { - newMethods[scope] = new Proxy({ octokit, scope, cache: {} }, handler); - } - return newMethods; -} -function decorate(octokit, scope, methodName, defaults, decorations) { - const requestWithDefaults = octokit.request.defaults(defaults); - function withDecorations(...args) { - let options = requestWithDefaults.endpoint.merge(...args); - if (decorations.mapToData) { - options = Object.assign({}, options, { - data: options[decorations.mapToData], - [decorations.mapToData]: void 0 - }); - return requestWithDefaults(options); - } - if (decorations.renamed) { - const [newScope, newMethodName] = decorations.renamed; - octokit.log.warn( - `octokit.${scope}.${methodName}() has been renamed to octokit.${newScope}.${newMethodName}()` - ); - } - if (decorations.deprecated) { - octokit.log.warn(decorations.deprecated); - } - if (decorations.renamedParameters) { - const options2 = requestWithDefaults.endpoint.merge(...args); - for (const [name, alias] of Object.entries( - decorations.renamedParameters - )) { - if (name in options2) { - octokit.log.warn( - `"${name}" parameter is deprecated for "octokit.${scope}.${methodName}()". Use "${alias}" instead` - ); - if (!(alias in options2)) { - options2[alias] = options2[name]; - } - delete options2[name]; - } - } - return requestWithDefaults(options2); - } - return requestWithDefaults(...args); - } - return Object.assign(withDecorations, requestWithDefaults); -} -//# sourceMappingURL=endpoints-to-methods.js.map +const parseIgnoreFile = (file, cwd) => { + const base = slash(external_node_path_.relative(cwd, external_node_path_.dirname(file.filePath))); -;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@octokit/plugin-rest-endpoint-methods/17.0.0/23bcad6a6f09bbdd8bd9193c1b6ebd3b4d7d5c15f3d5d6a119345284a74f0760/node_modules/@octokit/plugin-rest-endpoint-methods/dist-src/index.js + return file.content + .split(/\r?\n/) + .filter(line => line && !line.startsWith('#')) + .map(pattern => applyBaseToPattern(pattern, base)); +}; +const toRelativePath = (fileOrDirectory, cwd) => { + if (external_node_path_.isAbsolute(fileOrDirectory)) { + // When paths are equal, path.relative returns empty string which is valid + // isPathInside returns false for equal paths, so check this case first + const relativePath = external_node_path_.relative(cwd, fileOrDirectory); + if (relativePath && !isPathInside(fileOrDirectory, cwd)) { + // Path is outside cwd - it cannot be ignored by patterns in cwd + // Return undefined to indicate this path is outside scope + return undefined; + } -function restEndpointMethods(octokit) { - const api = endpointsToMethods(octokit); - return { - rest: api - }; -} -restEndpointMethods.VERSION = plugin_rest_endpoint_methods_dist_src_version_VERSION; -function legacyRestEndpointMethods(octokit) { - const api = endpointsToMethods(octokit); - return { - ...api, - rest: api - }; -} -legacyRestEndpointMethods.VERSION = plugin_rest_endpoint_methods_dist_src_version_VERSION; + return relativePath; + } + + // Normalize relative paths: + // - Git treats './foo' as 'foo' when checking against patterns + // - Patterns starting with './' in .gitignore are invalid and don't match anything + // - The ignore library expects normalized paths without './' prefix + if (fileOrDirectory.startsWith('./')) { + return fileOrDirectory.slice(2); + } + + // Paths with ../ point outside cwd and cannot match patterns from this directory + // Return undefined to indicate this path is outside scope + if (fileOrDirectory.startsWith('../')) { + return undefined; + } + + return fileOrDirectory; +}; + +const createIgnorePredicate = (patterns, cwd, baseDir) => { + const ignores = ignore().add(patterns); + // Normalize to handle path separator and . / .. components consistently + const resolvedCwd = external_node_path_.normalize(external_node_path_.resolve(cwd)); + const resolvedBaseDir = external_node_path_.normalize(external_node_path_.resolve(baseDir)); + + return fileOrDirectory => { + fileOrDirectory = toPath(fileOrDirectory); + + // Never ignore the cwd itself - use normalized comparison + const normalizedPath = external_node_path_.normalize(external_node_path_.resolve(fileOrDirectory)); + if (normalizedPath === resolvedCwd) { + return false; + } + + // Convert to relative path from baseDir (use normalized baseDir) + const relativePath = toRelativePath(fileOrDirectory, resolvedBaseDir); + + // If path is outside baseDir (undefined), it can't be ignored by patterns + if (relativePath === undefined) { + return false; + } + + return relativePath ? ignores.ignores(slash(relativePath)) : false; + }; +}; + +const normalizeOptions = (options = {}) => { + const ignoreOption = options.ignore + ? (Array.isArray(options.ignore) ? options.ignore : [options.ignore]) + : []; + + const cwd = toPath(options.cwd) ?? external_node_process_namespaceObject.cwd(); + + // Adjust deep option for fast-glob: fast-glob's deep counts differently than expected + // User's deep: 0 = root only -> fast-glob needs: 1 + // User's deep: 1 = root + 1 level -> fast-glob needs: 2 + const deep = typeof options.deep === 'number' ? Math.max(0, options.deep) + 1 : Number.POSITIVE_INFINITY; + + // Only pass through specific fast-glob options that make sense for finding ignore files + return { + cwd, + suppressErrors: options.suppressErrors ?? false, + deep, + ignore: [...ignoreOption, ...defaultIgnoredDirectories], + followSymbolicLinks: options.followSymbolicLinks ?? true, + concurrency: options.concurrency, + throwErrorOnBrokenSymbolicLink: options.throwErrorOnBrokenSymbolicLink ?? false, + fs: options.fs, + }; +}; + +const collectIgnoreFileArtifactsAsync = async (patterns, options, includeParentIgnoreFiles) => { + const normalizedOptions = normalizeOptions(options); + const childPaths = await globIgnoreFiles(out, patterns, normalizedOptions); + const gitRoot = includeParentIgnoreFiles + ? await findGitRoot(normalizedOptions.cwd, normalizedOptions.fs) + : undefined; + const allPaths = combineIgnoreFilePaths(gitRoot, normalizedOptions, childPaths); + const readFileMethod = getReadFileMethod(normalizedOptions.fs); + const files = await readIgnoreFilesSafely(allPaths, readFileMethod, normalizedOptions.suppressErrors); + + return {files, normalizedOptions, gitRoot}; +}; + +const collectIgnoreFileArtifactsSync = (patterns, options, includeParentIgnoreFiles) => { + const normalizedOptions = normalizeOptions(options); + const childPaths = globIgnoreFiles(out.sync, patterns, normalizedOptions); + const gitRoot = includeParentIgnoreFiles + ? findGitRootSync(normalizedOptions.cwd, normalizedOptions.fs) + : undefined; + const allPaths = combineIgnoreFilePaths(gitRoot, normalizedOptions, childPaths); + const readFileSyncMethod = getReadFileSyncMethod(normalizedOptions.fs); + const files = readIgnoreFilesSafelySync(allPaths, readFileSyncMethod, normalizedOptions.suppressErrors); + + return {files, normalizedOptions, gitRoot}; +}; + +const isIgnoredByIgnoreFiles = async (patterns, options) => { + const {files, normalizedOptions, gitRoot} = await collectIgnoreFileArtifactsAsync(patterns, options, false); + return buildIgnoreResult(files, normalizedOptions, gitRoot).predicate; +}; + +const isIgnoredByIgnoreFilesSync = (patterns, options) => { + const {files, normalizedOptions, gitRoot} = collectIgnoreFileArtifactsSync(patterns, options, false); + return buildIgnoreResult(files, normalizedOptions, gitRoot).predicate; +}; + +const getPatternsFromIgnoreFiles = (files, baseDir) => files.flatMap(file => parseIgnoreFile(file, baseDir)); + +/** +Read ignore files and return both patterns and predicate. +This avoids reading the same files twice (once for patterns, once for filtering). + +@param {string[]} patterns - Patterns to find ignore files +@param {Object} options - Options object +@param {boolean} [includeParentIgnoreFiles=false] - Whether to search for parent .gitignore files +@returns {Promise<{patterns: string[], predicate: Function, usingGitRoot: boolean}>} +*/ +const getIgnorePatternsAndPredicate = async (patterns, options, includeParentIgnoreFiles = false) => { + const {files, normalizedOptions, gitRoot} = await collectIgnoreFileArtifactsAsync( + patterns, + options, + includeParentIgnoreFiles, + ); + + return buildIgnoreResult(files, normalizedOptions, gitRoot); +}; + +/** +Read ignore files and return both patterns and predicate (sync version). + +@param {string[]} patterns - Patterns to find ignore files +@param {Object} options - Options object +@param {boolean} [includeParentIgnoreFiles=false] - Whether to search for parent .gitignore files +@returns {{patterns: string[], predicate: Function, usingGitRoot: boolean}} +*/ +const getIgnorePatternsAndPredicateSync = (patterns, options, includeParentIgnoreFiles = false) => { + const {files, normalizedOptions, gitRoot} = collectIgnoreFileArtifactsSync( + patterns, + options, + includeParentIgnoreFiles, + ); + + return buildIgnoreResult(files, normalizedOptions, gitRoot); +}; + +const isGitIgnored = options => isIgnoredByIgnoreFiles(GITIGNORE_FILES_PATTERN, options); +const isGitIgnoredSync = options => isIgnoredByIgnoreFilesSync(GITIGNORE_FILES_PATTERN, options); + +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@/globby/16.1.0/6bc516675ca718c332e5255dae86ad14f61b2538e1af28896d50d60441df5c38/node_modules/globby/index.js + + + + + + + + + + +const assertPatternsInput = patterns => { + if (patterns.some(pattern => typeof pattern !== 'string')) { + throw new TypeError('Patterns must be a string or an array of strings'); + } +}; + +const getStatMethod = fsImplementation => + bindFsMethod(fsImplementation?.promises, 'stat') + ?? bindFsMethod(external_node_fs_namespaceObject.promises, 'stat') + ?? promisifyFsMethod(fsImplementation, 'stat'); + +const globby_getStatSyncMethod = fsImplementation => + bindFsMethod(fsImplementation, 'statSync') + ?? bindFsMethod(external_node_fs_namespaceObject, 'statSync'); + +const globby_isDirectory = async (path, fsImplementation) => { + try { + const stats = await getStatMethod(fsImplementation)(path); + return stats.isDirectory(); + } catch { + return false; + } +}; + +const isDirectorySync = (path, fsImplementation) => { + try { + const stats = globby_getStatSyncMethod(fsImplementation)(path); + return stats.isDirectory(); + } catch { + return false; + } +}; + +const normalizePathForDirectoryGlob = (filePath, cwd) => { + const path = isNegativePattern(filePath) ? filePath.slice(1) : filePath; + return external_node_path_.isAbsolute(path) ? path : external_node_path_.join(cwd, path); +}; + +const shouldExpandGlobstarDirectory = pattern => { + const match = pattern?.match(/\*\*\/([^/]+)$/); + if (!match) { + return false; + } + + const dirname = match[1]; + const hasWildcards = /[*?[\]{}]/.test(dirname); + const hasExtension = external_node_path_.extname(dirname) && !dirname.startsWith('.'); + + return !hasWildcards && !hasExtension; +}; + +const getDirectoryGlob = ({directoryPath, files, extensions}) => { + const extensionGlob = extensions?.length > 0 ? `.${extensions.length > 1 ? `{${extensions.join(',')}}` : extensions[0]}` : ''; + return files + ? files.map(file => external_node_path_.posix.join(directoryPath, `**/${external_node_path_.extname(file) ? file : `${file}${extensionGlob}`}`)) + : [external_node_path_.posix.join(directoryPath, `**${extensionGlob ? `/*${extensionGlob}` : ''}`)]; +}; + +const directoryToGlob = async (directoryPaths, { + cwd = external_node_process_namespaceObject.cwd(), + files, + extensions, + fs: fsImplementation, +} = {}) => { + const globs = await Promise.all(directoryPaths.map(async directoryPath => { + // Check pattern without negative prefix + const checkPattern = isNegativePattern(directoryPath) ? directoryPath.slice(1) : directoryPath; + + // Expand globstar directory patterns like **/dirname to **/dirname/** + if (shouldExpandGlobstarDirectory(checkPattern)) { + return getDirectoryGlob({directoryPath, files, extensions}); + } + + // Original logic for checking actual directories + const pathToCheck = normalizePathForDirectoryGlob(directoryPath, cwd); + return (await globby_isDirectory(pathToCheck, fsImplementation)) ? getDirectoryGlob({directoryPath, files, extensions}) : directoryPath; + })); + + return globs.flat(); +}; + +const directoryToGlobSync = (directoryPaths, { + cwd = external_node_process_namespaceObject.cwd(), + files, + extensions, + fs: fsImplementation, +} = {}) => directoryPaths.flatMap(directoryPath => { + // Check pattern without negative prefix + const checkPattern = isNegativePattern(directoryPath) ? directoryPath.slice(1) : directoryPath; + + // Expand globstar directory patterns like **/dirname to **/dirname/** + if (shouldExpandGlobstarDirectory(checkPattern)) { + return getDirectoryGlob({directoryPath, files, extensions}); + } + + // Original logic for checking actual directories + const pathToCheck = normalizePathForDirectoryGlob(directoryPath, cwd); + return isDirectorySync(pathToCheck, fsImplementation) ? getDirectoryGlob({directoryPath, files, extensions}) : directoryPath; +}); + +const toPatternsArray = patterns => { + patterns = [...new Set([patterns].flat())]; + assertPatternsInput(patterns); + return patterns; +}; + +const checkCwdOption = (cwd, fsImplementation = external_node_fs_namespaceObject) => { + if (!cwd || !fsImplementation.statSync) { + return; + } + + let stats; + try { + stats = fsImplementation.statSync(cwd); + } catch { + // If stat fails (e.g., path doesn't exist), let fast-glob handle it + return; + } + + if (!stats.isDirectory()) { + throw new Error(`The \`cwd\` option must be a path to a directory, got: ${cwd}`); + } +}; + +const globby_normalizeOptions = (options = {}) => { + // Normalize ignore to an array (fast-glob accepts string but we need array internally) + const ignore = options.ignore + ? (Array.isArray(options.ignore) ? options.ignore : [options.ignore]) + : []; + + options = { + ...options, + ignore, + expandDirectories: options.expandDirectories ?? true, + cwd: toPath(options.cwd), + }; + + checkCwdOption(options.cwd, options.fs); + + return options; +}; + +const normalizeArguments = function_ => async (patterns, options) => function_(toPatternsArray(patterns), globby_normalizeOptions(options)); +const normalizeArgumentsSync = function_ => (patterns, options) => function_(toPatternsArray(patterns), globby_normalizeOptions(options)); + +const getIgnoreFilesPatterns = options => { + const {ignoreFiles, gitignore} = options; + + const patterns = ignoreFiles ? toPatternsArray(ignoreFiles) : []; + if (gitignore) { + patterns.push(GITIGNORE_FILES_PATTERN); + } + + return patterns; +}; -//# sourceMappingURL=index.js.map +/** +Apply gitignore patterns to options and return filter predicate. -;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@octokit/rest/22.0.1/4c3bb74612de15a47f9dee5e98a684c7ea32d1bf8fb5361ea1471543c9284017/node_modules/@octokit/rest/dist-src/version.js -const rest_dist_src_version_VERSION = "22.0.1"; +When negation patterns are present (e.g., '!important.log'), we cannot pass positive patterns to fast-glob because it would filter out files before our predicate can re-include them. In this case, we rely entirely on the predicate for filtering, which handles negations correctly. +When there are no negations, we optimize by passing patterns to fast-glob's ignore option to skip directories during traversal (performance optimization). -;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@octokit/rest/22.0.1/4c3bb74612de15a47f9dee5e98a684c7ea32d1bf8fb5361ea1471543c9284017/node_modules/@octokit/rest/dist-src/index.js +All patterns (including negated) are always used in the filter predicate to ensure correct Git-compatible behavior. +@returns {Promise<{options: Object, filter: Function}>} +*/ +const applyIgnoreFilesAndGetFilter = async options => { + const ignoreFilesPatterns = getIgnoreFilesPatterns(options); + if (ignoreFilesPatterns.length === 0) { + return { + options, + filter: createFilterFunction(false, options.cwd), + }; + } + // Read ignore files once and get both patterns and predicate + // Enable parent .gitignore search when using gitignore option + const includeParentIgnoreFiles = options.gitignore === true; + const {patterns, predicate, usingGitRoot} = await getIgnorePatternsAndPredicate(ignoreFilesPatterns, options, includeParentIgnoreFiles); + // Convert patterns to fast-glob format (may return empty array if predicate should handle everything) + const patternsForFastGlob = convertPatternsForFastGlob(patterns, usingGitRoot, normalizeDirectoryPatternForFastGlob); -const dist_src_Octokit = Octokit.plugin(requestLog, legacyRestEndpointMethods, paginateRest).defaults( - { - userAgent: `octokit-rest.js/${rest_dist_src_version_VERSION}` - } -); + const modifiedOptions = { + ...options, + ignore: [...options.ignore, ...patternsForFastGlob], + }; + return { + options: modifiedOptions, + filter: createFilterFunction(predicate, options.cwd), + }; +}; +/** +Apply gitignore patterns to options and return filter predicate (sync version). -/***/ }), +@returns {{options: Object, filter: Function}} +*/ +const applyIgnoreFilesAndGetFilterSync = options => { + const ignoreFilesPatterns = getIgnoreFilesPatterns(options); -/***/ 6875: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nccwpck_require__) => { - -"use strict"; -// ESM COMPAT FLAG -__nccwpck_require__.r(__webpack_exports__); - -// EXPORTS -__nccwpck_require__.d(__webpack_exports__, { - convertPathToPattern: () => (/* binding */ convertPathToPattern), - generateGlobTasks: () => (/* binding */ generateGlobTasks), - generateGlobTasksSync: () => (/* binding */ generateGlobTasksSync), - globby: () => (/* binding */ globby), - globbyStream: () => (/* binding */ globbyStream), - globbySync: () => (/* binding */ globbySync), - isDynamicPattern: () => (/* binding */ isDynamicPattern), - isGitIgnored: () => (/* reexport */ isGitIgnored), - isGitIgnoredSync: () => (/* reexport */ isGitIgnoredSync), - isIgnoredByIgnoreFiles: () => (/* reexport */ isIgnoredByIgnoreFiles), - isIgnoredByIgnoreFilesSync: () => (/* reexport */ isIgnoredByIgnoreFilesSync) -}); + if (ignoreFilesPatterns.length === 0) { + return { + options, + filter: createFilterFunction(false, options.cwd), + }; + } -;// CONCATENATED MODULE: external "node:process" -const external_node_process_namespaceObject = require("node:process"); -// EXTERNAL MODULE: external "node:fs" -var external_node_fs_ = __nccwpck_require__(3024); -// EXTERNAL MODULE: external "node:path" -var external_node_path_ = __nccwpck_require__(4379); -// EXTERNAL MODULE: external "node:stream" -var external_node_stream_ = __nccwpck_require__(7075); -// EXTERNAL MODULE: external "node:events" -var external_node_events_ = __nccwpck_require__(8474); -;// CONCATENATED MODULE: external "node:stream/promises" -const promises_namespaceObject = require("node:stream/promises"); -;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@sindresorhus/merge-streams/4.0.0/8e693ab70e031a19d1b7bae684db249220a2cb4faf41f63d8ac2c81a3ef13edb/node_modules/@sindresorhus/merge-streams/index.js + // Read ignore files once and get both patterns and predicate + // Enable parent .gitignore search when using gitignore option + const includeParentIgnoreFiles = options.gitignore === true; + const {patterns, predicate, usingGitRoot} = getIgnorePatternsAndPredicateSync(ignoreFilesPatterns, options, includeParentIgnoreFiles); + // Convert patterns to fast-glob format (may return empty array if predicate should handle everything) + const patternsForFastGlob = convertPatternsForFastGlob(patterns, usingGitRoot, normalizeDirectoryPatternForFastGlob); + const modifiedOptions = { + ...options, + ignore: [...options.ignore, ...patternsForFastGlob], + }; + return { + options: modifiedOptions, + filter: createFilterFunction(predicate, options.cwd), + }; +}; -function mergeStreams(streams) { - if (!Array.isArray(streams)) { - throw new TypeError(`Expected an array, got \`${typeof streams}\`.`); - } +const createFilterFunction = (isIgnored, cwd) => { + const seen = new Set(); + const basePath = cwd || external_node_process_namespaceObject.cwd(); + const pathCache = new Map(); // Cache for resolved paths - for (const stream of streams) { - validateStream(stream); - } + return fastGlobResult => { + const pathKey = external_node_path_.normalize(fastGlobResult.path ?? fastGlobResult); - const objectMode = streams.some(({readableObjectMode}) => readableObjectMode); - const highWaterMark = getHighWaterMark(streams, objectMode); - const passThroughStream = new MergedStream({ - objectMode, - writableHighWaterMark: highWaterMark, - readableHighWaterMark: highWaterMark, - }); + // Check seen set first (fast path) + if (seen.has(pathKey)) { + return false; + } - for (const stream of streams) { - passThroughStream.add(stream); - } + // Only compute absolute path and check predicate if needed + if (isIgnored) { + let absolutePath = pathCache.get(pathKey); + if (absolutePath === undefined) { + absolutePath = external_node_path_.isAbsolute(pathKey) ? pathKey : external_node_path_.resolve(basePath, pathKey); + pathCache.set(pathKey, absolutePath); - return passThroughStream; -} + // Only clear path cache if it gets too large + // Never clear 'seen' as it's needed for deduplication + if (pathCache.size > 10_000) { + pathCache.clear(); + } + } -const getHighWaterMark = (streams, objectMode) => { - if (streams.length === 0) { - return (0,external_node_stream_.getDefaultHighWaterMark)(objectMode); - } + if (isIgnored(absolutePath)) { + return false; + } + } - const highWaterMarks = streams - .filter(({readableObjectMode}) => readableObjectMode === objectMode) - .map(({readableHighWaterMark}) => readableHighWaterMark); - return Math.max(...highWaterMarks); + seen.add(pathKey); + return true; + }; }; -class MergedStream extends external_node_stream_.PassThrough { - #streams = new Set([]); - #ended = new Set([]); - #aborted = new Set([]); - #onFinished; - #unpipeEvent = Symbol('unpipe'); - #streamPromises = new WeakMap(); - - add(stream) { - validateStream(stream); +const unionFastGlobResults = (results, filter) => results.flat().filter(fastGlobResult => filter(fastGlobResult)); - if (this.#streams.has(stream)) { - return; +const convertNegativePatterns = (patterns, options) => { + // If all patterns are negative and expandNegationOnlyPatterns is enabled (default), + // prepend a positive catch-all pattern to make negation-only patterns work intuitively + // (e.g., '!*.json' matches all files except JSON) + if (patterns.length > 0 && patterns.every(pattern => isNegativePattern(pattern))) { + if (options.expandNegationOnlyPatterns === false) { + return []; } - this.#streams.add(stream); + patterns = ['**/*', ...patterns]; + } - this.#onFinished ??= onMergedStreamFinished(this, this.#streams, this.#unpipeEvent); - const streamPromise = endWhenStreamsDone({ - passThroughStream: this, - stream, - streams: this.#streams, - ended: this.#ended, - aborted: this.#aborted, - onFinished: this.#onFinished, - unpipeEvent: this.#unpipeEvent, - }); - this.#streamPromises.set(stream, streamPromise); + patterns = patterns.map(pattern => isNegativePattern(pattern) + ? `!${normalizeAbsolutePatternToRelative(pattern.slice(1))}` + : pattern); - stream.pipe(this, {end: false}); - } + const tasks = []; - async remove(stream) { - validateStream(stream); + while (patterns.length > 0) { + const index = patterns.findIndex(pattern => isNegativePattern(pattern)); - if (!this.#streams.has(stream)) { - return false; + if (index === -1) { + tasks.push({patterns, options}); + break; } - const streamPromise = this.#streamPromises.get(stream); - if (streamPromise === undefined) { - return false; + const ignorePattern = patterns[index].slice(1); + + for (const task of tasks) { + task.options.ignore.push(ignorePattern); } - this.#streamPromises.delete(stream); + if (index !== 0) { + tasks.push({ + patterns: patterns.slice(0, index), + options: { + ...options, + ignore: [ + ...options.ignore, + ignorePattern, + ], + }, + }); + } - stream.unpipe(this); - await streamPromise; - return true; + patterns = patterns.slice(index + 1); } -} - -const onMergedStreamFinished = async (passThroughStream, streams, unpipeEvent) => { - updateMaxListeners(passThroughStream, PASSTHROUGH_LISTENERS_COUNT); - const controller = new AbortController(); - try { - await Promise.race([ - onMergedStreamEnd(passThroughStream, controller), - onInputStreamsUnpipe(passThroughStream, streams, unpipeEvent, controller), - ]); - } finally { - controller.abort(); - updateMaxListeners(passThroughStream, -PASSTHROUGH_LISTENERS_COUNT); - } + return tasks; }; -const onMergedStreamEnd = async (passThroughStream, {signal}) => { - try { - await (0,promises_namespaceObject.finished)(passThroughStream, {signal, cleanup: true}); - } catch (error) { - errorOrAbortStream(passThroughStream, error); - throw error; - } -}; +const applyParentDirectoryIgnoreAdjustments = tasks => tasks.map(task => ({ + patterns: task.patterns, + options: { + ...task.options, + ignore: adjustIgnorePatternsForParentDirectories(task.patterns, task.options.ignore), + }, +})); -const onInputStreamsUnpipe = async (passThroughStream, streams, unpipeEvent, {signal}) => { - for await (const [unpipedStream] of (0,external_node_events_.on)(passThroughStream, 'unpipe', {signal})) { - if (streams.has(unpipedStream)) { - unpipedStream.emit(unpipeEvent); - } - } -}; +const normalizeExpandDirectoriesOption = (options, cwd) => ({ + ...(cwd ? {cwd} : {}), + ...(Array.isArray(options) ? {files: options} : options), +}); -const validateStream = stream => { - if (typeof stream?.pipe !== 'function') { - throw new TypeError(`Expected a readable stream, got: \`${typeof stream}\`.`); +const generateTasks = async (patterns, options) => { + const globTasks = convertNegativePatterns(patterns, options); + + const {cwd, expandDirectories, fs: fsImplementation} = options; + + if (!expandDirectories) { + return applyParentDirectoryIgnoreAdjustments(globTasks); } -}; -const endWhenStreamsDone = async ({passThroughStream, stream, streams, ended, aborted, onFinished, unpipeEvent}) => { - updateMaxListeners(passThroughStream, PASSTHROUGH_LISTENERS_PER_STREAM); - const controller = new AbortController(); + const directoryToGlobOptions = { + ...normalizeExpandDirectoriesOption(expandDirectories, cwd), + fs: fsImplementation, + }; - try { - await Promise.race([ - afterMergedStreamFinished(onFinished, stream, controller), - onInputStreamEnd({ - passThroughStream, - stream, - streams, - ended, - aborted, - controller, - }), - onInputStreamUnpipe({ - stream, - streams, - ended, - aborted, - unpipeEvent, - controller, - }), + return Promise.all(globTasks.map(async task => { + let {patterns, options} = task; + + [ + patterns, + options.ignore, + ] = await Promise.all([ + directoryToGlob(patterns, directoryToGlobOptions), + directoryToGlob(options.ignore, {cwd, fs: fsImplementation}), ]); - } finally { - controller.abort(); - updateMaxListeners(passThroughStream, -PASSTHROUGH_LISTENERS_PER_STREAM); - } - if (streams.size > 0 && streams.size === ended.size + aborted.size) { - if (ended.size === 0 && aborted.size > 0) { - abortStream(passThroughStream); - } else { - endStream(passThroughStream); - } - } -}; + // Adjust ignore patterns for parent directory references + options.ignore = adjustIgnorePatternsForParentDirectories(patterns, options.ignore); -const afterMergedStreamFinished = async (onFinished, stream, {signal}) => { - try { - await onFinished; - if (!signal.aborted) { - abortStream(stream); - } - } catch (error) { - if (!signal.aborted) { - errorOrAbortStream(stream, error); - } - } + return {patterns, options}; + })); }; -const onInputStreamEnd = async ({passThroughStream, stream, streams, ended, aborted, controller: {signal}}) => { - try { - await (0,promises_namespaceObject.finished)(stream, { - signal, - cleanup: true, - readable: true, - writable: false, - }); - if (streams.has(stream)) { - ended.add(stream); - } - } catch (error) { - if (signal.aborted || !streams.has(stream)) { - return; - } +const generateTasksSync = (patterns, options) => { + const globTasks = convertNegativePatterns(patterns, options); + const {cwd, expandDirectories, fs: fsImplementation} = options; - if (isAbortError(error)) { - aborted.add(stream); - } else { - errorStream(passThroughStream, error); - } + if (!expandDirectories) { + return applyParentDirectoryIgnoreAdjustments(globTasks); } -}; -const onInputStreamUnpipe = async ({stream, streams, ended, aborted, unpipeEvent, controller: {signal}}) => { - await (0,external_node_events_.once)(stream, unpipeEvent, {signal}); + const directoryToGlobSyncOptions = { + ...normalizeExpandDirectoriesOption(expandDirectories, cwd), + fs: fsImplementation, + }; - if (!stream.readable) { - return (0,external_node_events_.once)(signal, 'abort', {signal}); - } + return globTasks.map(task => { + let {patterns, options} = task; + patterns = directoryToGlobSync(patterns, directoryToGlobSyncOptions); + options.ignore = directoryToGlobSync(options.ignore, {cwd, fs: fsImplementation}); - streams.delete(stream); - ended.delete(stream); - aborted.delete(stream); -}; + // Adjust ignore patterns for parent directory references + options.ignore = adjustIgnorePatternsForParentDirectories(patterns, options.ignore); -const endStream = stream => { - if (stream.writable) { - stream.end(); - } + return {patterns, options}; + }); }; -const errorOrAbortStream = (stream, error) => { - if (isAbortError(error)) { - abortStream(stream); - } else { - errorStream(stream, error); +const globby = normalizeArguments(async (patterns, options) => { + // Apply ignore files and get filter (reads .gitignore files once) + const {options: modifiedOptions, filter} = await applyIgnoreFilesAndGetFilter(options); + + // Generate tasks with modified options (includes gitignore patterns in ignore option) + const tasks = await generateTasks(patterns, modifiedOptions); + + const results = await Promise.all(tasks.map(task => out(task.patterns, task.options))); + return unionFastGlobResults(results, filter); +}); + +const globbySync = normalizeArgumentsSync((patterns, options) => { + // Apply ignore files and get filter (reads .gitignore files once) + const {options: modifiedOptions, filter} = applyIgnoreFilesAndGetFilterSync(options); + + // Generate tasks with modified options (includes gitignore patterns in ignore option) + const tasks = generateTasksSync(patterns, modifiedOptions); + + const results = tasks.map(task => out.sync(task.patterns, task.options)); + return unionFastGlobResults(results, filter); +}); + +const globbyStream = normalizeArgumentsSync((patterns, options) => { + // Apply ignore files and get filter (reads .gitignore files once) + const {options: modifiedOptions, filter} = applyIgnoreFilesAndGetFilterSync(options); + + // Generate tasks with modified options (includes gitignore patterns in ignore option) + const tasks = generateTasksSync(patterns, modifiedOptions); + + const streams = tasks.map(task => out.stream(task.patterns, task.options)); + + if (streams.length === 0) { + return external_node_stream_.Readable.from([]); } + + const stream = mergeStreams(streams).filter(fastGlobResult => filter(fastGlobResult)); + + // Returning a web stream will require revisiting once Readable.toWeb integration is viable. + // return Readable.toWeb(stream); + + return stream; +}); + +const isDynamicPattern = normalizeArgumentsSync((patterns, options) => patterns.some(pattern => out.isDynamicPattern(pattern, options))); + +const generateGlobTasks = normalizeArguments(generateTasks); +const generateGlobTasksSync = normalizeArgumentsSync(generateTasksSync); + + + +const {convertPathToPattern} = out; + +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@actions/tool-cache/4.0.0/3b5b52c98bff9e0e9d2d58cde49fce9e5744ca098973f1a341bc1c27eefdda47/node_modules/@actions/tool-cache/lib/manifest.js +var manifest_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); }; -// This is the error thrown by `finished()` on `stream.destroy()` -const isAbortError = error => error?.code === 'ERR_STREAM_PREMATURE_CLOSE'; -const abortStream = stream => { - if (stream.readable || stream.writable) { - stream.destroy(); - } + + + +// Internal object for testability (allows mocking in ESM) +const _internal = { + readLinuxVersionFile() { + const lsbReleaseFile = '/etc/lsb-release'; + const osReleaseFile = '/etc/os-release'; + let contents = ''; + if (external_fs_.existsSync(lsbReleaseFile)) { + contents = external_fs_.readFileSync(lsbReleaseFile).toString(); + } + else if (external_fs_.existsSync(osReleaseFile)) { + contents = external_fs_.readFileSync(osReleaseFile).toString(); + } + return contents; + } +}; +function _findMatch(versionSpec, stable, candidates, archFilter) { + return manifest_awaiter(this, void 0, void 0, function* () { + const platFilter = os.platform(); + let result; + let match; + let file; + for (const candidate of candidates) { + const version = candidate.version; + debug(`check ${version} satisfies ${versionSpec}`); + if (semver.satisfies(version, versionSpec) && + (!stable || candidate.stable === stable)) { + file = candidate.files.find(item => { + debug(`${item.arch}===${archFilter} && ${item.platform}===${platFilter}`); + let chk = item.arch === archFilter && item.platform === platFilter; + if (chk && item.platform_version) { + const osVersion = _getOsVersion(); + if (osVersion === item.platform_version) { + chk = true; + } + else { + chk = semver.satisfies(osVersion, item.platform_version); + } + } + return chk; + }); + if (file) { + debug(`matched ${candidate.version}`); + match = candidate; + break; + } + } + } + if (match && file) { + // clone since we're mutating the file list to be only the file that matches + result = Object.assign({}, match); + result.files = [file]; + } + return result; + }); +} +function _getOsVersion() { + // TODO: add windows and other linux, arm variants + // right now filtering on version is only an ubuntu and macos scenario for tools we build for hosted (python) + const plat = os.platform(); + let version = ''; + if (plat === 'darwin') { + version = cp.execSync('sw_vers -productVersion').toString(); + } + else if (plat === 'linux') { + // lsb_release process not in some containers, readfile + // Run cat /etc/lsb-release + // DISTRIB_ID=Ubuntu + // DISTRIB_RELEASE=18.04 + // DISTRIB_CODENAME=bionic + // DISTRIB_DESCRIPTION="Ubuntu 18.04.4 LTS" + const lsbContents = _internal.readLinuxVersionFile(); + if (lsbContents) { + const lines = lsbContents.split('\n'); + for (const line of lines) { + const parts = line.split('='); + if (parts.length === 2 && + (parts[0].trim() === 'VERSION_ID' || + parts[0].trim() === 'DISTRIB_RELEASE')) { + version = parts[1].trim().replace(/^"/, '').replace(/"$/, ''); + break; + } + } + } + } + return version; +} +// Alias for backwards compatibility +function _readLinuxVersionFile() { + return _internal.readLinuxVersionFile(); +} +//# sourceMappingURL=manifest.js.map +// EXTERNAL MODULE: external "stream" +var external_stream_ = __nccwpck_require__(2203); +// EXTERNAL MODULE: external "util" +var external_util_ = __nccwpck_require__(9023); +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@actions/tool-cache/4.0.0/3b5b52c98bff9e0e9d2d58cde49fce9e5744ca098973f1a341bc1c27eefdda47/node_modules/@actions/tool-cache/lib/retry-helper.js +var retry_helper_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); }; -// `stream.destroy(error)` crashes the process with `uncaughtException` if no `error` event listener exists on `stream`. -// We take care of error handling on user behalf, so we do not want this to happen. -const errorStream = (stream, error) => { - if (!stream.destroyed) { - stream.once('error', noop); - stream.destroy(error); - } +/** + * Internal class for retries + */ +class RetryHelper { + constructor(maxAttempts, minSeconds, maxSeconds) { + if (maxAttempts < 1) { + throw new Error('max attempts should be greater than or equal to 1'); + } + this.maxAttempts = maxAttempts; + this.minSeconds = Math.floor(minSeconds); + this.maxSeconds = Math.floor(maxSeconds); + if (this.minSeconds > this.maxSeconds) { + throw new Error('min seconds should be less than or equal to max seconds'); + } + } + execute(action, isRetryable) { + return retry_helper_awaiter(this, void 0, void 0, function* () { + let attempt = 1; + while (attempt < this.maxAttempts) { + // Try + try { + return yield action(); + } + catch (err) { + if (isRetryable && !isRetryable(err)) { + throw err; + } + info(err.message); + } + // Sleep + const seconds = this.getSleepAmount(); + info(`Waiting ${seconds} seconds before trying again`); + yield this.sleep(seconds); + attempt++; + } + // Last attempt + return yield action(); + }); + } + getSleepAmount() { + return (Math.floor(Math.random() * (this.maxSeconds - this.minSeconds + 1)) + + this.minSeconds); + } + sleep(seconds) { + return retry_helper_awaiter(this, void 0, void 0, function* () { + return new Promise(resolve => setTimeout(resolve, seconds * 1000)); + }); + } +} +//# sourceMappingURL=retry-helper.js.map +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@actions/tool-cache/4.0.0/3b5b52c98bff9e0e9d2d58cde49fce9e5744ca098973f1a341bc1c27eefdda47/node_modules/@actions/tool-cache/lib/tool-cache.js +var tool_cache_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); }; -const noop = () => {}; -const updateMaxListeners = (passThroughStream, increment) => { - const maxListeners = passThroughStream.getMaxListeners(); - if (maxListeners !== 0 && maxListeners !== Number.POSITIVE_INFINITY) { - passThroughStream.setMaxListeners(maxListeners + increment); - } -}; -// Number of times `passThroughStream.on()` is called regardless of streams: -// - once due to `finished(passThroughStream)` -// - once due to `on(passThroughStream)` -const PASSTHROUGH_LISTENERS_COUNT = 2; -// Number of times `passThroughStream.on()` is called per stream: -// - once due to `stream.pipe(passThroughStream)` -const PASSTHROUGH_LISTENERS_PER_STREAM = 1; -// EXTERNAL MODULE: ../../../Library/pnpm/store/v10/links/fast-glob/3.3.3/4d7c9438b037a74bda80749d8ebeda290d818194756f22a5acf6cc000a4547b8/node_modules/fast-glob/out/index.js -var out = __nccwpck_require__(7469); -// EXTERNAL MODULE: external "node:util" -var external_node_util_ = __nccwpck_require__(7975); -;// CONCATENATED MODULE: external "node:child_process" -const external_node_child_process_namespaceObject = require("node:child_process"); -;// CONCATENATED MODULE: external "node:url" -const external_node_url_namespaceObject = require("node:url"); -;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/unicorn-magic/0.4.0/1557576fdcd95b77d110542b8071399275704dbe8ac6be0eb972573bead0ee0e/node_modules/unicorn-magic/node.js -const execFileOriginal = (0,external_node_util_.promisify)(external_node_child_process_namespaceObject.execFile); -function toPath(urlOrPath) { - return urlOrPath instanceof URL ? (0,external_node_url_namespaceObject.fileURLToPath)(urlOrPath) : urlOrPath; -} -function rootDirectory(pathInput) { - return path.parse(toPath(pathInput)).root; -} -function traversePathUp(startPath) { - return { - * [Symbol.iterator]() { - let currentPath = path.resolve(toPath(startPath)); - let previousPath; - while (previousPath !== currentPath) { - yield currentPath; - previousPath = currentPath; - currentPath = path.resolve(currentPath, '..'); - } - }, - }; +class HTTPError extends Error { + constructor(httpStatusCode) { + super(`Unexpected HTTP response: ${httpStatusCode}`); + this.httpStatusCode = httpStatusCode; + Object.setPrototypeOf(this, new.target.prototype); + } +} +const tool_cache_IS_WINDOWS = process.platform === 'win32'; +const IS_MAC = process.platform === 'darwin'; +const userAgent = 'actions/tool-cache'; +/** + * Download a tool from an url and stream it into a file + * + * @param url url of tool to download + * @param dest path to download tool + * @param auth authorization header + * @param headers other headers + * @returns path to downloaded tool + */ +function downloadTool(url, dest, auth, headers) { + return tool_cache_awaiter(this, void 0, void 0, function* () { + dest = dest || external_path_.join(_getTempDirectory(), external_crypto_namespaceObject.randomUUID()); + yield mkdirP(external_path_.dirname(dest)); + core_debug(`Downloading ${url}`); + core_debug(`Destination ${dest}`); + const maxAttempts = 3; + const minSeconds = _getGlobal('TEST_DOWNLOAD_TOOL_RETRY_MIN_SECONDS', 10); + const maxSeconds = _getGlobal('TEST_DOWNLOAD_TOOL_RETRY_MAX_SECONDS', 20); + const retryHelper = new RetryHelper(maxAttempts, minSeconds, maxSeconds); + return yield retryHelper.execute(() => tool_cache_awaiter(this, void 0, void 0, function* () { + return yield downloadToolAttempt(url, dest || '', auth, headers); + }), (err) => { + if (err instanceof HTTPError && err.httpStatusCode) { + // Don't retry anything less than 500, except 408 Request Timeout and 429 Too Many Requests + if (err.httpStatusCode < 500 && + err.httpStatusCode !== 408 && + err.httpStatusCode !== 429) { + return false; + } + } + // Otherwise retry + return true; + }); + }); +} +function downloadToolAttempt(url, dest, auth, headers) { + return tool_cache_awaiter(this, void 0, void 0, function* () { + if (external_fs_.existsSync(dest)) { + throw new Error(`Destination file path ${dest} already exists`); + } + // Get the response headers + const http = new lib_HttpClient(userAgent, [], { + allowRetries: false + }); + if (auth) { + core_debug('set auth'); + if (headers === undefined) { + headers = {}; + } + headers.authorization = auth; + } + const response = yield http.get(url, headers); + if (response.message.statusCode !== 200) { + const err = new HTTPError(response.message.statusCode); + core_debug(`Failed to download from "${url}". Code(${response.message.statusCode}) Message(${response.message.statusMessage})`); + throw err; + } + // Download the response body + const pipeline = external_util_.promisify(external_stream_.pipeline); + const responseMessageFactory = _getGlobal('TEST_DOWNLOAD_TOOL_RESPONSE_MESSAGE_FACTORY', () => response.message); + const readStream = responseMessageFactory(); + let succeeded = false; + try { + yield pipeline(readStream, external_fs_.createWriteStream(dest)); + core_debug('download complete'); + succeeded = true; + return dest; + } + finally { + // Error, delete dest before retry + if (!succeeded) { + core_debug('download failed'); + try { + yield rmRF(dest); + } + catch (err) { + core_debug(`Failed to delete '${dest}'. ${err.message}`); + } + } + } + }); +} +/** + * Extract a .7z file + * + * @param file path to the .7z file + * @param dest destination directory. Optional. + * @param _7zPath path to 7zr.exe. Optional, for long path support. Most .7z archives do not have this + * problem. If your .7z archive contains very long paths, you can pass the path to 7zr.exe which will + * gracefully handle long paths. By default 7zdec.exe is used because it is a very small program and is + * bundled with the tool lib. However it does not support long paths. 7zr.exe is the reduced command line + * interface, it is smaller than the full command line interface, and it does support long paths. At the + * time of this writing, it is freely available from the LZMA SDK that is available on the 7zip website. + * Be sure to check the current license agreement. If 7zr.exe is bundled with your action, then the path + * to 7zr.exe can be pass to this function. + * @returns path to the destination directory + */ +function extract7z(file, dest, _7zPath) { + return tool_cache_awaiter(this, void 0, void 0, function* () { + ok(tool_cache_IS_WINDOWS, 'extract7z() not supported on current OS'); + ok(file, 'parameter "file" is required'); + dest = yield _createExtractFolder(dest); + const originalCwd = process.cwd(); + process.chdir(dest); + if (_7zPath) { + try { + const logLevel = core.isDebug() ? '-bb1' : '-bb0'; + const args = [ + 'x', // eXtract files with full paths + logLevel, // -bb[0-3] : set output log level + '-bd', // disable progress indicator + '-sccUTF-8', // set charset for for console input/output + file + ]; + const options = { + silent: true + }; + yield exec(`"${_7zPath}"`, args, options); + } + finally { + process.chdir(originalCwd); + } + } + else { + const escapedScript = path + .join(__dirname, '..', 'scripts', 'Invoke-7zdec.ps1') + .replace(/'/g, "''") + .replace(/"|\n|\r/g, ''); // double-up single quotes, remove double quotes and newlines + const escapedFile = file.replace(/'/g, "''").replace(/"|\n|\r/g, ''); + const escapedTarget = dest.replace(/'/g, "''").replace(/"|\n|\r/g, ''); + const command = `& '${escapedScript}' -Source '${escapedFile}' -Target '${escapedTarget}'`; + const args = [ + '-NoLogo', + '-Sta', + '-NoProfile', + '-NonInteractive', + '-ExecutionPolicy', + 'Unrestricted', + '-Command', + command + ]; + const options = { + silent: true + }; + try { + const powershellPath = yield io.which('powershell', true); + yield exec(`"${powershellPath}"`, args, options); + } + finally { + process.chdir(originalCwd); + } + } + return dest; + }); +} +/** + * Extract a compressed tar archive + * + * @param file path to the tar + * @param dest destination directory. Optional. + * @param flags flags for the tar command to use for extraction. Defaults to 'xz' (extracting gzipped tars). Optional. + * @returns path to the destination directory + */ +function extractTar(file_1, dest_1) { + return tool_cache_awaiter(this, arguments, void 0, function* (file, dest, flags = 'xz') { + if (!file) { + throw new Error("parameter 'file' is required"); + } + // Create dest + dest = yield _createExtractFolder(dest); + // Determine whether GNU tar + core_debug('Checking tar --version'); + let versionOutput = ''; + yield exec_exec('tar --version', [], { + ignoreReturnCode: true, + silent: true, + listeners: { + stdout: (data) => (versionOutput += data.toString()), + stderr: (data) => (versionOutput += data.toString()) + } + }); + core_debug(versionOutput.trim()); + const isGnuTar = versionOutput.toUpperCase().includes('GNU TAR'); + // Initialize args + let args; + if (flags instanceof Array) { + args = flags; + } + else { + args = [flags]; + } + if (isDebug() && !flags.includes('v')) { + args.push('-v'); + } + let destArg = dest; + let fileArg = file; + if (tool_cache_IS_WINDOWS && isGnuTar) { + args.push('--force-local'); + destArg = dest.replace(/\\/g, '/'); + // Technically only the dest needs to have `/` but for aesthetic consistency + // convert slashes in the file arg too. + fileArg = file.replace(/\\/g, '/'); + } + if (isGnuTar) { + // Suppress warnings when using GNU tar to extract archives created by BSD tar + args.push('--warning=no-unknown-keyword'); + args.push('--overwrite'); + } + args.push('-C', destArg, '-f', fileArg); + yield exec_exec(`tar`, args); + return dest; + }); +} +/** + * Extract a xar compatible archive + * + * @param file path to the archive + * @param dest destination directory. Optional. + * @param flags flags for the xar. Optional. + * @returns path to the destination directory + */ +function extractXar(file_1, dest_1) { + return tool_cache_awaiter(this, arguments, void 0, function* (file, dest, flags = []) { + ok(IS_MAC, 'extractXar() not supported on current OS'); + ok(file, 'parameter "file" is required'); + dest = yield _createExtractFolder(dest); + let args; + if (flags instanceof Array) { + args = flags; + } + else { + args = [flags]; + } + args.push('-x', '-C', dest, '-f', file); + if (core.isDebug()) { + args.push('-v'); + } + const xarPath = yield io.which('xar', true); + yield exec(`"${xarPath}"`, _unique(args)); + return dest; + }); +} +/** + * Extract a zip + * + * @param file path to the zip + * @param dest destination directory. Optional. + * @returns path to the destination directory + */ +function extractZip(file, dest) { + return tool_cache_awaiter(this, void 0, void 0, function* () { + if (!file) { + throw new Error("parameter 'file' is required"); + } + dest = yield _createExtractFolder(dest); + if (tool_cache_IS_WINDOWS) { + yield extractZipWin(file, dest); + } + else { + yield extractZipNix(file, dest); + } + return dest; + }); +} +function extractZipWin(file, dest) { + return tool_cache_awaiter(this, void 0, void 0, function* () { + // build the powershell command + const escapedFile = file.replace(/'/g, "''").replace(/"|\n|\r/g, ''); // double-up single quotes, remove double quotes and newlines + const escapedDest = dest.replace(/'/g, "''").replace(/"|\n|\r/g, ''); + const pwshPath = yield which('pwsh', false); + //To match the file overwrite behavior on nix systems, we use the overwrite = true flag for ExtractToDirectory + //and the -Force flag for Expand-Archive as a fallback + if (pwshPath) { + //attempt to use pwsh with ExtractToDirectory, if this fails attempt Expand-Archive + const pwshCommand = [ + `$ErrorActionPreference = 'Stop' ;`, + `try { Add-Type -AssemblyName System.IO.Compression.ZipFile } catch { } ;`, + `try { [System.IO.Compression.ZipFile]::ExtractToDirectory('${escapedFile}', '${escapedDest}', $true) }`, + `catch { if (($_.Exception.GetType().FullName -eq 'System.Management.Automation.MethodException') -or ($_.Exception.GetType().FullName -eq 'System.Management.Automation.RuntimeException') ){ Expand-Archive -LiteralPath '${escapedFile}' -DestinationPath '${escapedDest}' -Force } else { throw $_ } } ;` + ].join(' '); + const args = [ + '-NoLogo', + '-NoProfile', + '-NonInteractive', + '-ExecutionPolicy', + 'Unrestricted', + '-Command', + pwshCommand + ]; + core_debug(`Using pwsh at path: ${pwshPath}`); + yield exec_exec(`"${pwshPath}"`, args); + } + else { + const powershellCommand = [ + `$ErrorActionPreference = 'Stop' ;`, + `try { Add-Type -AssemblyName System.IO.Compression.FileSystem } catch { } ;`, + `if ((Get-Command -Name Expand-Archive -Module Microsoft.PowerShell.Archive -ErrorAction Ignore)) { Expand-Archive -LiteralPath '${escapedFile}' -DestinationPath '${escapedDest}' -Force }`, + `else {[System.IO.Compression.ZipFile]::ExtractToDirectory('${escapedFile}', '${escapedDest}', $true) }` + ].join(' '); + const args = [ + '-NoLogo', + '-Sta', + '-NoProfile', + '-NonInteractive', + '-ExecutionPolicy', + 'Unrestricted', + '-Command', + powershellCommand + ]; + const powershellPath = yield which('powershell', true); + core_debug(`Using powershell at path: ${powershellPath}`); + yield exec_exec(`"${powershellPath}"`, args); + } + }); +} +function extractZipNix(file, dest) { + return tool_cache_awaiter(this, void 0, void 0, function* () { + const unzipPath = yield which('unzip', true); + const args = [file]; + if (!isDebug()) { + args.unshift('-q'); + } + args.unshift('-o'); //overwrite with -o, otherwise a prompt is shown which freezes the run + yield exec_exec(`"${unzipPath}"`, args, { cwd: dest }); + }); +} +/** + * Caches a directory and installs it into the tool cacheDir + * + * @param sourceDir the directory to cache into tools + * @param tool tool name + * @param version version of the tool. semver format + * @param arch architecture of the tool. Optional. Defaults to machine architecture + */ +function cacheDir(sourceDir, tool, version, arch) { + return tool_cache_awaiter(this, void 0, void 0, function* () { + version = node_modules_semver.clean(version) || version; + arch = arch || external_os_.arch(); + core_debug(`Caching tool ${tool} ${version} ${arch}`); + core_debug(`source dir: ${sourceDir}`); + if (!external_fs_.statSync(sourceDir).isDirectory()) { + throw new Error('sourceDir is not a directory'); + } + // Create the tool dir + const destPath = yield _createToolPath(tool, version, arch); + // copy each child item. do not move. move can fail on Windows + // due to anti-virus software having an open handle on a file. + for (const itemName of external_fs_.readdirSync(sourceDir)) { + const s = external_path_.join(sourceDir, itemName); + yield io_cp(s, destPath, { recursive: true }); + } + // write .complete + _completeToolPath(tool, version, arch); + return destPath; + }); +} +/** + * Caches a downloaded file (GUID) and installs it + * into the tool cache with a given targetName + * + * @param sourceFile the file to cache into tools. Typically a result of downloadTool which is a guid. + * @param targetFile the name of the file name in the tools directory + * @param tool tool name + * @param version version of the tool. semver format + * @param arch architecture of the tool. Optional. Defaults to machine architecture + */ +function cacheFile(sourceFile, targetFile, tool, version, arch) { + return tool_cache_awaiter(this, void 0, void 0, function* () { + version = semver.clean(version) || version; + arch = arch || os.arch(); + core.debug(`Caching tool ${tool} ${version} ${arch}`); + core.debug(`source file: ${sourceFile}`); + if (!fs.statSync(sourceFile).isFile()) { + throw new Error('sourceFile is not a file'); + } + // create the tool dir + const destFolder = yield _createToolPath(tool, version, arch); + // copy instead of move. move can fail on Windows due to + // anti-virus software having an open handle on a file. + const destPath = path.join(destFolder, targetFile); + core.debug(`destination file ${destPath}`); + yield io.cp(sourceFile, destPath); + // write .complete + _completeToolPath(tool, version, arch); + return destFolder; + }); +} +/** + * Finds the path to a tool version in the local installed tool cache + * + * @param toolName name of the tool + * @param versionSpec version of the tool + * @param arch optional arch. defaults to arch of computer + */ +function find(toolName, versionSpec, arch) { + if (!toolName) { + throw new Error('toolName parameter is required'); + } + if (!versionSpec) { + throw new Error('versionSpec parameter is required'); + } + arch = arch || external_os_.arch(); + // attempt to resolve an explicit version + if (!isExplicitVersion(versionSpec)) { + const localVersions = findAllVersions(toolName, arch); + const match = evaluateVersions(localVersions, versionSpec); + versionSpec = match; + } + // check for the explicit version in the cache + let toolPath = ''; + if (versionSpec) { + versionSpec = node_modules_semver.clean(versionSpec) || ''; + const cachePath = external_path_.join(_getCacheDirectory(), toolName, versionSpec, arch); + core_debug(`checking cache: ${cachePath}`); + if (external_fs_.existsSync(cachePath) && external_fs_.existsSync(`${cachePath}.complete`)) { + core_debug(`Found tool in cache ${toolName} ${versionSpec} ${arch}`); + toolPath = cachePath; + } + else { + core_debug('not found'); + } + } + return toolPath; +} +/** + * Finds the paths to all versions of a tool that are installed in the local tool cache + * + * @param toolName name of the tool + * @param arch optional arch. defaults to arch of computer + */ +function findAllVersions(toolName, arch) { + const versions = []; + arch = arch || external_os_.arch(); + const toolPath = external_path_.join(_getCacheDirectory(), toolName); + if (external_fs_.existsSync(toolPath)) { + const children = external_fs_.readdirSync(toolPath); + for (const child of children) { + if (isExplicitVersion(child)) { + const fullPath = external_path_.join(toolPath, child, arch || ''); + if (external_fs_.existsSync(fullPath) && external_fs_.existsSync(`${fullPath}.complete`)) { + versions.push(child); + } + } + } + } + return versions; +} +function getManifestFromRepo(owner_1, repo_1, auth_1) { + return tool_cache_awaiter(this, arguments, void 0, function* (owner, repo, auth, branch = 'master') { + let releases = []; + const treeUrl = `https://api.github.com/repos/${owner}/${repo}/git/trees/${branch}`; + const http = new httpm.HttpClient('tool-cache'); + const headers = {}; + if (auth) { + core.debug('set auth'); + headers.authorization = auth; + } + const response = yield http.getJson(treeUrl, headers); + if (!response.result) { + return releases; + } + let manifestUrl = ''; + for (const item of response.result.tree) { + if (item.path === 'versions-manifest.json') { + manifestUrl = item.url; + break; + } + } + headers['accept'] = 'application/vnd.github.VERSION.raw'; + let versionsRaw = yield (yield http.get(manifestUrl, headers)).readBody(); + if (versionsRaw) { + // shouldn't be needed but protects against invalid json saved with BOM + versionsRaw = versionsRaw.replace(/^\uFEFF/, ''); + try { + releases = JSON.parse(versionsRaw); + } + catch (_a) { + core.debug('Invalid json'); + } + } + return releases; + }); } - -const TEN_MEGABYTES_IN_BYTES = (/* unused pure expression or super */ null && (10 * 1024 * 1024)); - -async function execFile(file, arguments_, options = {}) { - return execFileOriginal(file, arguments_, { - maxBuffer: TEN_MEGABYTES_IN_BYTES, - ...options, - }); +function findFromManifest(versionSpec_1, stable_1, manifest_1) { + return tool_cache_awaiter(this, arguments, void 0, function* (versionSpec, stable, manifest, archFilter = os.arch()) { + // wrap the internal impl + const match = yield mm._findMatch(versionSpec, stable, manifest, archFilter); + return match; + }); } - -function execFileSync(file, arguments_ = [], options = {}) { - return execFileSyncOriginal(file, arguments_, { - maxBuffer: TEN_MEGABYTES_IN_BYTES, - encoding: 'utf8', - stdio: 'pipe', - ...options, - }); +function _createExtractFolder(dest) { + return tool_cache_awaiter(this, void 0, void 0, function* () { + if (!dest) { + // create a temp dir + dest = external_path_.join(_getTempDirectory(), external_crypto_namespaceObject.randomUUID()); + } + yield mkdirP(dest); + return dest; + }); } - - - -// EXTERNAL MODULE: external "node:fs/promises" -var promises_ = __nccwpck_require__(1455); -// EXTERNAL MODULE: ../../../Library/pnpm/store/v10/links/ignore/7.0.5/c0ceec7608eaec6cae63537114b52d466bdcd83c1173d7da9887eeb4960b9d7d/node_modules/ignore/index.js -var ignore = __nccwpck_require__(842); -;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/is-path-inside/4.0.0/2b16a362dbb8e8b5aa5655981cdb6263c3587d968e31d88cc6f725bd8da90401/node_modules/is-path-inside/index.js - - -function isPathInside(childPath, parentPath) { - const relation = external_node_path_.relative(parentPath, childPath); - - return Boolean( - relation && - relation !== '..' && - !relation.startsWith(`..${external_node_path_.sep}`) && - relation !== external_node_path_.resolve(childPath) - ); +function _createToolPath(tool, version, arch) { + return tool_cache_awaiter(this, void 0, void 0, function* () { + const folderPath = external_path_.join(_getCacheDirectory(), tool, node_modules_semver.clean(version) || version, arch || ''); + core_debug(`destination ${folderPath}`); + const markerPath = `${folderPath}.complete`; + yield rmRF(folderPath); + yield rmRF(markerPath); + yield mkdirP(folderPath); + return folderPath; + }); } - -;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/slash/5.1.0/7ff5261a1eca3a95e3cdfe7207843d8babb856765fbfcb593c174be6c0d93c32/node_modules/slash/index.js -function slash(path) { - const isExtendedLengthPath = path.startsWith('\\\\?\\'); - - if (isExtendedLengthPath) { - return path; - } - - return path.replace(/\\/g, '/'); +function _completeToolPath(tool, version, arch) { + const folderPath = external_path_.join(_getCacheDirectory(), tool, node_modules_semver.clean(version) || version, arch || ''); + const markerPath = `${folderPath}.complete`; + external_fs_.writeFileSync(markerPath, ''); + core_debug('finished caching tool'); } - -;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/globby/16.1.0/6bc516675ca718c332e5255dae86ad14f61b2538e1af28896d50d60441df5c38/node_modules/globby/utilities.js - - - - - -const isNegativePattern = pattern => pattern[0] === '!'; - /** -Normalize an absolute pattern to be relative. - -On Unix, patterns starting with `/` are interpreted as absolute paths from the filesystem root. This causes inconsistent behavior across platforms since Windows uses different path roots (like `C:\`). - -This function strips leading `/` to make patterns relative to cwd, ensuring consistent cross-platform behavior. - -@param {string} pattern - The pattern to normalize. -*/ -const normalizeAbsolutePatternToRelative = pattern => pattern.startsWith('/') ? pattern.slice(1) : pattern; - -const bindFsMethod = (object, methodName) => { - const method = object?.[methodName]; - return typeof method === 'function' ? method.bind(object) : undefined; -}; - -// Only used as a fallback for legacy fs implementations -const promisifyFsMethod = (object, methodName) => { - const method = object?.[methodName]; - if (typeof method !== 'function') { - return undefined; - } - - return (0,external_node_util_.promisify)(method.bind(object)); -}; - -const normalizeDirectoryPatternForFastGlob = pattern => { - if (!pattern.endsWith('/')) { - return pattern; - } - - const trimmedPattern = pattern.replace(/\/+$/u, ''); - if (!trimmedPattern) { - return '/**'; - } - - // Special case for '**/' to avoid producing '**/**/**' - if (trimmedPattern === '**') { - return '**/**'; - } - - const hasLeadingSlash = trimmedPattern.startsWith('/'); - const patternBody = hasLeadingSlash ? trimmedPattern.slice(1) : trimmedPattern; - const hasInnerSlash = patternBody.includes('/'); - const needsRecursivePrefix = !hasLeadingSlash && !hasInnerSlash && !trimmedPattern.startsWith('**/'); - const recursivePrefix = needsRecursivePrefix ? '**/' : ''; - - return `${recursivePrefix}${trimmedPattern}/**`; -}; - + * Check if version string is explicit + * + * @param versionSpec version string to check + */ +function isExplicitVersion(versionSpec) { + const c = node_modules_semver.clean(versionSpec) || ''; + core_debug(`isExplicit: ${c}`); + const valid = node_modules_semver.valid(c) != null; + core_debug(`explicit? ${valid}`); + return valid; +} /** -Extract the parent directory prefix from a pattern (e.g., '../' or '../../'). - -Note: Patterns should have trailing slash after '..' (e.g., '../foo' not '..foo'). The directoryToGlob function ensures this in the normal pipeline. - -@param {string} pattern - The pattern to analyze. -@returns {string} The parent directory prefix, or empty string if none. -*/ -const getParentDirectoryPrefix = pattern => { - const normalizedPattern = isNegativePattern(pattern) ? pattern.slice(1) : pattern; - const match = normalizedPattern.match(/^(\.\.\/)+/); - return match ? match[0] : ''; -}; - + * Get the highest satisfiying semantic version in `versions` which satisfies `versionSpec` + * + * @param versions array of versions to evaluate + * @param versionSpec semantic version spec to satisfy + */ +function evaluateVersions(versions, versionSpec) { + let version = ''; + core_debug(`evaluating ${versions.length} versions`); + versions = versions.sort((a, b) => { + if (node_modules_semver.gt(a, b)) { + return 1; + } + return -1; + }); + for (let i = versions.length - 1; i >= 0; i--) { + const potential = versions[i]; + const satisfied = node_modules_semver.satisfies(potential, versionSpec); + if (satisfied) { + version = potential; + break; + } + } + if (version) { + core_debug(`matched: ${version}`); + } + else { + core_debug('match not found'); + } + return version; +} /** -Adjust ignore patterns to match the relative base of the main patterns. - -When patterns reference parent directories, ignore patterns starting with globstars need to be adjusted to match from the same base directory. This ensures intuitive behavior where ignore patterns work correctly with parent directory patterns. - -This is analogous to how node-glob normalizes path prefixes (see node-glob issue #309) and how Rust ignore crate strips path prefixes before matching. - -@param {string[]} patterns - The main glob patterns. -@param {string[]} ignorePatterns - The ignore patterns to adjust. -@returns {string[]} Adjusted ignore patterns. -*/ -const adjustIgnorePatternsForParentDirectories = (patterns, ignorePatterns) => { - // Early exit for empty arrays - if (patterns.length === 0 || ignorePatterns.length === 0) { - return ignorePatterns; - } - - // Get parent directory prefixes for all patterns (empty string if no prefix) - const parentPrefixes = patterns.map(pattern => getParentDirectoryPrefix(pattern)); - - // Check if all patterns have the same parent prefix - const firstPrefix = parentPrefixes[0]; - if (!firstPrefix) { - return ignorePatterns; // No parent directories in any pattern - } - - const allSamePrefix = parentPrefixes.every(prefix => prefix === firstPrefix); - if (!allSamePrefix) { - return ignorePatterns; // Mixed bases - don't adjust - } - - // Adjust ignore patterns that start with **/ - return ignorePatterns.map(pattern => { - // Only adjust patterns starting with **/ that don't already have a parent reference - if (pattern.startsWith('**/') && !pattern.startsWith('../')) { - return firstPrefix + pattern; - } - - return pattern; - }); -}; - + * Gets RUNNER_TOOL_CACHE + */ +function _getCacheDirectory() { + const cacheDirectory = process.env['RUNNER_TOOL_CACHE'] || ''; + (0,external_assert_.ok)(cacheDirectory, 'Expected RUNNER_TOOL_CACHE to be defined'); + return cacheDirectory; +} /** -Find the git root directory by searching upward for a .git directory. - -@param {string} cwd - The directory to start searching from. -@param {Object} [fsImplementation] - Optional fs implementation. -@returns {string|undefined} The git root directory path, or undefined if not found. -*/ -const getAsyncStatMethod = fsImplementation => - bindFsMethod(fsImplementation?.promises, 'stat') - ?? bindFsMethod(external_node_fs_.promises, 'stat'); - -const getStatSyncMethod = fsImplementation => { - if (fsImplementation) { - return bindFsMethod(fsImplementation, 'statSync'); - } - - return bindFsMethod(external_node_fs_, 'statSync'); -}; - -const pathHasGitDirectory = stats => Boolean(stats?.isDirectory?.() || stats?.isFile?.()); - -const buildPathChain = (startPath, rootPath) => { - const chain = []; - let currentPath = startPath; - - chain.push(currentPath); - - while (currentPath !== rootPath) { - const parentPath = external_node_path_.dirname(currentPath); - if (parentPath === currentPath) { - break; - } - - currentPath = parentPath; - chain.push(currentPath); - } - - return chain; -}; - -const findGitRootInChain = async (paths, statMethod) => { - for (const directory of paths) { - const gitPath = external_node_path_.join(directory, '.git'); - - try { - const stats = await statMethod(gitPath); // eslint-disable-line no-await-in-loop - if (pathHasGitDirectory(stats)) { - return directory; - } - } catch { - // Ignore errors and continue searching - } - } - - return undefined; -}; - -const findGitRootSyncUncached = (cwd, fsImplementation) => { - const statSyncMethod = getStatSyncMethod(fsImplementation); - if (!statSyncMethod) { - return undefined; - } - - const currentPath = external_node_path_.resolve(cwd); - const {root} = external_node_path_.parse(currentPath); - const chain = buildPathChain(currentPath, root); - - for (const directory of chain) { - const gitPath = external_node_path_.join(directory, '.git'); - try { - const stats = statSyncMethod(gitPath); - if (pathHasGitDirectory(stats)) { - return directory; - } - } catch { - // Ignore errors and continue searching - } - } - - return undefined; -}; - -const findGitRootSync = (cwd, fsImplementation) => { - if (typeof cwd !== 'string') { - throw new TypeError('cwd must be a string'); - } - - return findGitRootSyncUncached(cwd, fsImplementation); -}; - -const findGitRootAsyncUncached = async (cwd, fsImplementation) => { - const statMethod = getAsyncStatMethod(fsImplementation); - if (!statMethod) { - return findGitRootSync(cwd, fsImplementation); - } - - const currentPath = external_node_path_.resolve(cwd); - const {root} = external_node_path_.parse(currentPath); - const chain = buildPathChain(currentPath, root); - - return findGitRootInChain(chain, statMethod); -}; - -const findGitRoot = async (cwd, fsImplementation) => { - if (typeof cwd !== 'string') { - throw new TypeError('cwd must be a string'); - } - - return findGitRootAsyncUncached(cwd, fsImplementation); -}; - + * Gets RUNNER_TEMP + */ +function _getTempDirectory() { + const tempDirectory = process.env['RUNNER_TEMP'] || ''; + (0,external_assert_.ok)(tempDirectory, 'Expected RUNNER_TEMP to be defined'); + return tempDirectory; +} /** -Get paths to all .gitignore files from git root to cwd (inclusive). - -@param {string} gitRoot - The git root directory. -@param {string} cwd - The current working directory. -@returns {string[]} Array of .gitignore file paths to search for. -*/ -const isWithinGitRoot = (gitRoot, cwd) => { - const resolvedGitRoot = external_node_path_.resolve(gitRoot); - const resolvedCwd = external_node_path_.resolve(cwd); - return resolvedCwd === resolvedGitRoot || isPathInside(resolvedCwd, resolvedGitRoot); -}; - -const getParentGitignorePaths = (gitRoot, cwd) => { - if (gitRoot && typeof gitRoot !== 'string') { - throw new TypeError('gitRoot must be a string or undefined'); - } - - if (typeof cwd !== 'string') { - throw new TypeError('cwd must be a string'); - } - - // If no gitRoot provided, return empty array - if (!gitRoot) { - return []; - } - - if (!isWithinGitRoot(gitRoot, cwd)) { - return []; - } - - const chain = buildPathChain(external_node_path_.resolve(cwd), external_node_path_.resolve(gitRoot)); - - return [...chain] - .reverse() - .map(directory => external_node_path_.join(directory, '.gitignore')); -}; - + * Gets a global variable + */ +function _getGlobal(key, defaultValue) { + /* eslint-disable @typescript-eslint/no-explicit-any */ + const value = global[key]; + /* eslint-enable @typescript-eslint/no-explicit-any */ + return value !== undefined ? value : defaultValue; +} /** -Convert ignore patterns to fast-glob compatible format. -Returns empty array if patterns should be handled by predicate only. - -@param {string[]} patterns - Ignore patterns from .gitignore files -@param {boolean} usingGitRoot - Whether patterns are relative to git root -@param {Function} normalizeDirectoryPatternForFastGlob - Function to normalize directory patterns -@returns {string[]} Patterns safe to pass to fast-glob, or empty array -*/ -const convertPatternsForFastGlob = (patterns, usingGitRoot, normalizeDirectoryPatternForFastGlob) => { - // Determine which patterns are safe to pass to fast-glob - // If there are negation patterns, we can't pass file patterns to fast-glob - // because fast-glob doesn't understand negations and would filter out files - // that should be re-included by negation patterns. - // If we're using git root, patterns are relative to git root not cwd, - // so we can't pass them to fast-glob which expects cwd-relative patterns. - // We only pass patterns to fast-glob if there are NO negations AND we're not using git root. - - if (usingGitRoot) { - return []; // Patterns are relative to git root, not cwd - } - - const result = []; - let hasNegations = false; - - // Single pass to check for negations and collect positive patterns - for (const pattern of patterns) { - if (isNegativePattern(pattern)) { - hasNegations = true; - break; // Early exit on first negation - } - - result.push(normalizeDirectoryPatternForFastGlob(pattern)); - } - - return hasNegations ? [] : result; -}; - -;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/globby/16.1.0/6bc516675ca718c332e5255dae86ad14f61b2538e1af28896d50d60441df5c38/node_modules/globby/ignore.js - - - - - - - - - - - -const defaultIgnoredDirectories = [ - '**/node_modules', - '**/flow-typed', - '**/coverage', - '**/.git', -]; -const ignoreFilesGlobOptions = { - absolute: true, - dot: true, -}; - -const GITIGNORE_FILES_PATTERN = '**/.gitignore'; - -const getReadFileMethod = fsImplementation => - bindFsMethod(fsImplementation?.promises, 'readFile') - ?? bindFsMethod(promises_, 'readFile') - ?? promisifyFsMethod(fsImplementation, 'readFile'); - -const getReadFileSyncMethod = fsImplementation => - bindFsMethod(fsImplementation, 'readFileSync') - ?? bindFsMethod(external_node_fs_, 'readFileSync'); - -const shouldSkipIgnoreFileError = (error, suppressErrors) => { - if (!error) { - return Boolean(suppressErrors); - } - - if (error.code === 'ENOENT' || error.code === 'ENOTDIR') { - return true; - } - - return Boolean(suppressErrors); -}; - -const createIgnoreFileReadError = (filePath, error) => { - if (error instanceof Error) { - error.message = `Failed to read ignore file at ${filePath}: ${error.message}`; - return error; - } - - return new Error(`Failed to read ignore file at ${filePath}: ${String(error)}`); -}; - -const processIgnoreFileCore = (filePath, readMethod, suppressErrors) => { - try { - const content = readMethod(filePath, 'utf8'); - return {filePath, content}; - } catch (error) { - if (shouldSkipIgnoreFileError(error, suppressErrors)) { - return undefined; - } + * Returns an array of unique values. + * @param values Values to make unique. + */ +function _unique(values) { + return Array.from(new Set(values)); +} +//# sourceMappingURL=tool-cache.js.map +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@/universal-user-agent/7.0.3/cc533676cf04e8aac99e3561a188b8867414674edad01efaf2a65a6b92904df4/node_modules/universal-user-agent/index.js +function getUserAgent() { + if (typeof navigator === "object" && "userAgent" in navigator) { + return navigator.userAgent; + } - throw createIgnoreFileReadError(filePath, error); - } -}; + if (typeof process === "object" && process.version !== undefined) { + return `Node.js/${process.version.substr(1)} (${process.platform}; ${ + process.arch + })`; + } -const readIgnoreFilesSafely = async (paths, readFileMethod, suppressErrors) => { - const fileResults = await Promise.all(paths.map(async filePath => { - try { - const content = await readFileMethod(filePath, 'utf8'); - return {filePath, content}; - } catch (error) { - if (shouldSkipIgnoreFileError(error, suppressErrors)) { - return undefined; - } + return ""; +} - throw createIgnoreFileReadError(filePath, error); - } - })); +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@/before-after-hook/4.0.0/1488bade5929b630234702d1039c0b9f6fcb00eaa2fa4988634014684001f87c/node_modules/before-after-hook/lib/register.js +// @ts-check - return fileResults.filter(Boolean); -}; +function register(state, name, method, options) { + if (typeof method !== "function") { + throw new Error("method for before hook must be a function"); + } -const readIgnoreFilesSafelySync = (paths, readFileSyncMethod, suppressErrors) => paths - .map(filePath => processIgnoreFileCore(filePath, readFileSyncMethod, suppressErrors)) - .filter(Boolean); + if (!options) { + options = {}; + } -const dedupePaths = paths => { - const seen = new Set(); - return paths.filter(filePath => { - if (seen.has(filePath)) { - return false; - } + if (Array.isArray(name)) { + return name.reverse().reduce((callback, name) => { + return register.bind(null, state, name, callback, options); + }, method)(); + } - seen.add(filePath); - return true; - }); -}; + return Promise.resolve().then(() => { + if (!state.registry[name]) { + return method(options); + } -const globIgnoreFiles = (globFunction, patterns, normalizedOptions) => globFunction(patterns, { - ...normalizedOptions, - ...ignoreFilesGlobOptions, // Must be last to ensure absolute/dot flags stick -}); + return state.registry[name].reduce((method, registered) => { + return registered.hook.bind(null, method, options); + }, method)(); + }); +} -const getParentIgnorePaths = (gitRoot, normalizedOptions) => gitRoot - ? getParentGitignorePaths(gitRoot, normalizedOptions.cwd) - : []; +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@/before-after-hook/4.0.0/1488bade5929b630234702d1039c0b9f6fcb00eaa2fa4988634014684001f87c/node_modules/before-after-hook/lib/add.js +// @ts-check -const combineIgnoreFilePaths = (gitRoot, normalizedOptions, childPaths) => dedupePaths([ - ...getParentIgnorePaths(gitRoot, normalizedOptions), - ...childPaths, -]); +function addHook(state, kind, name, hook) { + const orig = hook; + if (!state.registry[name]) { + state.registry[name] = []; + } -const buildIgnoreResult = (files, normalizedOptions, gitRoot) => { - const baseDir = gitRoot || normalizedOptions.cwd; - const patterns = getPatternsFromIgnoreFiles(files, baseDir); + if (kind === "before") { + hook = (method, options) => { + return Promise.resolve() + .then(orig.bind(null, options)) + .then(method.bind(null, options)); + }; + } - return { - patterns, - predicate: createIgnorePredicate(patterns, normalizedOptions.cwd, baseDir), - usingGitRoot: Boolean(gitRoot && gitRoot !== normalizedOptions.cwd), - }; -}; + if (kind === "after") { + hook = (method, options) => { + let result; + return Promise.resolve() + .then(method.bind(null, options)) + .then((result_) => { + result = result_; + return orig(result, options); + }) + .then(() => { + return result; + }); + }; + } -// Apply base path to gitignore patterns based on .gitignore spec 2.22.1 -// https://git-scm.com/docs/gitignore#_pattern_format -// See also https://github.com/sindresorhus/globby/issues/146 -const applyBaseToPattern = (pattern, base) => { - if (!base) { - return pattern; - } + if (kind === "error") { + hook = (method, options) => { + return Promise.resolve() + .then(method.bind(null, options)) + .catch((error) => { + return orig(error, options); + }); + }; + } - const isNegative = isNegativePattern(pattern); - const cleanPattern = isNegative ? pattern.slice(1) : pattern; + state.registry[name].push({ + hook: hook, + orig: orig, + }); +} - // Check if pattern has non-trailing slashes - const slashIndex = cleanPattern.indexOf('/'); - const hasNonTrailingSlash = slashIndex !== -1 && slashIndex !== cleanPattern.length - 1; +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@/before-after-hook/4.0.0/1488bade5929b630234702d1039c0b9f6fcb00eaa2fa4988634014684001f87c/node_modules/before-after-hook/lib/remove.js +// @ts-check - let result; - if (!hasNonTrailingSlash) { - // "If there is no separator at the beginning or middle of the pattern, - // then the pattern may also match at any level below the .gitignore level." - // So patterns like '*.log' or 'temp' or 'build/' (trailing slash) match recursively. - result = external_node_path_.posix.join(base, '**', cleanPattern); - } else if (cleanPattern.startsWith('/')) { - // "If there is a separator at the beginning [...] of the pattern, - // then the pattern is relative to the directory level of the particular .gitignore file itself." - // Leading slash anchors the pattern to the .gitignore's directory. - result = external_node_path_.posix.join(base, cleanPattern.slice(1)); - } else { - // "If there is a separator [...] middle [...] of the pattern, - // then the pattern is relative to the directory level of the particular .gitignore file itself." - // Patterns like 'src/foo' are relative to the .gitignore's directory. - result = external_node_path_.posix.join(base, cleanPattern); - } +function removeHook(state, name, method) { + if (!state.registry[name]) { + return; + } - return isNegative ? '!' + result : result; -}; + const index = state.registry[name] + .map((registered) => { + return registered.orig; + }) + .indexOf(method); -const parseIgnoreFile = (file, cwd) => { - const base = slash(external_node_path_.relative(cwd, external_node_path_.dirname(file.filePath))); + if (index === -1) { + return; + } - return file.content - .split(/\r?\n/) - .filter(line => line && !line.startsWith('#')) - .map(pattern => applyBaseToPattern(pattern, base)); -}; + state.registry[name].splice(index, 1); +} -const toRelativePath = (fileOrDirectory, cwd) => { - if (external_node_path_.isAbsolute(fileOrDirectory)) { - // When paths are equal, path.relative returns empty string which is valid - // isPathInside returns false for equal paths, so check this case first - const relativePath = external_node_path_.relative(cwd, fileOrDirectory); - if (relativePath && !isPathInside(fileOrDirectory, cwd)) { - // Path is outside cwd - it cannot be ignored by patterns in cwd - // Return undefined to indicate this path is outside scope - return undefined; - } +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@/before-after-hook/4.0.0/1488bade5929b630234702d1039c0b9f6fcb00eaa2fa4988634014684001f87c/node_modules/before-after-hook/index.js +// @ts-check - return relativePath; - } - // Normalize relative paths: - // - Git treats './foo' as 'foo' when checking against patterns - // - Patterns starting with './' in .gitignore are invalid and don't match anything - // - The ignore library expects normalized paths without './' prefix - if (fileOrDirectory.startsWith('./')) { - return fileOrDirectory.slice(2); - } - // Paths with ../ point outside cwd and cannot match patterns from this directory - // Return undefined to indicate this path is outside scope - if (fileOrDirectory.startsWith('../')) { - return undefined; - } - return fileOrDirectory; -}; -const createIgnorePredicate = (patterns, cwd, baseDir) => { - const ignores = ignore().add(patterns); - // Normalize to handle path separator and . / .. components consistently - const resolvedCwd = external_node_path_.normalize(external_node_path_.resolve(cwd)); - const resolvedBaseDir = external_node_path_.normalize(external_node_path_.resolve(baseDir)); +// bind with array of arguments: https://stackoverflow.com/a/21792913 +const bind = Function.bind; +const bindable = bind.bind(bind); - return fileOrDirectory => { - fileOrDirectory = toPath(fileOrDirectory); +function bindApi(hook, state, name) { + const removeHookRef = bindable(removeHook, null).apply( + null, + name ? [state, name] : [state] + ); + hook.api = { remove: removeHookRef }; + hook.remove = removeHookRef; + ["before", "error", "after", "wrap"].forEach((kind) => { + const args = name ? [state, kind, name] : [state, kind]; + hook[kind] = hook.api[kind] = bindable(addHook, null).apply(null, args); + }); +} - // Never ignore the cwd itself - use normalized comparison - const normalizedPath = external_node_path_.normalize(external_node_path_.resolve(fileOrDirectory)); - if (normalizedPath === resolvedCwd) { - return false; - } +function Singular() { + const singularHookName = Symbol("Singular"); + const singularHookState = { + registry: {}, + }; + const singularHook = register.bind(null, singularHookState, singularHookName); + bindApi(singularHook, singularHookState, singularHookName); + return singularHook; +} - // Convert to relative path from baseDir (use normalized baseDir) - const relativePath = toRelativePath(fileOrDirectory, resolvedBaseDir); +function Collection() { + const state = { + registry: {}, + }; - // If path is outside baseDir (undefined), it can't be ignored by patterns - if (relativePath === undefined) { - return false; - } + const hook = register.bind(null, state); + bindApi(hook, state); - return relativePath ? ignores.ignores(slash(relativePath)) : false; - }; -}; + return hook; +} -const normalizeOptions = (options = {}) => { - const ignoreOption = options.ignore - ? (Array.isArray(options.ignore) ? options.ignore : [options.ignore]) - : []; +/* harmony default export */ const before_after_hook = ({ Singular, Collection }); - const cwd = toPath(options.cwd) ?? external_node_process_namespaceObject.cwd(); +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@octokit/endpoint/11.0.2/c40c09a599bfa85bfd8a4f173350fad63734cc375db4d3441e5b75d91852138f/node_modules/@octokit/endpoint/dist-bundle/index.js +// pkg/dist-src/defaults.js - // Adjust deep option for fast-glob: fast-glob's deep counts differently than expected - // User's deep: 0 = root only -> fast-glob needs: 1 - // User's deep: 1 = root + 1 level -> fast-glob needs: 2 - const deep = typeof options.deep === 'number' ? Math.max(0, options.deep) + 1 : Number.POSITIVE_INFINITY; - // Only pass through specific fast-glob options that make sense for finding ignore files - return { - cwd, - suppressErrors: options.suppressErrors ?? false, - deep, - ignore: [...ignoreOption, ...defaultIgnoredDirectories], - followSymbolicLinks: options.followSymbolicLinks ?? true, - concurrency: options.concurrency, - throwErrorOnBrokenSymbolicLink: options.throwErrorOnBrokenSymbolicLink ?? false, - fs: options.fs, - }; +// pkg/dist-src/version.js +var VERSION = "0.0.0-development"; + +// pkg/dist-src/defaults.js +var dist_bundle_userAgent = `octokit-endpoint.js/${VERSION} ${getUserAgent()}`; +var DEFAULTS = { + method: "GET", + baseUrl: "https://api.github.com", + headers: { + accept: "application/vnd.github.v3+json", + "user-agent": dist_bundle_userAgent + }, + mediaType: { + format: "" + } }; -const collectIgnoreFileArtifactsAsync = async (patterns, options, includeParentIgnoreFiles) => { - const normalizedOptions = normalizeOptions(options); - const childPaths = await globIgnoreFiles(out, patterns, normalizedOptions); - const gitRoot = includeParentIgnoreFiles - ? await findGitRoot(normalizedOptions.cwd, normalizedOptions.fs) - : undefined; - const allPaths = combineIgnoreFilePaths(gitRoot, normalizedOptions, childPaths); - const readFileMethod = getReadFileMethod(normalizedOptions.fs); - const files = await readIgnoreFilesSafely(allPaths, readFileMethod, normalizedOptions.suppressErrors); +// pkg/dist-src/util/lowercase-keys.js +function dist_bundle_lowercaseKeys(object) { + if (!object) { + return {}; + } + return Object.keys(object).reduce((newObj, key) => { + newObj[key.toLowerCase()] = object[key]; + return newObj; + }, {}); +} - return {files, normalizedOptions, gitRoot}; -}; +// pkg/dist-src/util/is-plain-object.js +function isPlainObject(value) { + if (typeof value !== "object" || value === null) return false; + if (Object.prototype.toString.call(value) !== "[object Object]") return false; + const proto = Object.getPrototypeOf(value); + if (proto === null) return true; + const Ctor = Object.prototype.hasOwnProperty.call(proto, "constructor") && proto.constructor; + return typeof Ctor === "function" && Ctor instanceof Ctor && Function.prototype.call(Ctor) === Function.prototype.call(value); +} -const collectIgnoreFileArtifactsSync = (patterns, options, includeParentIgnoreFiles) => { - const normalizedOptions = normalizeOptions(options); - const childPaths = globIgnoreFiles(out.sync, patterns, normalizedOptions); - const gitRoot = includeParentIgnoreFiles - ? findGitRootSync(normalizedOptions.cwd, normalizedOptions.fs) - : undefined; - const allPaths = combineIgnoreFilePaths(gitRoot, normalizedOptions, childPaths); - const readFileSyncMethod = getReadFileSyncMethod(normalizedOptions.fs); - const files = readIgnoreFilesSafelySync(allPaths, readFileSyncMethod, normalizedOptions.suppressErrors); +// pkg/dist-src/util/merge-deep.js +function mergeDeep(defaults, options) { + const result = Object.assign({}, defaults); + Object.keys(options).forEach((key) => { + if (isPlainObject(options[key])) { + if (!(key in defaults)) Object.assign(result, { [key]: options[key] }); + else result[key] = mergeDeep(defaults[key], options[key]); + } else { + Object.assign(result, { [key]: options[key] }); + } + }); + return result; +} - return {files, normalizedOptions, gitRoot}; -}; +// pkg/dist-src/util/remove-undefined-properties.js +function removeUndefinedProperties(obj) { + for (const key in obj) { + if (obj[key] === void 0) { + delete obj[key]; + } + } + return obj; +} -const isIgnoredByIgnoreFiles = async (patterns, options) => { - const {files, normalizedOptions, gitRoot} = await collectIgnoreFileArtifactsAsync(patterns, options, false); - return buildIgnoreResult(files, normalizedOptions, gitRoot).predicate; -}; +// pkg/dist-src/merge.js +function merge(defaults, route, options) { + if (typeof route === "string") { + let [method, url] = route.split(" "); + options = Object.assign(url ? { method, url } : { url: method }, options); + } else { + options = Object.assign({}, route); + } + options.headers = dist_bundle_lowercaseKeys(options.headers); + removeUndefinedProperties(options); + removeUndefinedProperties(options.headers); + const mergedOptions = mergeDeep(defaults || {}, options); + if (options.url === "/graphql") { + if (defaults && defaults.mediaType.previews?.length) { + mergedOptions.mediaType.previews = defaults.mediaType.previews.filter( + (preview) => !mergedOptions.mediaType.previews.includes(preview) + ).concat(mergedOptions.mediaType.previews); + } + mergedOptions.mediaType.previews = (mergedOptions.mediaType.previews || []).map((preview) => preview.replace(/-preview/, "")); + } + return mergedOptions; +} -const isIgnoredByIgnoreFilesSync = (patterns, options) => { - const {files, normalizedOptions, gitRoot} = collectIgnoreFileArtifactsSync(patterns, options, false); - return buildIgnoreResult(files, normalizedOptions, gitRoot).predicate; -}; +// pkg/dist-src/util/add-query-parameters.js +function addQueryParameters(url, parameters) { + const separator = /\?/.test(url) ? "&" : "?"; + const names = Object.keys(parameters); + if (names.length === 0) { + return url; + } + return url + separator + names.map((name) => { + if (name === "q") { + return "q=" + parameters.q.split("+").map(encodeURIComponent).join("+"); + } + return `${name}=${encodeURIComponent(parameters[name])}`; + }).join("&"); +} -const getPatternsFromIgnoreFiles = (files, baseDir) => files.flatMap(file => parseIgnoreFile(file, baseDir)); +// pkg/dist-src/util/extract-url-variable-names.js +var urlVariableRegex = /\{[^{}}]+\}/g; +function removeNonChars(variableName) { + return variableName.replace(/(?:^\W+)|(?:(? a.concat(b), []); +} -/** -Read ignore files and return both patterns and predicate. -This avoids reading the same files twice (once for patterns, once for filtering). +// pkg/dist-src/util/omit.js +function omit(object, keysToOmit) { + const result = { __proto__: null }; + for (const key of Object.keys(object)) { + if (keysToOmit.indexOf(key) === -1) { + result[key] = object[key]; + } + } + return result; +} + +// pkg/dist-src/util/url-template.js +function encodeReserved(str) { + return str.split(/(%[0-9A-Fa-f]{2})/g).map(function(part) { + if (!/%[0-9A-Fa-f]/.test(part)) { + part = encodeURI(part).replace(/%5B/g, "[").replace(/%5D/g, "]"); + } + return part; + }).join(""); +} +function encodeUnreserved(str) { + return encodeURIComponent(str).replace(/[!'()*]/g, function(c) { + return "%" + c.charCodeAt(0).toString(16).toUpperCase(); + }); +} +function encodeValue(operator, value, key) { + value = operator === "+" || operator === "#" ? encodeReserved(value) : encodeUnreserved(value); + if (key) { + return encodeUnreserved(key) + "=" + value; + } else { + return value; + } +} +function isDefined(value) { + return value !== void 0 && value !== null; +} +function isKeyOperator(operator) { + return operator === ";" || operator === "&" || operator === "?"; +} +function getValues(context, operator, key, modifier) { + var value = context[key], result = []; + if (isDefined(value) && value !== "") { + if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") { + value = value.toString(); + if (modifier && modifier !== "*") { + value = value.substring(0, parseInt(modifier, 10)); + } + result.push( + encodeValue(operator, value, isKeyOperator(operator) ? key : "") + ); + } else { + if (modifier === "*") { + if (Array.isArray(value)) { + value.filter(isDefined).forEach(function(value2) { + result.push( + encodeValue(operator, value2, isKeyOperator(operator) ? key : "") + ); + }); + } else { + Object.keys(value).forEach(function(k) { + if (isDefined(value[k])) { + result.push(encodeValue(operator, value[k], k)); + } + }); + } + } else { + const tmp = []; + if (Array.isArray(value)) { + value.filter(isDefined).forEach(function(value2) { + tmp.push(encodeValue(operator, value2)); + }); + } else { + Object.keys(value).forEach(function(k) { + if (isDefined(value[k])) { + tmp.push(encodeUnreserved(k)); + tmp.push(encodeValue(operator, value[k].toString())); + } + }); + } + if (isKeyOperator(operator)) { + result.push(encodeUnreserved(key) + "=" + tmp.join(",")); + } else if (tmp.length !== 0) { + result.push(tmp.join(",")); + } + } + } + } else { + if (operator === ";") { + if (isDefined(value)) { + result.push(encodeUnreserved(key)); + } + } else if (value === "" && (operator === "&" || operator === "?")) { + result.push(encodeUnreserved(key) + "="); + } else if (value === "") { + result.push(""); + } + } + return result; +} +function parseUrl(template) { + return { + expand: expand.bind(null, template) + }; +} +function expand(template, context) { + var operators = ["+", "#", ".", "/", ";", "?", "&"]; + template = template.replace( + /\{([^\{\}]+)\}|([^\{\}]+)/g, + function(_, expression, literal) { + if (expression) { + let operator = ""; + const values = []; + if (operators.indexOf(expression.charAt(0)) !== -1) { + operator = expression.charAt(0); + expression = expression.substr(1); + } + expression.split(/,/g).forEach(function(variable) { + var tmp = /([^:\*]*)(?::(\d+)|(\*))?/.exec(variable); + values.push(getValues(context, operator, tmp[1], tmp[2] || tmp[3])); + }); + if (operator && operator !== "+") { + var separator = ","; + if (operator === "?") { + separator = "&"; + } else if (operator !== "#") { + separator = operator; + } + return (values.length !== 0 ? operator : "") + values.join(separator); + } else { + return values.join(","); + } + } else { + return encodeReserved(literal); + } + } + ); + if (template === "/") { + return template; + } else { + return template.replace(/\/$/, ""); + } +} -@param {string[]} patterns - Patterns to find ignore files -@param {Object} options - Options object -@param {boolean} [includeParentIgnoreFiles=false] - Whether to search for parent .gitignore files -@returns {Promise<{patterns: string[], predicate: Function, usingGitRoot: boolean}>} -*/ -const getIgnorePatternsAndPredicate = async (patterns, options, includeParentIgnoreFiles = false) => { - const {files, normalizedOptions, gitRoot} = await collectIgnoreFileArtifactsAsync( - patterns, - options, - includeParentIgnoreFiles, - ); +// pkg/dist-src/parse.js +function parse(options) { + let method = options.method.toUpperCase(); + let url = (options.url || "/").replace(/:([a-z]\w+)/g, "{$1}"); + let headers = Object.assign({}, options.headers); + let body; + let parameters = omit(options, [ + "method", + "baseUrl", + "url", + "headers", + "request", + "mediaType" + ]); + const urlVariableNames = extractUrlVariableNames(url); + url = parseUrl(url).expand(parameters); + if (!/^http/.test(url)) { + url = options.baseUrl + url; + } + const omittedParameters = Object.keys(options).filter((option) => urlVariableNames.includes(option)).concat("baseUrl"); + const remainingParameters = omit(parameters, omittedParameters); + const isBinaryRequest = /application\/octet-stream/i.test(headers.accept); + if (!isBinaryRequest) { + if (options.mediaType.format) { + headers.accept = headers.accept.split(/,/).map( + (format) => format.replace( + /application\/vnd(\.\w+)(\.v3)?(\.\w+)?(\+json)?$/, + `application/vnd$1$2.${options.mediaType.format}` + ) + ).join(","); + } + if (url.endsWith("/graphql")) { + if (options.mediaType.previews?.length) { + const previewsFromAcceptHeader = headers.accept.match(/(? { + const format = options.mediaType.format ? `.${options.mediaType.format}` : "+json"; + return `application/vnd.github.${preview}-preview${format}`; + }).join(","); + } + } + } + if (["GET", "HEAD"].includes(method)) { + url = addQueryParameters(url, remainingParameters); + } else { + if ("data" in remainingParameters) { + body = remainingParameters.data; + } else { + if (Object.keys(remainingParameters).length) { + body = remainingParameters; + } + } + } + if (!headers["content-type"] && typeof body !== "undefined") { + headers["content-type"] = "application/json; charset=utf-8"; + } + if (["PATCH", "PUT"].includes(method) && typeof body === "undefined") { + body = ""; + } + return Object.assign( + { method, url, headers }, + typeof body !== "undefined" ? { body } : null, + options.request ? { request: options.request } : null + ); +} - return buildIgnoreResult(files, normalizedOptions, gitRoot); -}; +// pkg/dist-src/endpoint-with-defaults.js +function endpointWithDefaults(defaults, route, options) { + return parse(merge(defaults, route, options)); +} -/** -Read ignore files and return both patterns and predicate (sync version). +// pkg/dist-src/with-defaults.js +function withDefaults(oldDefaults, newDefaults) { + const DEFAULTS2 = merge(oldDefaults, newDefaults); + const endpoint2 = endpointWithDefaults.bind(null, DEFAULTS2); + return Object.assign(endpoint2, { + DEFAULTS: DEFAULTS2, + defaults: withDefaults.bind(null, DEFAULTS2), + merge: merge.bind(null, DEFAULTS2), + parse + }); +} -@param {string[]} patterns - Patterns to find ignore files -@param {Object} options - Options object -@param {boolean} [includeParentIgnoreFiles=false] - Whether to search for parent .gitignore files -@returns {{patterns: string[], predicate: Function, usingGitRoot: boolean}} -*/ -const getIgnorePatternsAndPredicateSync = (patterns, options, includeParentIgnoreFiles = false) => { - const {files, normalizedOptions, gitRoot} = collectIgnoreFileArtifactsSync( - patterns, - options, - includeParentIgnoreFiles, - ); +// pkg/dist-src/index.js +var endpoint = withDefaults(null, DEFAULTS); - return buildIgnoreResult(files, normalizedOptions, gitRoot); -}; -const isGitIgnored = options => isIgnoredByIgnoreFiles(GITIGNORE_FILES_PATTERN, options); -const isGitIgnoredSync = options => isIgnoredByIgnoreFilesSync(GITIGNORE_FILES_PATTERN, options); +// EXTERNAL MODULE: ../../../Library/pnpm/store/v10/links/@/fast-content-type-parse/3.0.0/d143e4b4a18b5ed5e3b5a3ccf9a6b4667d50bd62c3713f15509757ebe8c7d68d/node_modules/fast-content-type-parse/index.js +var fast_content_type_parse = __nccwpck_require__(5232); +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@octokit/request-error/7.0.2/5b0e4bdf473658ab369e5c04938a642f5025a766a3e8adaff76f1cdd8b503197/node_modules/@octokit/request-error/dist-src/index.js +class RequestError extends Error { + name; + /** + * http status code + */ + status; + /** + * Request options that lead to the error. + */ + request; + /** + * Response object if a response was received + */ + response; + constructor(message, statusCode, options) { + super(message); + this.name = "HttpError"; + this.status = Number.parseInt(statusCode); + if (Number.isNaN(this.status)) { + this.status = 0; + } + if ("response" in options) { + this.response = options.response; + } + const requestCopy = Object.assign({}, options.request); + if (options.request.headers.authorization) { + requestCopy.headers = Object.assign({}, options.request.headers, { + authorization: options.request.headers.authorization.replace( + /(? { - if (patterns.some(pattern => typeof pattern !== 'string')) { - throw new TypeError('Patterns must be a string or an array of strings'); - } -}; +// pkg/dist-src/fetch-wrapper.js -const getStatMethod = fsImplementation => - bindFsMethod(fsImplementation?.promises, 'stat') - ?? bindFsMethod(external_node_fs_.promises, 'stat') - ?? promisifyFsMethod(fsImplementation, 'stat'); +async function fetchWrapper(requestOptions) { + const fetch = requestOptions.request?.fetch || globalThis.fetch; + if (!fetch) { + throw new Error( + "fetch is not set. Please pass a fetch implementation as new Octokit({ request: { fetch }}). Learn more at https://github.com/octokit/octokit.js/#fetch-missing" + ); + } + const log = requestOptions.request?.log || console; + const parseSuccessResponseBody = requestOptions.request?.parseSuccessResponseBody !== false; + const body = dist_bundle_isPlainObject(requestOptions.body) || Array.isArray(requestOptions.body) ? JSON.stringify(requestOptions.body) : requestOptions.body; + const requestHeaders = Object.fromEntries( + Object.entries(requestOptions.headers).map(([name, value]) => [ + name, + String(value) + ]) + ); + let fetchResponse; + try { + fetchResponse = await fetch(requestOptions.url, { + method: requestOptions.method, + body, + redirect: requestOptions.request?.redirect, + headers: requestHeaders, + signal: requestOptions.request?.signal, + // duplex must be set if request.body is ReadableStream or Async Iterables. + // See https://fetch.spec.whatwg.org/#dom-requestinit-duplex. + ...requestOptions.body && { duplex: "half" } + }); + } catch (error) { + let message = "Unknown Error"; + if (error instanceof Error) { + if (error.name === "AbortError") { + error.status = 500; + throw error; + } + message = error.message; + if (error.name === "TypeError" && "cause" in error) { + if (error.cause instanceof Error) { + message = error.cause.message; + } else if (typeof error.cause === "string") { + message = error.cause; + } + } + } + const requestError = new RequestError(message, 500, { + request: requestOptions + }); + requestError.cause = error; + throw requestError; + } + const status = fetchResponse.status; + const url = fetchResponse.url; + const responseHeaders = {}; + for (const [key, value] of fetchResponse.headers) { + responseHeaders[key] = value; + } + const octokitResponse = { + url, + status, + headers: responseHeaders, + data: "" + }; + if ("deprecation" in responseHeaders) { + const matches = responseHeaders.link && responseHeaders.link.match(/<([^<>]+)>; rel="deprecation"/); + const deprecationLink = matches && matches.pop(); + log.warn( + `[@octokit/request] "${requestOptions.method} ${requestOptions.url}" is deprecated. It is scheduled to be removed on ${responseHeaders.sunset}${deprecationLink ? `. See ${deprecationLink}` : ""}` + ); + } + if (status === 204 || status === 205) { + return octokitResponse; + } + if (requestOptions.method === "HEAD") { + if (status < 400) { + return octokitResponse; + } + throw new RequestError(fetchResponse.statusText, status, { + response: octokitResponse, + request: requestOptions + }); + } + if (status === 304) { + octokitResponse.data = await getResponseData(fetchResponse); + throw new RequestError("Not modified", status, { + response: octokitResponse, + request: requestOptions + }); + } + if (status >= 400) { + octokitResponse.data = await getResponseData(fetchResponse); + throw new RequestError(toErrorMessage(octokitResponse.data), status, { + response: octokitResponse, + request: requestOptions + }); + } + octokitResponse.data = parseSuccessResponseBody ? await getResponseData(fetchResponse) : fetchResponse.body; + return octokitResponse; +} +async function getResponseData(response) { + const contentType = response.headers.get("content-type"); + if (!contentType) { + return response.text().catch(() => ""); + } + const mimetype = (0,fast_content_type_parse/* safeParse */.xL)(contentType); + if (isJSONResponse(mimetype)) { + let text = ""; + try { + text = await response.text(); + return JSON.parse(text); + } catch (err) { + return text; + } + } else if (mimetype.type.startsWith("text/") || mimetype.parameters.charset?.toLowerCase() === "utf-8") { + return response.text().catch(() => ""); + } else { + return response.arrayBuffer().catch(() => new ArrayBuffer(0)); + } +} +function isJSONResponse(mimetype) { + return mimetype.type === "application/json" || mimetype.type === "application/scim+json"; +} +function toErrorMessage(data) { + if (typeof data === "string") { + return data; + } + if (data instanceof ArrayBuffer) { + return "Unknown error"; + } + if ("message" in data) { + const suffix = "documentation_url" in data ? ` - ${data.documentation_url}` : ""; + return Array.isArray(data.errors) ? `${data.message}: ${data.errors.map((v) => JSON.stringify(v)).join(", ")}${suffix}` : `${data.message}${suffix}`; + } + return `Unknown error: ${JSON.stringify(data)}`; +} -const globby_getStatSyncMethod = fsImplementation => - bindFsMethod(fsImplementation, 'statSync') - ?? bindFsMethod(external_node_fs_, 'statSync'); +// pkg/dist-src/with-defaults.js +function dist_bundle_withDefaults(oldEndpoint, newDefaults) { + const endpoint2 = oldEndpoint.defaults(newDefaults); + const newApi = function(route, parameters) { + const endpointOptions = endpoint2.merge(route, parameters); + if (!endpointOptions.request || !endpointOptions.request.hook) { + return fetchWrapper(endpoint2.parse(endpointOptions)); + } + const request2 = (route2, parameters2) => { + return fetchWrapper( + endpoint2.parse(endpoint2.merge(route2, parameters2)) + ); + }; + Object.assign(request2, { + endpoint: endpoint2, + defaults: dist_bundle_withDefaults.bind(null, endpoint2) + }); + return endpointOptions.request.hook(request2, endpointOptions); + }; + return Object.assign(newApi, { + endpoint: endpoint2, + defaults: dist_bundle_withDefaults.bind(null, endpoint2) + }); +} -const isDirectory = async (path, fsImplementation) => { - try { - const stats = await getStatMethod(fsImplementation)(path); - return stats.isDirectory(); - } catch { - return false; - } -}; +// pkg/dist-src/index.js +var request = dist_bundle_withDefaults(endpoint, defaults_default); -const isDirectorySync = (path, fsImplementation) => { - try { - const stats = globby_getStatSyncMethod(fsImplementation)(path); - return stats.isDirectory(); - } catch { - return false; - } -}; -const normalizePathForDirectoryGlob = (filePath, cwd) => { - const path = isNegativePattern(filePath) ? filePath.slice(1) : filePath; - return external_node_path_.isAbsolute(path) ? path : external_node_path_.join(cwd, path); -}; +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@octokit/graphql/9.0.3/15813a75b543b69a2dc2f9bebbfc8fe9957e5d14a2be8c5307ea39d391ddf87e/node_modules/@octokit/graphql/dist-bundle/index.js +// pkg/dist-src/index.js -const shouldExpandGlobstarDirectory = pattern => { - const match = pattern?.match(/\*\*\/([^/]+)$/); - if (!match) { - return false; - } - const dirname = match[1]; - const hasWildcards = /[*?[\]{}]/.test(dirname); - const hasExtension = external_node_path_.extname(dirname) && !dirname.startsWith('.'); - return !hasWildcards && !hasExtension; -}; +// pkg/dist-src/version.js +var graphql_dist_bundle_VERSION = "0.0.0-development"; -const getDirectoryGlob = ({directoryPath, files, extensions}) => { - const extensionGlob = extensions?.length > 0 ? `.${extensions.length > 1 ? `{${extensions.join(',')}}` : extensions[0]}` : ''; - return files - ? files.map(file => external_node_path_.posix.join(directoryPath, `**/${external_node_path_.extname(file) ? file : `${file}${extensionGlob}`}`)) - : [external_node_path_.posix.join(directoryPath, `**${extensionGlob ? `/*${extensionGlob}` : ''}`)]; -}; +// pkg/dist-src/with-defaults.js -const directoryToGlob = async (directoryPaths, { - cwd = external_node_process_namespaceObject.cwd(), - files, - extensions, - fs: fsImplementation, -} = {}) => { - const globs = await Promise.all(directoryPaths.map(async directoryPath => { - // Check pattern without negative prefix - const checkPattern = isNegativePattern(directoryPath) ? directoryPath.slice(1) : directoryPath; - // Expand globstar directory patterns like **/dirname to **/dirname/** - if (shouldExpandGlobstarDirectory(checkPattern)) { - return getDirectoryGlob({directoryPath, files, extensions}); - } +// pkg/dist-src/graphql.js - // Original logic for checking actual directories - const pathToCheck = normalizePathForDirectoryGlob(directoryPath, cwd); - return (await isDirectory(pathToCheck, fsImplementation)) ? getDirectoryGlob({directoryPath, files, extensions}) : directoryPath; - })); - return globs.flat(); +// pkg/dist-src/error.js +function _buildMessageForResponseErrors(data) { + return `Request failed due to following response errors: +` + data.errors.map((e) => ` - ${e.message}`).join("\n"); +} +var GraphqlResponseError = class extends Error { + constructor(request2, headers, response) { + super(_buildMessageForResponseErrors(response)); + this.request = request2; + this.headers = headers; + this.response = response; + this.errors = response.errors; + this.data = response.data; + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + } + name = "GraphqlResponseError"; + errors; + data; }; -const directoryToGlobSync = (directoryPaths, { - cwd = external_node_process_namespaceObject.cwd(), - files, - extensions, - fs: fsImplementation, -} = {}) => directoryPaths.flatMap(directoryPath => { - // Check pattern without negative prefix - const checkPattern = isNegativePattern(directoryPath) ? directoryPath.slice(1) : directoryPath; - - // Expand globstar directory patterns like **/dirname to **/dirname/** - if (shouldExpandGlobstarDirectory(checkPattern)) { - return getDirectoryGlob({directoryPath, files, extensions}); - } - - // Original logic for checking actual directories - const pathToCheck = normalizePathForDirectoryGlob(directoryPath, cwd); - return isDirectorySync(pathToCheck, fsImplementation) ? getDirectoryGlob({directoryPath, files, extensions}) : directoryPath; -}); +// pkg/dist-src/graphql.js +var NON_VARIABLE_OPTIONS = [ + "method", + "baseUrl", + "url", + "headers", + "request", + "query", + "mediaType", + "operationName" +]; +var FORBIDDEN_VARIABLE_OPTIONS = ["query", "method", "url"]; +var GHES_V3_SUFFIX_REGEX = /\/api\/v3\/?$/; +function graphql(request2, query, options) { + if (options) { + if (typeof query === "string" && "query" in options) { + return Promise.reject( + new Error(`[@octokit/graphql] "query" cannot be used as variable name`) + ); + } + for (const key in options) { + if (!FORBIDDEN_VARIABLE_OPTIONS.includes(key)) continue; + return Promise.reject( + new Error( + `[@octokit/graphql] "${key}" cannot be used as variable name` + ) + ); + } + } + const parsedOptions = typeof query === "string" ? Object.assign({ query }, options) : query; + const requestOptions = Object.keys( + parsedOptions + ).reduce((result, key) => { + if (NON_VARIABLE_OPTIONS.includes(key)) { + result[key] = parsedOptions[key]; + return result; + } + if (!result.variables) { + result.variables = {}; + } + result.variables[key] = parsedOptions[key]; + return result; + }, {}); + const baseUrl = parsedOptions.baseUrl || request2.endpoint.DEFAULTS.baseUrl; + if (GHES_V3_SUFFIX_REGEX.test(baseUrl)) { + requestOptions.url = baseUrl.replace(GHES_V3_SUFFIX_REGEX, "/api/graphql"); + } + return request2(requestOptions).then((response) => { + if (response.data.errors) { + const headers = {}; + for (const key of Object.keys(response.headers)) { + headers[key] = response.headers[key]; + } + throw new GraphqlResponseError( + requestOptions, + headers, + response.data + ); + } + return response.data.data; + }); +} -const toPatternsArray = patterns => { - patterns = [...new Set([patterns].flat())]; - assertPatternsInput(patterns); - return patterns; -}; +// pkg/dist-src/with-defaults.js +function graphql_dist_bundle_withDefaults(request2, newDefaults) { + const newRequest = request2.defaults(newDefaults); + const newApi = (query, options) => { + return graphql(newRequest, query, options); + }; + return Object.assign(newApi, { + defaults: graphql_dist_bundle_withDefaults.bind(null, newRequest), + endpoint: newRequest.endpoint + }); +} -const checkCwdOption = (cwd, fsImplementation = external_node_fs_) => { - if (!cwd || !fsImplementation.statSync) { - return; - } +// pkg/dist-src/index.js +var graphql2 = graphql_dist_bundle_withDefaults(request, { + headers: { + "user-agent": `octokit-graphql.js/${graphql_dist_bundle_VERSION} ${getUserAgent()}` + }, + method: "POST", + url: "/graphql" +}); +function withCustomRequest(customRequest) { + return graphql_dist_bundle_withDefaults(customRequest, { + method: "POST", + url: "/graphql" + }); +} - let stats; - try { - stats = fsImplementation.statSync(cwd); - } catch { - // If stat fails (e.g., path doesn't exist), let fast-glob handle it - return; - } - if (!stats.isDirectory()) { - throw new Error(`The \`cwd\` option must be a path to a directory, got: ${cwd}`); - } -}; +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@octokit/auth-token/6.0.0/08b03fb2cdd18bc44a83469bff0b5dd0f542de689bdb885e7a744e288e52565a/node_modules/@octokit/auth-token/dist-bundle/index.js +// pkg/dist-src/is-jwt.js +var b64url = "(?:[a-zA-Z0-9_-]+)"; +var sep = "\\."; +var jwtRE = new RegExp(`^${b64url}${sep}${b64url}${sep}${b64url}$`); +var isJWT = jwtRE.test.bind(jwtRE); -const globby_normalizeOptions = (options = {}) => { - // Normalize ignore to an array (fast-glob accepts string but we need array internally) - const ignore = options.ignore - ? (Array.isArray(options.ignore) ? options.ignore : [options.ignore]) - : []; +// pkg/dist-src/auth.js +async function auth(token) { + const isApp = isJWT(token); + const isInstallation = token.startsWith("v1.") || token.startsWith("ghs_"); + const isUserToServer = token.startsWith("ghu_"); + const tokenType = isApp ? "app" : isInstallation ? "installation" : isUserToServer ? "user-to-server" : "oauth"; + return { + type: "token", + token, + tokenType + }; +} - options = { - ...options, - ignore, - expandDirectories: options.expandDirectories ?? true, - cwd: toPath(options.cwd), - }; +// pkg/dist-src/with-authorization-prefix.js +function withAuthorizationPrefix(token) { + if (token.split(/\./).length === 3) { + return `bearer ${token}`; + } + return `token ${token}`; +} - checkCwdOption(options.cwd, options.fs); +// pkg/dist-src/hook.js +async function hook(token, request, route, parameters) { + const endpoint = request.endpoint.merge( + route, + parameters + ); + endpoint.headers.authorization = withAuthorizationPrefix(token); + return request(endpoint); +} - return options; +// pkg/dist-src/index.js +var createTokenAuth = function createTokenAuth2(token) { + if (!token) { + throw new Error("[@octokit/auth-token] No token passed to createTokenAuth"); + } + if (typeof token !== "string") { + throw new Error( + "[@octokit/auth-token] Token passed to createTokenAuth is not a string" + ); + } + token = token.replace(/^(token|bearer) +/i, ""); + return Object.assign(auth.bind(null, token), { + hook: hook.bind(null, token) + }); }; -const normalizeArguments = function_ => async (patterns, options) => function_(toPatternsArray(patterns), globby_normalizeOptions(options)); -const normalizeArgumentsSync = function_ => (patterns, options) => function_(toPatternsArray(patterns), globby_normalizeOptions(options)); -const getIgnoreFilesPatterns = options => { - const {ignoreFiles, gitignore} = options; +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@octokit/core/7.0.6/62376fcda0a91a2d50ad254cd93e83ae4bd5317a357d24ba6c141c5fcf9334af/node_modules/@octokit/core/dist-src/version.js +const version_VERSION = "7.0.6"; - const patterns = ignoreFiles ? toPatternsArray(ignoreFiles) : []; - if (gitignore) { - patterns.push(GITIGNORE_FILES_PATTERN); - } - return patterns; -}; +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@octokit/core/7.0.6/62376fcda0a91a2d50ad254cd93e83ae4bd5317a357d24ba6c141c5fcf9334af/node_modules/@octokit/core/dist-src/index.js -/** -Apply gitignore patterns to options and return filter predicate. -When negation patterns are present (e.g., '!important.log'), we cannot pass positive patterns to fast-glob because it would filter out files before our predicate can re-include them. In this case, we rely entirely on the predicate for filtering, which handles negations correctly. -When there are no negations, we optimize by passing patterns to fast-glob's ignore option to skip directories during traversal (performance optimization). -All patterns (including negated) are always used in the filter predicate to ensure correct Git-compatible behavior. -@returns {Promise<{options: Object, filter: Function}>} -*/ -const applyIgnoreFilesAndGetFilter = async options => { - const ignoreFilesPatterns = getIgnoreFilesPatterns(options); - if (ignoreFilesPatterns.length === 0) { - return { - options, - filter: createFilterFunction(false, options.cwd), - }; - } +const dist_src_noop = () => { +}; +const consoleWarn = console.warn.bind(console); +const consoleError = console.error.bind(console); +function createLogger(logger = {}) { + if (typeof logger.debug !== "function") { + logger.debug = dist_src_noop; + } + if (typeof logger.info !== "function") { + logger.info = dist_src_noop; + } + if (typeof logger.warn !== "function") { + logger.warn = consoleWarn; + } + if (typeof logger.error !== "function") { + logger.error = consoleError; + } + return logger; +} +const userAgentTrail = `octokit-core.js/${version_VERSION} ${getUserAgent()}`; +class Octokit { + static VERSION = version_VERSION; + static defaults(defaults) { + const OctokitWithDefaults = class extends this { + constructor(...args) { + const options = args[0] || {}; + if (typeof defaults === "function") { + super(defaults(options)); + return; + } + super( + Object.assign( + {}, + defaults, + options, + options.userAgent && defaults.userAgent ? { + userAgent: `${options.userAgent} ${defaults.userAgent}` + } : null + ) + ); + } + }; + return OctokitWithDefaults; + } + static plugins = []; + /** + * Attach a plugin (or many) to your Octokit instance. + * + * @example + * const API = Octokit.plugin(plugin1, plugin2, plugin3, ...) + */ + static plugin(...newPlugins) { + const currentPlugins = this.plugins; + const NewOctokit = class extends this { + static plugins = currentPlugins.concat( + newPlugins.filter((plugin) => !currentPlugins.includes(plugin)) + ); + }; + return NewOctokit; + } + constructor(options = {}) { + const hook = new before_after_hook.Collection(); + const requestDefaults = { + baseUrl: request.endpoint.DEFAULTS.baseUrl, + headers: {}, + request: Object.assign({}, options.request, { + // @ts-ignore internal usage only, no need to type + hook: hook.bind(null, "request") + }), + mediaType: { + previews: [], + format: "" + } + }; + requestDefaults.headers["user-agent"] = options.userAgent ? `${options.userAgent} ${userAgentTrail}` : userAgentTrail; + if (options.baseUrl) { + requestDefaults.baseUrl = options.baseUrl; + } + if (options.previews) { + requestDefaults.mediaType.previews = options.previews; + } + if (options.timeZone) { + requestDefaults.headers["time-zone"] = options.timeZone; + } + this.request = request.defaults(requestDefaults); + this.graphql = withCustomRequest(this.request).defaults(requestDefaults); + this.log = createLogger(options.log); + this.hook = hook; + if (!options.authStrategy) { + if (!options.auth) { + this.auth = async () => ({ + type: "unauthenticated" + }); + } else { + const auth = createTokenAuth(options.auth); + hook.wrap("request", auth.hook); + this.auth = auth; + } + } else { + const { authStrategy, ...otherOptions } = options; + const auth = authStrategy( + Object.assign( + { + request: this.request, + log: this.log, + // we pass the current octokit instance as well as its constructor options + // to allow for authentication strategies that return a new octokit instance + // that shares the same internal state as the current one. The original + // requirement for this was the "event-octokit" authentication strategy + // of https://github.com/probot/octokit-auth-probot. + octokit: this, + octokitOptions: otherOptions + }, + options.auth + ) + ); + hook.wrap("request", auth.hook); + this.auth = auth; + } + const classConstructor = this.constructor; + for (let i = 0; i < classConstructor.plugins.length; ++i) { + Object.assign(this, classConstructor.plugins[i](this, options)); + } + } + // assigned during constructor + request; + graphql; + log; + hook; + // TODO: type `octokit.auth` based on passed options.authStrategy + auth; +} - // Read ignore files once and get both patterns and predicate - // Enable parent .gitignore search when using gitignore option - const includeParentIgnoreFiles = options.gitignore === true; - const {patterns, predicate, usingGitRoot} = await getIgnorePatternsAndPredicate(ignoreFilesPatterns, options, includeParentIgnoreFiles); - // Convert patterns to fast-glob format (may return empty array if predicate should handle everything) - const patternsForFastGlob = convertPatternsForFastGlob(patterns, usingGitRoot, normalizeDirectoryPatternForFastGlob); +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@octokit/plugin-request-log/6.0.0/14b098bdb1f0daf676fbad85305c94e3f10bcf8e271a2efb211b347676ca5591/node_modules/@octokit/plugin-request-log/dist-src/version.js +const dist_src_version_VERSION = "6.0.0"; - const modifiedOptions = { - ...options, - ignore: [...options.ignore, ...patternsForFastGlob], - }; - return { - options: modifiedOptions, - filter: createFilterFunction(predicate, options.cwd), - }; -}; +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@octokit/plugin-request-log/6.0.0/14b098bdb1f0daf676fbad85305c94e3f10bcf8e271a2efb211b347676ca5591/node_modules/@octokit/plugin-request-log/dist-src/index.js -/** -Apply gitignore patterns to options and return filter predicate (sync version). +function requestLog(octokit) { + octokit.hook.wrap("request", (request, options) => { + octokit.log.debug("request", options); + const start = Date.now(); + const requestOptions = octokit.request.endpoint.parse(options); + const path = requestOptions.url.replace(options.baseUrl, ""); + return request(options).then((response) => { + const requestId = response.headers["x-github-request-id"]; + octokit.log.info( + `${requestOptions.method} ${path} - ${response.status} with id ${requestId} in ${Date.now() - start}ms` + ); + return response; + }).catch((error) => { + const requestId = error.response?.headers["x-github-request-id"] || "UNKNOWN"; + octokit.log.error( + `${requestOptions.method} ${path} - ${error.status} with id ${requestId} in ${Date.now() - start}ms` + ); + throw error; + }); + }); +} +requestLog.VERSION = dist_src_version_VERSION; -@returns {{options: Object, filter: Function}} -*/ -const applyIgnoreFilesAndGetFilterSync = options => { - const ignoreFilesPatterns = getIgnoreFilesPatterns(options); - if (ignoreFilesPatterns.length === 0) { - return { - options, - filter: createFilterFunction(false, options.cwd), - }; - } +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@octokit/plugin-paginate-rest/14.0.0/19ec16e2c5fdca4ca7f96c8aee21c7af275d329ba4ff9a2237dac909640ef23f/node_modules/@octokit/plugin-paginate-rest/dist-bundle/index.js +// pkg/dist-src/version.js +var plugin_paginate_rest_dist_bundle_VERSION = "0.0.0-development"; - // Read ignore files once and get both patterns and predicate - // Enable parent .gitignore search when using gitignore option - const includeParentIgnoreFiles = options.gitignore === true; - const {patterns, predicate, usingGitRoot} = getIgnorePatternsAndPredicateSync(ignoreFilesPatterns, options, includeParentIgnoreFiles); +// pkg/dist-src/normalize-paginated-list-response.js +function normalizePaginatedListResponse(response) { + if (!response.data) { + return { + ...response, + data: [] + }; + } + const responseNeedsNormalization = ("total_count" in response.data || "total_commits" in response.data) && !("url" in response.data); + if (!responseNeedsNormalization) return response; + const incompleteResults = response.data.incomplete_results; + const repositorySelection = response.data.repository_selection; + const totalCount = response.data.total_count; + const totalCommits = response.data.total_commits; + delete response.data.incomplete_results; + delete response.data.repository_selection; + delete response.data.total_count; + delete response.data.total_commits; + const namespaceKey = Object.keys(response.data)[0]; + const data = response.data[namespaceKey]; + response.data = data; + if (typeof incompleteResults !== "undefined") { + response.data.incomplete_results = incompleteResults; + } + if (typeof repositorySelection !== "undefined") { + response.data.repository_selection = repositorySelection; + } + response.data.total_count = totalCount; + response.data.total_commits = totalCommits; + return response; +} - // Convert patterns to fast-glob format (may return empty array if predicate should handle everything) - const patternsForFastGlob = convertPatternsForFastGlob(patterns, usingGitRoot, normalizeDirectoryPatternForFastGlob); +// pkg/dist-src/iterator.js +function iterator(octokit, route, parameters) { + const options = typeof route === "function" ? route.endpoint(parameters) : octokit.request.endpoint(route, parameters); + const requestMethod = typeof route === "function" ? route : octokit.request; + const method = options.method; + const headers = options.headers; + let url = options.url; + return { + [Symbol.asyncIterator]: () => ({ + async next() { + if (!url) return { done: true }; + try { + const response = await requestMethod({ method, url, headers }); + const normalizedResponse = normalizePaginatedListResponse(response); + url = ((normalizedResponse.headers.link || "").match( + /<([^<>]+)>;\s*rel="next"/ + ) || [])[1]; + if (!url && "total_commits" in normalizedResponse.data) { + const parsedUrl = new URL(normalizedResponse.url); + const params = parsedUrl.searchParams; + const page = parseInt(params.get("page") || "1", 10); + const per_page = parseInt(params.get("per_page") || "250", 10); + if (page * per_page < normalizedResponse.data.total_commits) { + params.set("page", String(page + 1)); + url = parsedUrl.toString(); + } + } + return { value: normalizedResponse }; + } catch (error) { + if (error.status !== 409) throw error; + url = ""; + return { + value: { + status: 200, + headers: {}, + data: [] + } + }; + } + } + }) + }; +} - const modifiedOptions = { - ...options, - ignore: [...options.ignore, ...patternsForFastGlob], - }; +// pkg/dist-src/paginate.js +function paginate(octokit, route, parameters, mapFn) { + if (typeof parameters === "function") { + mapFn = parameters; + parameters = void 0; + } + return gather( + octokit, + [], + iterator(octokit, route, parameters)[Symbol.asyncIterator](), + mapFn + ); +} +function gather(octokit, results, iterator2, mapFn) { + return iterator2.next().then((result) => { + if (result.done) { + return results; + } + let earlyExit = false; + function done() { + earlyExit = true; + } + results = results.concat( + mapFn ? mapFn(result.value, done) : result.value.data + ); + if (earlyExit) { + return results; + } + return gather(octokit, results, iterator2, mapFn); + }); +} - return { - options: modifiedOptions, - filter: createFilterFunction(predicate, options.cwd), - }; -}; +// pkg/dist-src/compose-paginate.js +var composePaginateRest = Object.assign(paginate, { + iterator +}); -const createFilterFunction = (isIgnored, cwd) => { - const seen = new Set(); - const basePath = cwd || external_node_process_namespaceObject.cwd(); - const pathCache = new Map(); // Cache for resolved paths +// pkg/dist-src/generated/paginating-endpoints.js +var paginatingEndpoints = (/* unused pure expression or super */ null && ([ + "GET /advisories", + "GET /app/hook/deliveries", + "GET /app/installation-requests", + "GET /app/installations", + "GET /assignments/{assignment_id}/accepted_assignments", + "GET /classrooms", + "GET /classrooms/{classroom_id}/assignments", + "GET /enterprises/{enterprise}/code-security/configurations", + "GET /enterprises/{enterprise}/code-security/configurations/{configuration_id}/repositories", + "GET /enterprises/{enterprise}/dependabot/alerts", + "GET /enterprises/{enterprise}/teams", + "GET /enterprises/{enterprise}/teams/{enterprise-team}/memberships", + "GET /enterprises/{enterprise}/teams/{enterprise-team}/organizations", + "GET /events", + "GET /gists", + "GET /gists/public", + "GET /gists/starred", + "GET /gists/{gist_id}/comments", + "GET /gists/{gist_id}/commits", + "GET /gists/{gist_id}/forks", + "GET /installation/repositories", + "GET /issues", + "GET /licenses", + "GET /marketplace_listing/plans", + "GET /marketplace_listing/plans/{plan_id}/accounts", + "GET /marketplace_listing/stubbed/plans", + "GET /marketplace_listing/stubbed/plans/{plan_id}/accounts", + "GET /networks/{owner}/{repo}/events", + "GET /notifications", + "GET /organizations", + "GET /organizations/{org}/dependabot/repository-access", + "GET /orgs/{org}/actions/cache/usage-by-repository", + "GET /orgs/{org}/actions/hosted-runners", + "GET /orgs/{org}/actions/permissions/repositories", + "GET /orgs/{org}/actions/permissions/self-hosted-runners/repositories", + "GET /orgs/{org}/actions/runner-groups", + "GET /orgs/{org}/actions/runner-groups/{runner_group_id}/hosted-runners", + "GET /orgs/{org}/actions/runner-groups/{runner_group_id}/repositories", + "GET /orgs/{org}/actions/runner-groups/{runner_group_id}/runners", + "GET /orgs/{org}/actions/runners", + "GET /orgs/{org}/actions/secrets", + "GET /orgs/{org}/actions/secrets/{secret_name}/repositories", + "GET /orgs/{org}/actions/variables", + "GET /orgs/{org}/actions/variables/{name}/repositories", + "GET /orgs/{org}/attestations/repositories", + "GET /orgs/{org}/attestations/{subject_digest}", + "GET /orgs/{org}/blocks", + "GET /orgs/{org}/campaigns", + "GET /orgs/{org}/code-scanning/alerts", + "GET /orgs/{org}/code-security/configurations", + "GET /orgs/{org}/code-security/configurations/{configuration_id}/repositories", + "GET /orgs/{org}/codespaces", + "GET /orgs/{org}/codespaces/secrets", + "GET /orgs/{org}/codespaces/secrets/{secret_name}/repositories", + "GET /orgs/{org}/copilot/billing/seats", + "GET /orgs/{org}/copilot/metrics", + "GET /orgs/{org}/dependabot/alerts", + "GET /orgs/{org}/dependabot/secrets", + "GET /orgs/{org}/dependabot/secrets/{secret_name}/repositories", + "GET /orgs/{org}/events", + "GET /orgs/{org}/failed_invitations", + "GET /orgs/{org}/hooks", + "GET /orgs/{org}/hooks/{hook_id}/deliveries", + "GET /orgs/{org}/insights/api/route-stats/{actor_type}/{actor_id}", + "GET /orgs/{org}/insights/api/subject-stats", + "GET /orgs/{org}/insights/api/user-stats/{user_id}", + "GET /orgs/{org}/installations", + "GET /orgs/{org}/invitations", + "GET /orgs/{org}/invitations/{invitation_id}/teams", + "GET /orgs/{org}/issues", + "GET /orgs/{org}/members", + "GET /orgs/{org}/members/{username}/codespaces", + "GET /orgs/{org}/migrations", + "GET /orgs/{org}/migrations/{migration_id}/repositories", + "GET /orgs/{org}/organization-roles/{role_id}/teams", + "GET /orgs/{org}/organization-roles/{role_id}/users", + "GET /orgs/{org}/outside_collaborators", + "GET /orgs/{org}/packages", + "GET /orgs/{org}/packages/{package_type}/{package_name}/versions", + "GET /orgs/{org}/personal-access-token-requests", + "GET /orgs/{org}/personal-access-token-requests/{pat_request_id}/repositories", + "GET /orgs/{org}/personal-access-tokens", + "GET /orgs/{org}/personal-access-tokens/{pat_id}/repositories", + "GET /orgs/{org}/private-registries", + "GET /orgs/{org}/projects", + "GET /orgs/{org}/projectsV2", + "GET /orgs/{org}/projectsV2/{project_number}/fields", + "GET /orgs/{org}/projectsV2/{project_number}/items", + "GET /orgs/{org}/properties/values", + "GET /orgs/{org}/public_members", + "GET /orgs/{org}/repos", + "GET /orgs/{org}/rulesets", + "GET /orgs/{org}/rulesets/rule-suites", + "GET /orgs/{org}/rulesets/{ruleset_id}/history", + "GET /orgs/{org}/secret-scanning/alerts", + "GET /orgs/{org}/security-advisories", + "GET /orgs/{org}/settings/immutable-releases/repositories", + "GET /orgs/{org}/settings/network-configurations", + "GET /orgs/{org}/team/{team_slug}/copilot/metrics", + "GET /orgs/{org}/teams", + "GET /orgs/{org}/teams/{team_slug}/discussions", + "GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments", + "GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions", + "GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions", + "GET /orgs/{org}/teams/{team_slug}/invitations", + "GET /orgs/{org}/teams/{team_slug}/members", + "GET /orgs/{org}/teams/{team_slug}/projects", + "GET /orgs/{org}/teams/{team_slug}/repos", + "GET /orgs/{org}/teams/{team_slug}/teams", + "GET /projects/{project_id}/collaborators", + "GET /repos/{owner}/{repo}/actions/artifacts", + "GET /repos/{owner}/{repo}/actions/caches", + "GET /repos/{owner}/{repo}/actions/organization-secrets", + "GET /repos/{owner}/{repo}/actions/organization-variables", + "GET /repos/{owner}/{repo}/actions/runners", + "GET /repos/{owner}/{repo}/actions/runs", + "GET /repos/{owner}/{repo}/actions/runs/{run_id}/artifacts", + "GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}/jobs", + "GET /repos/{owner}/{repo}/actions/runs/{run_id}/jobs", + "GET /repos/{owner}/{repo}/actions/secrets", + "GET /repos/{owner}/{repo}/actions/variables", + "GET /repos/{owner}/{repo}/actions/workflows", + "GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/runs", + "GET /repos/{owner}/{repo}/activity", + "GET /repos/{owner}/{repo}/assignees", + "GET /repos/{owner}/{repo}/attestations/{subject_digest}", + "GET /repos/{owner}/{repo}/branches", + "GET /repos/{owner}/{repo}/check-runs/{check_run_id}/annotations", + "GET /repos/{owner}/{repo}/check-suites/{check_suite_id}/check-runs", + "GET /repos/{owner}/{repo}/code-scanning/alerts", + "GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}/instances", + "GET /repos/{owner}/{repo}/code-scanning/analyses", + "GET /repos/{owner}/{repo}/codespaces", + "GET /repos/{owner}/{repo}/codespaces/devcontainers", + "GET /repos/{owner}/{repo}/codespaces/secrets", + "GET /repos/{owner}/{repo}/collaborators", + "GET /repos/{owner}/{repo}/comments", + "GET /repos/{owner}/{repo}/comments/{comment_id}/reactions", + "GET /repos/{owner}/{repo}/commits", + "GET /repos/{owner}/{repo}/commits/{commit_sha}/comments", + "GET /repos/{owner}/{repo}/commits/{commit_sha}/pulls", + "GET /repos/{owner}/{repo}/commits/{ref}/check-runs", + "GET /repos/{owner}/{repo}/commits/{ref}/check-suites", + "GET /repos/{owner}/{repo}/commits/{ref}/status", + "GET /repos/{owner}/{repo}/commits/{ref}/statuses", + "GET /repos/{owner}/{repo}/compare/{basehead}", + "GET /repos/{owner}/{repo}/compare/{base}...{head}", + "GET /repos/{owner}/{repo}/contributors", + "GET /repos/{owner}/{repo}/dependabot/alerts", + "GET /repos/{owner}/{repo}/dependabot/secrets", + "GET /repos/{owner}/{repo}/deployments", + "GET /repos/{owner}/{repo}/deployments/{deployment_id}/statuses", + "GET /repos/{owner}/{repo}/environments", + "GET /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies", + "GET /repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules/apps", + "GET /repos/{owner}/{repo}/environments/{environment_name}/secrets", + "GET /repos/{owner}/{repo}/environments/{environment_name}/variables", + "GET /repos/{owner}/{repo}/events", + "GET /repos/{owner}/{repo}/forks", + "GET /repos/{owner}/{repo}/hooks", + "GET /repos/{owner}/{repo}/hooks/{hook_id}/deliveries", + "GET /repos/{owner}/{repo}/invitations", + "GET /repos/{owner}/{repo}/issues", + "GET /repos/{owner}/{repo}/issues/comments", + "GET /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions", + "GET /repos/{owner}/{repo}/issues/events", + "GET /repos/{owner}/{repo}/issues/{issue_number}/comments", + "GET /repos/{owner}/{repo}/issues/{issue_number}/dependencies/blocked_by", + "GET /repos/{owner}/{repo}/issues/{issue_number}/dependencies/blocking", + "GET /repos/{owner}/{repo}/issues/{issue_number}/events", + "GET /repos/{owner}/{repo}/issues/{issue_number}/labels", + "GET /repos/{owner}/{repo}/issues/{issue_number}/reactions", + "GET /repos/{owner}/{repo}/issues/{issue_number}/sub_issues", + "GET /repos/{owner}/{repo}/issues/{issue_number}/timeline", + "GET /repos/{owner}/{repo}/keys", + "GET /repos/{owner}/{repo}/labels", + "GET /repos/{owner}/{repo}/milestones", + "GET /repos/{owner}/{repo}/milestones/{milestone_number}/labels", + "GET /repos/{owner}/{repo}/notifications", + "GET /repos/{owner}/{repo}/pages/builds", + "GET /repos/{owner}/{repo}/projects", + "GET /repos/{owner}/{repo}/pulls", + "GET /repos/{owner}/{repo}/pulls/comments", + "GET /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions", + "GET /repos/{owner}/{repo}/pulls/{pull_number}/comments", + "GET /repos/{owner}/{repo}/pulls/{pull_number}/commits", + "GET /repos/{owner}/{repo}/pulls/{pull_number}/files", + "GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews", + "GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/comments", + "GET /repos/{owner}/{repo}/releases", + "GET /repos/{owner}/{repo}/releases/{release_id}/assets", + "GET /repos/{owner}/{repo}/releases/{release_id}/reactions", + "GET /repos/{owner}/{repo}/rules/branches/{branch}", + "GET /repos/{owner}/{repo}/rulesets", + "GET /repos/{owner}/{repo}/rulesets/rule-suites", + "GET /repos/{owner}/{repo}/rulesets/{ruleset_id}/history", + "GET /repos/{owner}/{repo}/secret-scanning/alerts", + "GET /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}/locations", + "GET /repos/{owner}/{repo}/security-advisories", + "GET /repos/{owner}/{repo}/stargazers", + "GET /repos/{owner}/{repo}/subscribers", + "GET /repos/{owner}/{repo}/tags", + "GET /repos/{owner}/{repo}/teams", + "GET /repos/{owner}/{repo}/topics", + "GET /repositories", + "GET /search/code", + "GET /search/commits", + "GET /search/issues", + "GET /search/labels", + "GET /search/repositories", + "GET /search/topics", + "GET /search/users", + "GET /teams/{team_id}/discussions", + "GET /teams/{team_id}/discussions/{discussion_number}/comments", + "GET /teams/{team_id}/discussions/{discussion_number}/comments/{comment_number}/reactions", + "GET /teams/{team_id}/discussions/{discussion_number}/reactions", + "GET /teams/{team_id}/invitations", + "GET /teams/{team_id}/members", + "GET /teams/{team_id}/projects", + "GET /teams/{team_id}/repos", + "GET /teams/{team_id}/teams", + "GET /user/blocks", + "GET /user/codespaces", + "GET /user/codespaces/secrets", + "GET /user/emails", + "GET /user/followers", + "GET /user/following", + "GET /user/gpg_keys", + "GET /user/installations", + "GET /user/installations/{installation_id}/repositories", + "GET /user/issues", + "GET /user/keys", + "GET /user/marketplace_purchases", + "GET /user/marketplace_purchases/stubbed", + "GET /user/memberships/orgs", + "GET /user/migrations", + "GET /user/migrations/{migration_id}/repositories", + "GET /user/orgs", + "GET /user/packages", + "GET /user/packages/{package_type}/{package_name}/versions", + "GET /user/public_emails", + "GET /user/repos", + "GET /user/repository_invitations", + "GET /user/social_accounts", + "GET /user/ssh_signing_keys", + "GET /user/starred", + "GET /user/subscriptions", + "GET /user/teams", + "GET /users", + "GET /users/{username}/attestations/{subject_digest}", + "GET /users/{username}/events", + "GET /users/{username}/events/orgs/{org}", + "GET /users/{username}/events/public", + "GET /users/{username}/followers", + "GET /users/{username}/following", + "GET /users/{username}/gists", + "GET /users/{username}/gpg_keys", + "GET /users/{username}/keys", + "GET /users/{username}/orgs", + "GET /users/{username}/packages", + "GET /users/{username}/projects", + "GET /users/{username}/projectsV2", + "GET /users/{username}/projectsV2/{project_number}/fields", + "GET /users/{username}/projectsV2/{project_number}/items", + "GET /users/{username}/received_events", + "GET /users/{username}/received_events/public", + "GET /users/{username}/repos", + "GET /users/{username}/social_accounts", + "GET /users/{username}/ssh_signing_keys", + "GET /users/{username}/starred", + "GET /users/{username}/subscriptions" +])); - return fastGlobResult => { - const pathKey = external_node_path_.normalize(fastGlobResult.path ?? fastGlobResult); +// pkg/dist-src/paginating-endpoints.js +function isPaginatingEndpoint(arg) { + if (typeof arg === "string") { + return paginatingEndpoints.includes(arg); + } else { + return false; + } +} - // Check seen set first (fast path) - if (seen.has(pathKey)) { - return false; - } +// pkg/dist-src/index.js +function paginateRest(octokit) { + return { + paginate: Object.assign(paginate.bind(null, octokit), { + iterator: iterator.bind(null, octokit) + }) + }; +} +paginateRest.VERSION = plugin_paginate_rest_dist_bundle_VERSION; - // Only compute absolute path and check predicate if needed - if (isIgnored) { - let absolutePath = pathCache.get(pathKey); - if (absolutePath === undefined) { - absolutePath = external_node_path_.isAbsolute(pathKey) ? pathKey : external_node_path_.resolve(basePath, pathKey); - pathCache.set(pathKey, absolutePath); - // Only clear path cache if it gets too large - // Never clear 'seen' as it's needed for deduplication - if (pathCache.size > 10_000) { - pathCache.clear(); - } - } +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@octokit/plugin-rest-endpoint-methods/17.0.0/23bcad6a6f09bbdd8bd9193c1b6ebd3b4d7d5c15f3d5d6a119345284a74f0760/node_modules/@octokit/plugin-rest-endpoint-methods/dist-src/version.js +const plugin_rest_endpoint_methods_dist_src_version_VERSION = "17.0.0"; - if (isIgnored(absolutePath)) { - return false; - } - } +//# sourceMappingURL=version.js.map - seen.add(pathKey); - return true; - }; +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@octokit/plugin-rest-endpoint-methods/17.0.0/23bcad6a6f09bbdd8bd9193c1b6ebd3b4d7d5c15f3d5d6a119345284a74f0760/node_modules/@octokit/plugin-rest-endpoint-methods/dist-src/generated/endpoints.js +const Endpoints = { + actions: { + addCustomLabelsToSelfHostedRunnerForOrg: [ + "POST /orgs/{org}/actions/runners/{runner_id}/labels" + ], + addCustomLabelsToSelfHostedRunnerForRepo: [ + "POST /repos/{owner}/{repo}/actions/runners/{runner_id}/labels" + ], + addRepoAccessToSelfHostedRunnerGroupInOrg: [ + "PUT /orgs/{org}/actions/runner-groups/{runner_group_id}/repositories/{repository_id}" + ], + addSelectedRepoToOrgSecret: [ + "PUT /orgs/{org}/actions/secrets/{secret_name}/repositories/{repository_id}" + ], + addSelectedRepoToOrgVariable: [ + "PUT /orgs/{org}/actions/variables/{name}/repositories/{repository_id}" + ], + approveWorkflowRun: [ + "POST /repos/{owner}/{repo}/actions/runs/{run_id}/approve" + ], + cancelWorkflowRun: [ + "POST /repos/{owner}/{repo}/actions/runs/{run_id}/cancel" + ], + createEnvironmentVariable: [ + "POST /repos/{owner}/{repo}/environments/{environment_name}/variables" + ], + createHostedRunnerForOrg: ["POST /orgs/{org}/actions/hosted-runners"], + createOrUpdateEnvironmentSecret: [ + "PUT /repos/{owner}/{repo}/environments/{environment_name}/secrets/{secret_name}" + ], + createOrUpdateOrgSecret: ["PUT /orgs/{org}/actions/secrets/{secret_name}"], + createOrUpdateRepoSecret: [ + "PUT /repos/{owner}/{repo}/actions/secrets/{secret_name}" + ], + createOrgVariable: ["POST /orgs/{org}/actions/variables"], + createRegistrationTokenForOrg: [ + "POST /orgs/{org}/actions/runners/registration-token" + ], + createRegistrationTokenForRepo: [ + "POST /repos/{owner}/{repo}/actions/runners/registration-token" + ], + createRemoveTokenForOrg: ["POST /orgs/{org}/actions/runners/remove-token"], + createRemoveTokenForRepo: [ + "POST /repos/{owner}/{repo}/actions/runners/remove-token" + ], + createRepoVariable: ["POST /repos/{owner}/{repo}/actions/variables"], + createWorkflowDispatch: [ + "POST /repos/{owner}/{repo}/actions/workflows/{workflow_id}/dispatches" + ], + deleteActionsCacheById: [ + "DELETE /repos/{owner}/{repo}/actions/caches/{cache_id}" + ], + deleteActionsCacheByKey: [ + "DELETE /repos/{owner}/{repo}/actions/caches{?key,ref}" + ], + deleteArtifact: [ + "DELETE /repos/{owner}/{repo}/actions/artifacts/{artifact_id}" + ], + deleteCustomImageFromOrg: [ + "DELETE /orgs/{org}/actions/hosted-runners/images/custom/{image_definition_id}" + ], + deleteCustomImageVersionFromOrg: [ + "DELETE /orgs/{org}/actions/hosted-runners/images/custom/{image_definition_id}/versions/{version}" + ], + deleteEnvironmentSecret: [ + "DELETE /repos/{owner}/{repo}/environments/{environment_name}/secrets/{secret_name}" + ], + deleteEnvironmentVariable: [ + "DELETE /repos/{owner}/{repo}/environments/{environment_name}/variables/{name}" + ], + deleteHostedRunnerForOrg: [ + "DELETE /orgs/{org}/actions/hosted-runners/{hosted_runner_id}" + ], + deleteOrgSecret: ["DELETE /orgs/{org}/actions/secrets/{secret_name}"], + deleteOrgVariable: ["DELETE /orgs/{org}/actions/variables/{name}"], + deleteRepoSecret: [ + "DELETE /repos/{owner}/{repo}/actions/secrets/{secret_name}" + ], + deleteRepoVariable: [ + "DELETE /repos/{owner}/{repo}/actions/variables/{name}" + ], + deleteSelfHostedRunnerFromOrg: [ + "DELETE /orgs/{org}/actions/runners/{runner_id}" + ], + deleteSelfHostedRunnerFromRepo: [ + "DELETE /repos/{owner}/{repo}/actions/runners/{runner_id}" + ], + deleteWorkflowRun: ["DELETE /repos/{owner}/{repo}/actions/runs/{run_id}"], + deleteWorkflowRunLogs: [ + "DELETE /repos/{owner}/{repo}/actions/runs/{run_id}/logs" + ], + disableSelectedRepositoryGithubActionsOrganization: [ + "DELETE /orgs/{org}/actions/permissions/repositories/{repository_id}" + ], + disableWorkflow: [ + "PUT /repos/{owner}/{repo}/actions/workflows/{workflow_id}/disable" + ], + downloadArtifact: [ + "GET /repos/{owner}/{repo}/actions/artifacts/{artifact_id}/{archive_format}" + ], + downloadJobLogsForWorkflowRun: [ + "GET /repos/{owner}/{repo}/actions/jobs/{job_id}/logs" + ], + downloadWorkflowRunAttemptLogs: [ + "GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}/logs" + ], + downloadWorkflowRunLogs: [ + "GET /repos/{owner}/{repo}/actions/runs/{run_id}/logs" + ], + enableSelectedRepositoryGithubActionsOrganization: [ + "PUT /orgs/{org}/actions/permissions/repositories/{repository_id}" + ], + enableWorkflow: [ + "PUT /repos/{owner}/{repo}/actions/workflows/{workflow_id}/enable" + ], + forceCancelWorkflowRun: [ + "POST /repos/{owner}/{repo}/actions/runs/{run_id}/force-cancel" + ], + generateRunnerJitconfigForOrg: [ + "POST /orgs/{org}/actions/runners/generate-jitconfig" + ], + generateRunnerJitconfigForRepo: [ + "POST /repos/{owner}/{repo}/actions/runners/generate-jitconfig" + ], + getActionsCacheList: ["GET /repos/{owner}/{repo}/actions/caches"], + getActionsCacheUsage: ["GET /repos/{owner}/{repo}/actions/cache/usage"], + getActionsCacheUsageByRepoForOrg: [ + "GET /orgs/{org}/actions/cache/usage-by-repository" + ], + getActionsCacheUsageForOrg: ["GET /orgs/{org}/actions/cache/usage"], + getAllowedActionsOrganization: [ + "GET /orgs/{org}/actions/permissions/selected-actions" + ], + getAllowedActionsRepository: [ + "GET /repos/{owner}/{repo}/actions/permissions/selected-actions" + ], + getArtifact: ["GET /repos/{owner}/{repo}/actions/artifacts/{artifact_id}"], + getCustomImageForOrg: [ + "GET /orgs/{org}/actions/hosted-runners/images/custom/{image_definition_id}" + ], + getCustomImageVersionForOrg: [ + "GET /orgs/{org}/actions/hosted-runners/images/custom/{image_definition_id}/versions/{version}" + ], + getCustomOidcSubClaimForRepo: [ + "GET /repos/{owner}/{repo}/actions/oidc/customization/sub" + ], + getEnvironmentPublicKey: [ + "GET /repos/{owner}/{repo}/environments/{environment_name}/secrets/public-key" + ], + getEnvironmentSecret: [ + "GET /repos/{owner}/{repo}/environments/{environment_name}/secrets/{secret_name}" + ], + getEnvironmentVariable: [ + "GET /repos/{owner}/{repo}/environments/{environment_name}/variables/{name}" + ], + getGithubActionsDefaultWorkflowPermissionsOrganization: [ + "GET /orgs/{org}/actions/permissions/workflow" + ], + getGithubActionsDefaultWorkflowPermissionsRepository: [ + "GET /repos/{owner}/{repo}/actions/permissions/workflow" + ], + getGithubActionsPermissionsOrganization: [ + "GET /orgs/{org}/actions/permissions" + ], + getGithubActionsPermissionsRepository: [ + "GET /repos/{owner}/{repo}/actions/permissions" + ], + getHostedRunnerForOrg: [ + "GET /orgs/{org}/actions/hosted-runners/{hosted_runner_id}" + ], + getHostedRunnersGithubOwnedImagesForOrg: [ + "GET /orgs/{org}/actions/hosted-runners/images/github-owned" + ], + getHostedRunnersLimitsForOrg: [ + "GET /orgs/{org}/actions/hosted-runners/limits" + ], + getHostedRunnersMachineSpecsForOrg: [ + "GET /orgs/{org}/actions/hosted-runners/machine-sizes" + ], + getHostedRunnersPartnerImagesForOrg: [ + "GET /orgs/{org}/actions/hosted-runners/images/partner" + ], + getHostedRunnersPlatformsForOrg: [ + "GET /orgs/{org}/actions/hosted-runners/platforms" + ], + getJobForWorkflowRun: ["GET /repos/{owner}/{repo}/actions/jobs/{job_id}"], + getOrgPublicKey: ["GET /orgs/{org}/actions/secrets/public-key"], + getOrgSecret: ["GET /orgs/{org}/actions/secrets/{secret_name}"], + getOrgVariable: ["GET /orgs/{org}/actions/variables/{name}"], + getPendingDeploymentsForRun: [ + "GET /repos/{owner}/{repo}/actions/runs/{run_id}/pending_deployments" + ], + getRepoPermissions: [ + "GET /repos/{owner}/{repo}/actions/permissions", + {}, + { renamed: ["actions", "getGithubActionsPermissionsRepository"] } + ], + getRepoPublicKey: ["GET /repos/{owner}/{repo}/actions/secrets/public-key"], + getRepoSecret: ["GET /repos/{owner}/{repo}/actions/secrets/{secret_name}"], + getRepoVariable: ["GET /repos/{owner}/{repo}/actions/variables/{name}"], + getReviewsForRun: [ + "GET /repos/{owner}/{repo}/actions/runs/{run_id}/approvals" + ], + getSelfHostedRunnerForOrg: ["GET /orgs/{org}/actions/runners/{runner_id}"], + getSelfHostedRunnerForRepo: [ + "GET /repos/{owner}/{repo}/actions/runners/{runner_id}" + ], + getWorkflow: ["GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}"], + getWorkflowAccessToRepository: [ + "GET /repos/{owner}/{repo}/actions/permissions/access" + ], + getWorkflowRun: ["GET /repos/{owner}/{repo}/actions/runs/{run_id}"], + getWorkflowRunAttempt: [ + "GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}" + ], + getWorkflowRunUsage: [ + "GET /repos/{owner}/{repo}/actions/runs/{run_id}/timing" + ], + getWorkflowUsage: [ + "GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/timing" + ], + listArtifactsForRepo: ["GET /repos/{owner}/{repo}/actions/artifacts"], + listCustomImageVersionsForOrg: [ + "GET /orgs/{org}/actions/hosted-runners/images/custom/{image_definition_id}/versions" + ], + listCustomImagesForOrg: [ + "GET /orgs/{org}/actions/hosted-runners/images/custom" + ], + listEnvironmentSecrets: [ + "GET /repos/{owner}/{repo}/environments/{environment_name}/secrets" + ], + listEnvironmentVariables: [ + "GET /repos/{owner}/{repo}/environments/{environment_name}/variables" + ], + listGithubHostedRunnersInGroupForOrg: [ + "GET /orgs/{org}/actions/runner-groups/{runner_group_id}/hosted-runners" + ], + listHostedRunnersForOrg: ["GET /orgs/{org}/actions/hosted-runners"], + listJobsForWorkflowRun: [ + "GET /repos/{owner}/{repo}/actions/runs/{run_id}/jobs" + ], + listJobsForWorkflowRunAttempt: [ + "GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}/jobs" + ], + listLabelsForSelfHostedRunnerForOrg: [ + "GET /orgs/{org}/actions/runners/{runner_id}/labels" + ], + listLabelsForSelfHostedRunnerForRepo: [ + "GET /repos/{owner}/{repo}/actions/runners/{runner_id}/labels" + ], + listOrgSecrets: ["GET /orgs/{org}/actions/secrets"], + listOrgVariables: ["GET /orgs/{org}/actions/variables"], + listRepoOrganizationSecrets: [ + "GET /repos/{owner}/{repo}/actions/organization-secrets" + ], + listRepoOrganizationVariables: [ + "GET /repos/{owner}/{repo}/actions/organization-variables" + ], + listRepoSecrets: ["GET /repos/{owner}/{repo}/actions/secrets"], + listRepoVariables: ["GET /repos/{owner}/{repo}/actions/variables"], + listRepoWorkflows: ["GET /repos/{owner}/{repo}/actions/workflows"], + listRunnerApplicationsForOrg: ["GET /orgs/{org}/actions/runners/downloads"], + listRunnerApplicationsForRepo: [ + "GET /repos/{owner}/{repo}/actions/runners/downloads" + ], + listSelectedReposForOrgSecret: [ + "GET /orgs/{org}/actions/secrets/{secret_name}/repositories" + ], + listSelectedReposForOrgVariable: [ + "GET /orgs/{org}/actions/variables/{name}/repositories" + ], + listSelectedRepositoriesEnabledGithubActionsOrganization: [ + "GET /orgs/{org}/actions/permissions/repositories" + ], + listSelfHostedRunnersForOrg: ["GET /orgs/{org}/actions/runners"], + listSelfHostedRunnersForRepo: ["GET /repos/{owner}/{repo}/actions/runners"], + listWorkflowRunArtifacts: [ + "GET /repos/{owner}/{repo}/actions/runs/{run_id}/artifacts" + ], + listWorkflowRuns: [ + "GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/runs" + ], + listWorkflowRunsForRepo: ["GET /repos/{owner}/{repo}/actions/runs"], + reRunJobForWorkflowRun: [ + "POST /repos/{owner}/{repo}/actions/jobs/{job_id}/rerun" + ], + reRunWorkflow: ["POST /repos/{owner}/{repo}/actions/runs/{run_id}/rerun"], + reRunWorkflowFailedJobs: [ + "POST /repos/{owner}/{repo}/actions/runs/{run_id}/rerun-failed-jobs" + ], + removeAllCustomLabelsFromSelfHostedRunnerForOrg: [ + "DELETE /orgs/{org}/actions/runners/{runner_id}/labels" + ], + removeAllCustomLabelsFromSelfHostedRunnerForRepo: [ + "DELETE /repos/{owner}/{repo}/actions/runners/{runner_id}/labels" + ], + removeCustomLabelFromSelfHostedRunnerForOrg: [ + "DELETE /orgs/{org}/actions/runners/{runner_id}/labels/{name}" + ], + removeCustomLabelFromSelfHostedRunnerForRepo: [ + "DELETE /repos/{owner}/{repo}/actions/runners/{runner_id}/labels/{name}" + ], + removeSelectedRepoFromOrgSecret: [ + "DELETE /orgs/{org}/actions/secrets/{secret_name}/repositories/{repository_id}" + ], + removeSelectedRepoFromOrgVariable: [ + "DELETE /orgs/{org}/actions/variables/{name}/repositories/{repository_id}" + ], + reviewCustomGatesForRun: [ + "POST /repos/{owner}/{repo}/actions/runs/{run_id}/deployment_protection_rule" + ], + reviewPendingDeploymentsForRun: [ + "POST /repos/{owner}/{repo}/actions/runs/{run_id}/pending_deployments" + ], + setAllowedActionsOrganization: [ + "PUT /orgs/{org}/actions/permissions/selected-actions" + ], + setAllowedActionsRepository: [ + "PUT /repos/{owner}/{repo}/actions/permissions/selected-actions" + ], + setCustomLabelsForSelfHostedRunnerForOrg: [ + "PUT /orgs/{org}/actions/runners/{runner_id}/labels" + ], + setCustomLabelsForSelfHostedRunnerForRepo: [ + "PUT /repos/{owner}/{repo}/actions/runners/{runner_id}/labels" + ], + setCustomOidcSubClaimForRepo: [ + "PUT /repos/{owner}/{repo}/actions/oidc/customization/sub" + ], + setGithubActionsDefaultWorkflowPermissionsOrganization: [ + "PUT /orgs/{org}/actions/permissions/workflow" + ], + setGithubActionsDefaultWorkflowPermissionsRepository: [ + "PUT /repos/{owner}/{repo}/actions/permissions/workflow" + ], + setGithubActionsPermissionsOrganization: [ + "PUT /orgs/{org}/actions/permissions" + ], + setGithubActionsPermissionsRepository: [ + "PUT /repos/{owner}/{repo}/actions/permissions" + ], + setSelectedReposForOrgSecret: [ + "PUT /orgs/{org}/actions/secrets/{secret_name}/repositories" + ], + setSelectedReposForOrgVariable: [ + "PUT /orgs/{org}/actions/variables/{name}/repositories" + ], + setSelectedRepositoriesEnabledGithubActionsOrganization: [ + "PUT /orgs/{org}/actions/permissions/repositories" + ], + setWorkflowAccessToRepository: [ + "PUT /repos/{owner}/{repo}/actions/permissions/access" + ], + updateEnvironmentVariable: [ + "PATCH /repos/{owner}/{repo}/environments/{environment_name}/variables/{name}" + ], + updateHostedRunnerForOrg: [ + "PATCH /orgs/{org}/actions/hosted-runners/{hosted_runner_id}" + ], + updateOrgVariable: ["PATCH /orgs/{org}/actions/variables/{name}"], + updateRepoVariable: [ + "PATCH /repos/{owner}/{repo}/actions/variables/{name}" + ] + }, + activity: { + checkRepoIsStarredByAuthenticatedUser: ["GET /user/starred/{owner}/{repo}"], + deleteRepoSubscription: ["DELETE /repos/{owner}/{repo}/subscription"], + deleteThreadSubscription: [ + "DELETE /notifications/threads/{thread_id}/subscription" + ], + getFeeds: ["GET /feeds"], + getRepoSubscription: ["GET /repos/{owner}/{repo}/subscription"], + getThread: ["GET /notifications/threads/{thread_id}"], + getThreadSubscriptionForAuthenticatedUser: [ + "GET /notifications/threads/{thread_id}/subscription" + ], + listEventsForAuthenticatedUser: ["GET /users/{username}/events"], + listNotificationsForAuthenticatedUser: ["GET /notifications"], + listOrgEventsForAuthenticatedUser: [ + "GET /users/{username}/events/orgs/{org}" + ], + listPublicEvents: ["GET /events"], + listPublicEventsForRepoNetwork: ["GET /networks/{owner}/{repo}/events"], + listPublicEventsForUser: ["GET /users/{username}/events/public"], + listPublicOrgEvents: ["GET /orgs/{org}/events"], + listReceivedEventsForUser: ["GET /users/{username}/received_events"], + listReceivedPublicEventsForUser: [ + "GET /users/{username}/received_events/public" + ], + listRepoEvents: ["GET /repos/{owner}/{repo}/events"], + listRepoNotificationsForAuthenticatedUser: [ + "GET /repos/{owner}/{repo}/notifications" + ], + listReposStarredByAuthenticatedUser: ["GET /user/starred"], + listReposStarredByUser: ["GET /users/{username}/starred"], + listReposWatchedByUser: ["GET /users/{username}/subscriptions"], + listStargazersForRepo: ["GET /repos/{owner}/{repo}/stargazers"], + listWatchedReposForAuthenticatedUser: ["GET /user/subscriptions"], + listWatchersForRepo: ["GET /repos/{owner}/{repo}/subscribers"], + markNotificationsAsRead: ["PUT /notifications"], + markRepoNotificationsAsRead: ["PUT /repos/{owner}/{repo}/notifications"], + markThreadAsDone: ["DELETE /notifications/threads/{thread_id}"], + markThreadAsRead: ["PATCH /notifications/threads/{thread_id}"], + setRepoSubscription: ["PUT /repos/{owner}/{repo}/subscription"], + setThreadSubscription: [ + "PUT /notifications/threads/{thread_id}/subscription" + ], + starRepoForAuthenticatedUser: ["PUT /user/starred/{owner}/{repo}"], + unstarRepoForAuthenticatedUser: ["DELETE /user/starred/{owner}/{repo}"] + }, + apps: { + addRepoToInstallation: [ + "PUT /user/installations/{installation_id}/repositories/{repository_id}", + {}, + { renamed: ["apps", "addRepoToInstallationForAuthenticatedUser"] } + ], + addRepoToInstallationForAuthenticatedUser: [ + "PUT /user/installations/{installation_id}/repositories/{repository_id}" + ], + checkToken: ["POST /applications/{client_id}/token"], + createFromManifest: ["POST /app-manifests/{code}/conversions"], + createInstallationAccessToken: [ + "POST /app/installations/{installation_id}/access_tokens" + ], + deleteAuthorization: ["DELETE /applications/{client_id}/grant"], + deleteInstallation: ["DELETE /app/installations/{installation_id}"], + deleteToken: ["DELETE /applications/{client_id}/token"], + getAuthenticated: ["GET /app"], + getBySlug: ["GET /apps/{app_slug}"], + getInstallation: ["GET /app/installations/{installation_id}"], + getOrgInstallation: ["GET /orgs/{org}/installation"], + getRepoInstallation: ["GET /repos/{owner}/{repo}/installation"], + getSubscriptionPlanForAccount: [ + "GET /marketplace_listing/accounts/{account_id}" + ], + getSubscriptionPlanForAccountStubbed: [ + "GET /marketplace_listing/stubbed/accounts/{account_id}" + ], + getUserInstallation: ["GET /users/{username}/installation"], + getWebhookConfigForApp: ["GET /app/hook/config"], + getWebhookDelivery: ["GET /app/hook/deliveries/{delivery_id}"], + listAccountsForPlan: ["GET /marketplace_listing/plans/{plan_id}/accounts"], + listAccountsForPlanStubbed: [ + "GET /marketplace_listing/stubbed/plans/{plan_id}/accounts" + ], + listInstallationReposForAuthenticatedUser: [ + "GET /user/installations/{installation_id}/repositories" + ], + listInstallationRequestsForAuthenticatedApp: [ + "GET /app/installation-requests" + ], + listInstallations: ["GET /app/installations"], + listInstallationsForAuthenticatedUser: ["GET /user/installations"], + listPlans: ["GET /marketplace_listing/plans"], + listPlansStubbed: ["GET /marketplace_listing/stubbed/plans"], + listReposAccessibleToInstallation: ["GET /installation/repositories"], + listSubscriptionsForAuthenticatedUser: ["GET /user/marketplace_purchases"], + listSubscriptionsForAuthenticatedUserStubbed: [ + "GET /user/marketplace_purchases/stubbed" + ], + listWebhookDeliveries: ["GET /app/hook/deliveries"], + redeliverWebhookDelivery: [ + "POST /app/hook/deliveries/{delivery_id}/attempts" + ], + removeRepoFromInstallation: [ + "DELETE /user/installations/{installation_id}/repositories/{repository_id}", + {}, + { renamed: ["apps", "removeRepoFromInstallationForAuthenticatedUser"] } + ], + removeRepoFromInstallationForAuthenticatedUser: [ + "DELETE /user/installations/{installation_id}/repositories/{repository_id}" + ], + resetToken: ["PATCH /applications/{client_id}/token"], + revokeInstallationAccessToken: ["DELETE /installation/token"], + scopeToken: ["POST /applications/{client_id}/token/scoped"], + suspendInstallation: ["PUT /app/installations/{installation_id}/suspended"], + unsuspendInstallation: [ + "DELETE /app/installations/{installation_id}/suspended" + ], + updateWebhookConfigForApp: ["PATCH /app/hook/config"] + }, + billing: { + getGithubActionsBillingOrg: ["GET /orgs/{org}/settings/billing/actions"], + getGithubActionsBillingUser: [ + "GET /users/{username}/settings/billing/actions" + ], + getGithubBillingPremiumRequestUsageReportOrg: [ + "GET /organizations/{org}/settings/billing/premium_request/usage" + ], + getGithubBillingPremiumRequestUsageReportUser: [ + "GET /users/{username}/settings/billing/premium_request/usage" + ], + getGithubBillingUsageReportOrg: [ + "GET /organizations/{org}/settings/billing/usage" + ], + getGithubBillingUsageReportUser: [ + "GET /users/{username}/settings/billing/usage" + ], + getGithubPackagesBillingOrg: ["GET /orgs/{org}/settings/billing/packages"], + getGithubPackagesBillingUser: [ + "GET /users/{username}/settings/billing/packages" + ], + getSharedStorageBillingOrg: [ + "GET /orgs/{org}/settings/billing/shared-storage" + ], + getSharedStorageBillingUser: [ + "GET /users/{username}/settings/billing/shared-storage" + ] + }, + campaigns: { + createCampaign: ["POST /orgs/{org}/campaigns"], + deleteCampaign: ["DELETE /orgs/{org}/campaigns/{campaign_number}"], + getCampaignSummary: ["GET /orgs/{org}/campaigns/{campaign_number}"], + listOrgCampaigns: ["GET /orgs/{org}/campaigns"], + updateCampaign: ["PATCH /orgs/{org}/campaigns/{campaign_number}"] + }, + checks: { + create: ["POST /repos/{owner}/{repo}/check-runs"], + createSuite: ["POST /repos/{owner}/{repo}/check-suites"], + get: ["GET /repos/{owner}/{repo}/check-runs/{check_run_id}"], + getSuite: ["GET /repos/{owner}/{repo}/check-suites/{check_suite_id}"], + listAnnotations: [ + "GET /repos/{owner}/{repo}/check-runs/{check_run_id}/annotations" + ], + listForRef: ["GET /repos/{owner}/{repo}/commits/{ref}/check-runs"], + listForSuite: [ + "GET /repos/{owner}/{repo}/check-suites/{check_suite_id}/check-runs" + ], + listSuitesForRef: ["GET /repos/{owner}/{repo}/commits/{ref}/check-suites"], + rerequestRun: [ + "POST /repos/{owner}/{repo}/check-runs/{check_run_id}/rerequest" + ], + rerequestSuite: [ + "POST /repos/{owner}/{repo}/check-suites/{check_suite_id}/rerequest" + ], + setSuitesPreferences: [ + "PATCH /repos/{owner}/{repo}/check-suites/preferences" + ], + update: ["PATCH /repos/{owner}/{repo}/check-runs/{check_run_id}"] + }, + codeScanning: { + commitAutofix: [ + "POST /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}/autofix/commits" + ], + createAutofix: [ + "POST /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}/autofix" + ], + createVariantAnalysis: [ + "POST /repos/{owner}/{repo}/code-scanning/codeql/variant-analyses" + ], + deleteAnalysis: [ + "DELETE /repos/{owner}/{repo}/code-scanning/analyses/{analysis_id}{?confirm_delete}" + ], + deleteCodeqlDatabase: [ + "DELETE /repos/{owner}/{repo}/code-scanning/codeql/databases/{language}" + ], + getAlert: [ + "GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}", + {}, + { renamedParameters: { alert_id: "alert_number" } } + ], + getAnalysis: [ + "GET /repos/{owner}/{repo}/code-scanning/analyses/{analysis_id}" + ], + getAutofix: [ + "GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}/autofix" + ], + getCodeqlDatabase: [ + "GET /repos/{owner}/{repo}/code-scanning/codeql/databases/{language}" + ], + getDefaultSetup: ["GET /repos/{owner}/{repo}/code-scanning/default-setup"], + getSarif: ["GET /repos/{owner}/{repo}/code-scanning/sarifs/{sarif_id}"], + getVariantAnalysis: [ + "GET /repos/{owner}/{repo}/code-scanning/codeql/variant-analyses/{codeql_variant_analysis_id}" + ], + getVariantAnalysisRepoTask: [ + "GET /repos/{owner}/{repo}/code-scanning/codeql/variant-analyses/{codeql_variant_analysis_id}/repos/{repo_owner}/{repo_name}" + ], + listAlertInstances: [ + "GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}/instances" + ], + listAlertsForOrg: ["GET /orgs/{org}/code-scanning/alerts"], + listAlertsForRepo: ["GET /repos/{owner}/{repo}/code-scanning/alerts"], + listAlertsInstances: [ + "GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}/instances", + {}, + { renamed: ["codeScanning", "listAlertInstances"] } + ], + listCodeqlDatabases: [ + "GET /repos/{owner}/{repo}/code-scanning/codeql/databases" + ], + listRecentAnalyses: ["GET /repos/{owner}/{repo}/code-scanning/analyses"], + updateAlert: [ + "PATCH /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}" + ], + updateDefaultSetup: [ + "PATCH /repos/{owner}/{repo}/code-scanning/default-setup" + ], + uploadSarif: ["POST /repos/{owner}/{repo}/code-scanning/sarifs"] + }, + codeSecurity: { + attachConfiguration: [ + "POST /orgs/{org}/code-security/configurations/{configuration_id}/attach" + ], + attachEnterpriseConfiguration: [ + "POST /enterprises/{enterprise}/code-security/configurations/{configuration_id}/attach" + ], + createConfiguration: ["POST /orgs/{org}/code-security/configurations"], + createConfigurationForEnterprise: [ + "POST /enterprises/{enterprise}/code-security/configurations" + ], + deleteConfiguration: [ + "DELETE /orgs/{org}/code-security/configurations/{configuration_id}" + ], + deleteConfigurationForEnterprise: [ + "DELETE /enterprises/{enterprise}/code-security/configurations/{configuration_id}" + ], + detachConfiguration: [ + "DELETE /orgs/{org}/code-security/configurations/detach" + ], + getConfiguration: [ + "GET /orgs/{org}/code-security/configurations/{configuration_id}" + ], + getConfigurationForRepository: [ + "GET /repos/{owner}/{repo}/code-security-configuration" + ], + getConfigurationsForEnterprise: [ + "GET /enterprises/{enterprise}/code-security/configurations" + ], + getConfigurationsForOrg: ["GET /orgs/{org}/code-security/configurations"], + getDefaultConfigurations: [ + "GET /orgs/{org}/code-security/configurations/defaults" + ], + getDefaultConfigurationsForEnterprise: [ + "GET /enterprises/{enterprise}/code-security/configurations/defaults" + ], + getRepositoriesForConfiguration: [ + "GET /orgs/{org}/code-security/configurations/{configuration_id}/repositories" + ], + getRepositoriesForEnterpriseConfiguration: [ + "GET /enterprises/{enterprise}/code-security/configurations/{configuration_id}/repositories" + ], + getSingleConfigurationForEnterprise: [ + "GET /enterprises/{enterprise}/code-security/configurations/{configuration_id}" + ], + setConfigurationAsDefault: [ + "PUT /orgs/{org}/code-security/configurations/{configuration_id}/defaults" + ], + setConfigurationAsDefaultForEnterprise: [ + "PUT /enterprises/{enterprise}/code-security/configurations/{configuration_id}/defaults" + ], + updateConfiguration: [ + "PATCH /orgs/{org}/code-security/configurations/{configuration_id}" + ], + updateEnterpriseConfiguration: [ + "PATCH /enterprises/{enterprise}/code-security/configurations/{configuration_id}" + ] + }, + codesOfConduct: { + getAllCodesOfConduct: ["GET /codes_of_conduct"], + getConductCode: ["GET /codes_of_conduct/{key}"] + }, + codespaces: { + addRepositoryForSecretForAuthenticatedUser: [ + "PUT /user/codespaces/secrets/{secret_name}/repositories/{repository_id}" + ], + addSelectedRepoToOrgSecret: [ + "PUT /orgs/{org}/codespaces/secrets/{secret_name}/repositories/{repository_id}" + ], + checkPermissionsForDevcontainer: [ + "GET /repos/{owner}/{repo}/codespaces/permissions_check" + ], + codespaceMachinesForAuthenticatedUser: [ + "GET /user/codespaces/{codespace_name}/machines" + ], + createForAuthenticatedUser: ["POST /user/codespaces"], + createOrUpdateOrgSecret: [ + "PUT /orgs/{org}/codespaces/secrets/{secret_name}" + ], + createOrUpdateRepoSecret: [ + "PUT /repos/{owner}/{repo}/codespaces/secrets/{secret_name}" + ], + createOrUpdateSecretForAuthenticatedUser: [ + "PUT /user/codespaces/secrets/{secret_name}" + ], + createWithPrForAuthenticatedUser: [ + "POST /repos/{owner}/{repo}/pulls/{pull_number}/codespaces" + ], + createWithRepoForAuthenticatedUser: [ + "POST /repos/{owner}/{repo}/codespaces" + ], + deleteForAuthenticatedUser: ["DELETE /user/codespaces/{codespace_name}"], + deleteFromOrganization: [ + "DELETE /orgs/{org}/members/{username}/codespaces/{codespace_name}" + ], + deleteOrgSecret: ["DELETE /orgs/{org}/codespaces/secrets/{secret_name}"], + deleteRepoSecret: [ + "DELETE /repos/{owner}/{repo}/codespaces/secrets/{secret_name}" + ], + deleteSecretForAuthenticatedUser: [ + "DELETE /user/codespaces/secrets/{secret_name}" + ], + exportForAuthenticatedUser: [ + "POST /user/codespaces/{codespace_name}/exports" + ], + getCodespacesForUserInOrg: [ + "GET /orgs/{org}/members/{username}/codespaces" + ], + getExportDetailsForAuthenticatedUser: [ + "GET /user/codespaces/{codespace_name}/exports/{export_id}" + ], + getForAuthenticatedUser: ["GET /user/codespaces/{codespace_name}"], + getOrgPublicKey: ["GET /orgs/{org}/codespaces/secrets/public-key"], + getOrgSecret: ["GET /orgs/{org}/codespaces/secrets/{secret_name}"], + getPublicKeyForAuthenticatedUser: [ + "GET /user/codespaces/secrets/public-key" + ], + getRepoPublicKey: [ + "GET /repos/{owner}/{repo}/codespaces/secrets/public-key" + ], + getRepoSecret: [ + "GET /repos/{owner}/{repo}/codespaces/secrets/{secret_name}" + ], + getSecretForAuthenticatedUser: [ + "GET /user/codespaces/secrets/{secret_name}" + ], + listDevcontainersInRepositoryForAuthenticatedUser: [ + "GET /repos/{owner}/{repo}/codespaces/devcontainers" + ], + listForAuthenticatedUser: ["GET /user/codespaces"], + listInOrganization: [ + "GET /orgs/{org}/codespaces", + {}, + { renamedParameters: { org_id: "org" } } + ], + listInRepositoryForAuthenticatedUser: [ + "GET /repos/{owner}/{repo}/codespaces" + ], + listOrgSecrets: ["GET /orgs/{org}/codespaces/secrets"], + listRepoSecrets: ["GET /repos/{owner}/{repo}/codespaces/secrets"], + listRepositoriesForSecretForAuthenticatedUser: [ + "GET /user/codespaces/secrets/{secret_name}/repositories" + ], + listSecretsForAuthenticatedUser: ["GET /user/codespaces/secrets"], + listSelectedReposForOrgSecret: [ + "GET /orgs/{org}/codespaces/secrets/{secret_name}/repositories" + ], + preFlightWithRepoForAuthenticatedUser: [ + "GET /repos/{owner}/{repo}/codespaces/new" + ], + publishForAuthenticatedUser: [ + "POST /user/codespaces/{codespace_name}/publish" + ], + removeRepositoryForSecretForAuthenticatedUser: [ + "DELETE /user/codespaces/secrets/{secret_name}/repositories/{repository_id}" + ], + removeSelectedRepoFromOrgSecret: [ + "DELETE /orgs/{org}/codespaces/secrets/{secret_name}/repositories/{repository_id}" + ], + repoMachinesForAuthenticatedUser: [ + "GET /repos/{owner}/{repo}/codespaces/machines" + ], + setRepositoriesForSecretForAuthenticatedUser: [ + "PUT /user/codespaces/secrets/{secret_name}/repositories" + ], + setSelectedReposForOrgSecret: [ + "PUT /orgs/{org}/codespaces/secrets/{secret_name}/repositories" + ], + startForAuthenticatedUser: ["POST /user/codespaces/{codespace_name}/start"], + stopForAuthenticatedUser: ["POST /user/codespaces/{codespace_name}/stop"], + stopInOrganization: [ + "POST /orgs/{org}/members/{username}/codespaces/{codespace_name}/stop" + ], + updateForAuthenticatedUser: ["PATCH /user/codespaces/{codespace_name}"] + }, + copilot: { + addCopilotSeatsForTeams: [ + "POST /orgs/{org}/copilot/billing/selected_teams" + ], + addCopilotSeatsForUsers: [ + "POST /orgs/{org}/copilot/billing/selected_users" + ], + cancelCopilotSeatAssignmentForTeams: [ + "DELETE /orgs/{org}/copilot/billing/selected_teams" + ], + cancelCopilotSeatAssignmentForUsers: [ + "DELETE /orgs/{org}/copilot/billing/selected_users" + ], + copilotMetricsForOrganization: ["GET /orgs/{org}/copilot/metrics"], + copilotMetricsForTeam: ["GET /orgs/{org}/team/{team_slug}/copilot/metrics"], + getCopilotOrganizationDetails: ["GET /orgs/{org}/copilot/billing"], + getCopilotSeatDetailsForUser: [ + "GET /orgs/{org}/members/{username}/copilot" + ], + listCopilotSeats: ["GET /orgs/{org}/copilot/billing/seats"] + }, + credentials: { revoke: ["POST /credentials/revoke"] }, + dependabot: { + addSelectedRepoToOrgSecret: [ + "PUT /orgs/{org}/dependabot/secrets/{secret_name}/repositories/{repository_id}" + ], + createOrUpdateOrgSecret: [ + "PUT /orgs/{org}/dependabot/secrets/{secret_name}" + ], + createOrUpdateRepoSecret: [ + "PUT /repos/{owner}/{repo}/dependabot/secrets/{secret_name}" + ], + deleteOrgSecret: ["DELETE /orgs/{org}/dependabot/secrets/{secret_name}"], + deleteRepoSecret: [ + "DELETE /repos/{owner}/{repo}/dependabot/secrets/{secret_name}" + ], + getAlert: ["GET /repos/{owner}/{repo}/dependabot/alerts/{alert_number}"], + getOrgPublicKey: ["GET /orgs/{org}/dependabot/secrets/public-key"], + getOrgSecret: ["GET /orgs/{org}/dependabot/secrets/{secret_name}"], + getRepoPublicKey: [ + "GET /repos/{owner}/{repo}/dependabot/secrets/public-key" + ], + getRepoSecret: [ + "GET /repos/{owner}/{repo}/dependabot/secrets/{secret_name}" + ], + listAlertsForEnterprise: [ + "GET /enterprises/{enterprise}/dependabot/alerts" + ], + listAlertsForOrg: ["GET /orgs/{org}/dependabot/alerts"], + listAlertsForRepo: ["GET /repos/{owner}/{repo}/dependabot/alerts"], + listOrgSecrets: ["GET /orgs/{org}/dependabot/secrets"], + listRepoSecrets: ["GET /repos/{owner}/{repo}/dependabot/secrets"], + listSelectedReposForOrgSecret: [ + "GET /orgs/{org}/dependabot/secrets/{secret_name}/repositories" + ], + removeSelectedRepoFromOrgSecret: [ + "DELETE /orgs/{org}/dependabot/secrets/{secret_name}/repositories/{repository_id}" + ], + repositoryAccessForOrg: [ + "GET /organizations/{org}/dependabot/repository-access" + ], + setRepositoryAccessDefaultLevel: [ + "PUT /organizations/{org}/dependabot/repository-access/default-level" + ], + setSelectedReposForOrgSecret: [ + "PUT /orgs/{org}/dependabot/secrets/{secret_name}/repositories" + ], + updateAlert: [ + "PATCH /repos/{owner}/{repo}/dependabot/alerts/{alert_number}" + ], + updateRepositoryAccessForOrg: [ + "PATCH /organizations/{org}/dependabot/repository-access" + ] + }, + dependencyGraph: { + createRepositorySnapshot: [ + "POST /repos/{owner}/{repo}/dependency-graph/snapshots" + ], + diffRange: [ + "GET /repos/{owner}/{repo}/dependency-graph/compare/{basehead}" + ], + exportSbom: ["GET /repos/{owner}/{repo}/dependency-graph/sbom"] + }, + emojis: { get: ["GET /emojis"] }, + enterpriseTeamMemberships: { + add: [ + "PUT /enterprises/{enterprise}/teams/{enterprise-team}/memberships/{username}" + ], + bulkAdd: [ + "POST /enterprises/{enterprise}/teams/{enterprise-team}/memberships/add" + ], + bulkRemove: [ + "POST /enterprises/{enterprise}/teams/{enterprise-team}/memberships/remove" + ], + get: [ + "GET /enterprises/{enterprise}/teams/{enterprise-team}/memberships/{username}" + ], + list: ["GET /enterprises/{enterprise}/teams/{enterprise-team}/memberships"], + remove: [ + "DELETE /enterprises/{enterprise}/teams/{enterprise-team}/memberships/{username}" + ] + }, + enterpriseTeamOrganizations: { + add: [ + "PUT /enterprises/{enterprise}/teams/{enterprise-team}/organizations/{org}" + ], + bulkAdd: [ + "POST /enterprises/{enterprise}/teams/{enterprise-team}/organizations/add" + ], + bulkRemove: [ + "POST /enterprises/{enterprise}/teams/{enterprise-team}/organizations/remove" + ], + delete: [ + "DELETE /enterprises/{enterprise}/teams/{enterprise-team}/organizations/{org}" + ], + getAssignment: [ + "GET /enterprises/{enterprise}/teams/{enterprise-team}/organizations/{org}" + ], + getAssignments: [ + "GET /enterprises/{enterprise}/teams/{enterprise-team}/organizations" + ] + }, + enterpriseTeams: { + create: ["POST /enterprises/{enterprise}/teams"], + delete: ["DELETE /enterprises/{enterprise}/teams/{team_slug}"], + get: ["GET /enterprises/{enterprise}/teams/{team_slug}"], + list: ["GET /enterprises/{enterprise}/teams"], + update: ["PATCH /enterprises/{enterprise}/teams/{team_slug}"] + }, + gists: { + checkIsStarred: ["GET /gists/{gist_id}/star"], + create: ["POST /gists"], + createComment: ["POST /gists/{gist_id}/comments"], + delete: ["DELETE /gists/{gist_id}"], + deleteComment: ["DELETE /gists/{gist_id}/comments/{comment_id}"], + fork: ["POST /gists/{gist_id}/forks"], + get: ["GET /gists/{gist_id}"], + getComment: ["GET /gists/{gist_id}/comments/{comment_id}"], + getRevision: ["GET /gists/{gist_id}/{sha}"], + list: ["GET /gists"], + listComments: ["GET /gists/{gist_id}/comments"], + listCommits: ["GET /gists/{gist_id}/commits"], + listForUser: ["GET /users/{username}/gists"], + listForks: ["GET /gists/{gist_id}/forks"], + listPublic: ["GET /gists/public"], + listStarred: ["GET /gists/starred"], + star: ["PUT /gists/{gist_id}/star"], + unstar: ["DELETE /gists/{gist_id}/star"], + update: ["PATCH /gists/{gist_id}"], + updateComment: ["PATCH /gists/{gist_id}/comments/{comment_id}"] + }, + git: { + createBlob: ["POST /repos/{owner}/{repo}/git/blobs"], + createCommit: ["POST /repos/{owner}/{repo}/git/commits"], + createRef: ["POST /repos/{owner}/{repo}/git/refs"], + createTag: ["POST /repos/{owner}/{repo}/git/tags"], + createTree: ["POST /repos/{owner}/{repo}/git/trees"], + deleteRef: ["DELETE /repos/{owner}/{repo}/git/refs/{ref}"], + getBlob: ["GET /repos/{owner}/{repo}/git/blobs/{file_sha}"], + getCommit: ["GET /repos/{owner}/{repo}/git/commits/{commit_sha}"], + getRef: ["GET /repos/{owner}/{repo}/git/ref/{ref}"], + getTag: ["GET /repos/{owner}/{repo}/git/tags/{tag_sha}"], + getTree: ["GET /repos/{owner}/{repo}/git/trees/{tree_sha}"], + listMatchingRefs: ["GET /repos/{owner}/{repo}/git/matching-refs/{ref}"], + updateRef: ["PATCH /repos/{owner}/{repo}/git/refs/{ref}"] + }, + gitignore: { + getAllTemplates: ["GET /gitignore/templates"], + getTemplate: ["GET /gitignore/templates/{name}"] + }, + hostedCompute: { + createNetworkConfigurationForOrg: [ + "POST /orgs/{org}/settings/network-configurations" + ], + deleteNetworkConfigurationFromOrg: [ + "DELETE /orgs/{org}/settings/network-configurations/{network_configuration_id}" + ], + getNetworkConfigurationForOrg: [ + "GET /orgs/{org}/settings/network-configurations/{network_configuration_id}" + ], + getNetworkSettingsForOrg: [ + "GET /orgs/{org}/settings/network-settings/{network_settings_id}" + ], + listNetworkConfigurationsForOrg: [ + "GET /orgs/{org}/settings/network-configurations" + ], + updateNetworkConfigurationForOrg: [ + "PATCH /orgs/{org}/settings/network-configurations/{network_configuration_id}" + ] + }, + interactions: { + getRestrictionsForAuthenticatedUser: ["GET /user/interaction-limits"], + getRestrictionsForOrg: ["GET /orgs/{org}/interaction-limits"], + getRestrictionsForRepo: ["GET /repos/{owner}/{repo}/interaction-limits"], + getRestrictionsForYourPublicRepos: [ + "GET /user/interaction-limits", + {}, + { renamed: ["interactions", "getRestrictionsForAuthenticatedUser"] } + ], + removeRestrictionsForAuthenticatedUser: ["DELETE /user/interaction-limits"], + removeRestrictionsForOrg: ["DELETE /orgs/{org}/interaction-limits"], + removeRestrictionsForRepo: [ + "DELETE /repos/{owner}/{repo}/interaction-limits" + ], + removeRestrictionsForYourPublicRepos: [ + "DELETE /user/interaction-limits", + {}, + { renamed: ["interactions", "removeRestrictionsForAuthenticatedUser"] } + ], + setRestrictionsForAuthenticatedUser: ["PUT /user/interaction-limits"], + setRestrictionsForOrg: ["PUT /orgs/{org}/interaction-limits"], + setRestrictionsForRepo: ["PUT /repos/{owner}/{repo}/interaction-limits"], + setRestrictionsForYourPublicRepos: [ + "PUT /user/interaction-limits", + {}, + { renamed: ["interactions", "setRestrictionsForAuthenticatedUser"] } + ] + }, + issues: { + addAssignees: [ + "POST /repos/{owner}/{repo}/issues/{issue_number}/assignees" + ], + addBlockedByDependency: [ + "POST /repos/{owner}/{repo}/issues/{issue_number}/dependencies/blocked_by" + ], + addLabels: ["POST /repos/{owner}/{repo}/issues/{issue_number}/labels"], + addSubIssue: [ + "POST /repos/{owner}/{repo}/issues/{issue_number}/sub_issues" + ], + checkUserCanBeAssigned: ["GET /repos/{owner}/{repo}/assignees/{assignee}"], + checkUserCanBeAssignedToIssue: [ + "GET /repos/{owner}/{repo}/issues/{issue_number}/assignees/{assignee}" + ], + create: ["POST /repos/{owner}/{repo}/issues"], + createComment: [ + "POST /repos/{owner}/{repo}/issues/{issue_number}/comments" + ], + createLabel: ["POST /repos/{owner}/{repo}/labels"], + createMilestone: ["POST /repos/{owner}/{repo}/milestones"], + deleteComment: [ + "DELETE /repos/{owner}/{repo}/issues/comments/{comment_id}" + ], + deleteLabel: ["DELETE /repos/{owner}/{repo}/labels/{name}"], + deleteMilestone: [ + "DELETE /repos/{owner}/{repo}/milestones/{milestone_number}" + ], + get: ["GET /repos/{owner}/{repo}/issues/{issue_number}"], + getComment: ["GET /repos/{owner}/{repo}/issues/comments/{comment_id}"], + getEvent: ["GET /repos/{owner}/{repo}/issues/events/{event_id}"], + getLabel: ["GET /repos/{owner}/{repo}/labels/{name}"], + getMilestone: ["GET /repos/{owner}/{repo}/milestones/{milestone_number}"], + getParent: ["GET /repos/{owner}/{repo}/issues/{issue_number}/parent"], + list: ["GET /issues"], + listAssignees: ["GET /repos/{owner}/{repo}/assignees"], + listComments: ["GET /repos/{owner}/{repo}/issues/{issue_number}/comments"], + listCommentsForRepo: ["GET /repos/{owner}/{repo}/issues/comments"], + listDependenciesBlockedBy: [ + "GET /repos/{owner}/{repo}/issues/{issue_number}/dependencies/blocked_by" + ], + listDependenciesBlocking: [ + "GET /repos/{owner}/{repo}/issues/{issue_number}/dependencies/blocking" + ], + listEvents: ["GET /repos/{owner}/{repo}/issues/{issue_number}/events"], + listEventsForRepo: ["GET /repos/{owner}/{repo}/issues/events"], + listEventsForTimeline: [ + "GET /repos/{owner}/{repo}/issues/{issue_number}/timeline" + ], + listForAuthenticatedUser: ["GET /user/issues"], + listForOrg: ["GET /orgs/{org}/issues"], + listForRepo: ["GET /repos/{owner}/{repo}/issues"], + listLabelsForMilestone: [ + "GET /repos/{owner}/{repo}/milestones/{milestone_number}/labels" + ], + listLabelsForRepo: ["GET /repos/{owner}/{repo}/labels"], + listLabelsOnIssue: [ + "GET /repos/{owner}/{repo}/issues/{issue_number}/labels" + ], + listMilestones: ["GET /repos/{owner}/{repo}/milestones"], + listSubIssues: [ + "GET /repos/{owner}/{repo}/issues/{issue_number}/sub_issues" + ], + lock: ["PUT /repos/{owner}/{repo}/issues/{issue_number}/lock"], + removeAllLabels: [ + "DELETE /repos/{owner}/{repo}/issues/{issue_number}/labels" + ], + removeAssignees: [ + "DELETE /repos/{owner}/{repo}/issues/{issue_number}/assignees" + ], + removeDependencyBlockedBy: [ + "DELETE /repos/{owner}/{repo}/issues/{issue_number}/dependencies/blocked_by/{issue_id}" + ], + removeLabel: [ + "DELETE /repos/{owner}/{repo}/issues/{issue_number}/labels/{name}" + ], + removeSubIssue: [ + "DELETE /repos/{owner}/{repo}/issues/{issue_number}/sub_issue" + ], + reprioritizeSubIssue: [ + "PATCH /repos/{owner}/{repo}/issues/{issue_number}/sub_issues/priority" + ], + setLabels: ["PUT /repos/{owner}/{repo}/issues/{issue_number}/labels"], + unlock: ["DELETE /repos/{owner}/{repo}/issues/{issue_number}/lock"], + update: ["PATCH /repos/{owner}/{repo}/issues/{issue_number}"], + updateComment: ["PATCH /repos/{owner}/{repo}/issues/comments/{comment_id}"], + updateLabel: ["PATCH /repos/{owner}/{repo}/labels/{name}"], + updateMilestone: [ + "PATCH /repos/{owner}/{repo}/milestones/{milestone_number}" + ] + }, + licenses: { + get: ["GET /licenses/{license}"], + getAllCommonlyUsed: ["GET /licenses"], + getForRepo: ["GET /repos/{owner}/{repo}/license"] + }, + markdown: { + render: ["POST /markdown"], + renderRaw: [ + "POST /markdown/raw", + { headers: { "content-type": "text/plain; charset=utf-8" } } + ] + }, + meta: { + get: ["GET /meta"], + getAllVersions: ["GET /versions"], + getOctocat: ["GET /octocat"], + getZen: ["GET /zen"], + root: ["GET /"] + }, + migrations: { + deleteArchiveForAuthenticatedUser: [ + "DELETE /user/migrations/{migration_id}/archive" + ], + deleteArchiveForOrg: [ + "DELETE /orgs/{org}/migrations/{migration_id}/archive" + ], + downloadArchiveForOrg: [ + "GET /orgs/{org}/migrations/{migration_id}/archive" + ], + getArchiveForAuthenticatedUser: [ + "GET /user/migrations/{migration_id}/archive" + ], + getStatusForAuthenticatedUser: ["GET /user/migrations/{migration_id}"], + getStatusForOrg: ["GET /orgs/{org}/migrations/{migration_id}"], + listForAuthenticatedUser: ["GET /user/migrations"], + listForOrg: ["GET /orgs/{org}/migrations"], + listReposForAuthenticatedUser: [ + "GET /user/migrations/{migration_id}/repositories" + ], + listReposForOrg: ["GET /orgs/{org}/migrations/{migration_id}/repositories"], + listReposForUser: [ + "GET /user/migrations/{migration_id}/repositories", + {}, + { renamed: ["migrations", "listReposForAuthenticatedUser"] } + ], + startForAuthenticatedUser: ["POST /user/migrations"], + startForOrg: ["POST /orgs/{org}/migrations"], + unlockRepoForAuthenticatedUser: [ + "DELETE /user/migrations/{migration_id}/repos/{repo_name}/lock" + ], + unlockRepoForOrg: [ + "DELETE /orgs/{org}/migrations/{migration_id}/repos/{repo_name}/lock" + ] + }, + oidc: { + getOidcCustomSubTemplateForOrg: [ + "GET /orgs/{org}/actions/oidc/customization/sub" + ], + updateOidcCustomSubTemplateForOrg: [ + "PUT /orgs/{org}/actions/oidc/customization/sub" + ] + }, + orgs: { + addSecurityManagerTeam: [ + "PUT /orgs/{org}/security-managers/teams/{team_slug}", + {}, + { + deprecated: "octokit.rest.orgs.addSecurityManagerTeam() is deprecated, see https://docs.github.com/rest/orgs/security-managers#add-a-security-manager-team" + } + ], + assignTeamToOrgRole: [ + "PUT /orgs/{org}/organization-roles/teams/{team_slug}/{role_id}" + ], + assignUserToOrgRole: [ + "PUT /orgs/{org}/organization-roles/users/{username}/{role_id}" + ], + blockUser: ["PUT /orgs/{org}/blocks/{username}"], + cancelInvitation: ["DELETE /orgs/{org}/invitations/{invitation_id}"], + checkBlockedUser: ["GET /orgs/{org}/blocks/{username}"], + checkMembershipForUser: ["GET /orgs/{org}/members/{username}"], + checkPublicMembershipForUser: ["GET /orgs/{org}/public_members/{username}"], + convertMemberToOutsideCollaborator: [ + "PUT /orgs/{org}/outside_collaborators/{username}" + ], + createArtifactStorageRecord: [ + "POST /orgs/{org}/artifacts/metadata/storage-record" + ], + createInvitation: ["POST /orgs/{org}/invitations"], + createIssueType: ["POST /orgs/{org}/issue-types"], + createWebhook: ["POST /orgs/{org}/hooks"], + customPropertiesForOrgsCreateOrUpdateOrganizationValues: [ + "PATCH /organizations/{org}/org-properties/values" + ], + customPropertiesForOrgsGetOrganizationValues: [ + "GET /organizations/{org}/org-properties/values" + ], + customPropertiesForReposCreateOrUpdateOrganizationDefinition: [ + "PUT /orgs/{org}/properties/schema/{custom_property_name}" + ], + customPropertiesForReposCreateOrUpdateOrganizationDefinitions: [ + "PATCH /orgs/{org}/properties/schema" + ], + customPropertiesForReposCreateOrUpdateOrganizationValues: [ + "PATCH /orgs/{org}/properties/values" + ], + customPropertiesForReposDeleteOrganizationDefinition: [ + "DELETE /orgs/{org}/properties/schema/{custom_property_name}" + ], + customPropertiesForReposGetOrganizationDefinition: [ + "GET /orgs/{org}/properties/schema/{custom_property_name}" + ], + customPropertiesForReposGetOrganizationDefinitions: [ + "GET /orgs/{org}/properties/schema" + ], + customPropertiesForReposGetOrganizationValues: [ + "GET /orgs/{org}/properties/values" + ], + delete: ["DELETE /orgs/{org}"], + deleteAttestationsBulk: ["POST /orgs/{org}/attestations/delete-request"], + deleteAttestationsById: [ + "DELETE /orgs/{org}/attestations/{attestation_id}" + ], + deleteAttestationsBySubjectDigest: [ + "DELETE /orgs/{org}/attestations/digest/{subject_digest}" + ], + deleteIssueType: ["DELETE /orgs/{org}/issue-types/{issue_type_id}"], + deleteWebhook: ["DELETE /orgs/{org}/hooks/{hook_id}"], + disableSelectedRepositoryImmutableReleasesOrganization: [ + "DELETE /orgs/{org}/settings/immutable-releases/repositories/{repository_id}" + ], + enableSelectedRepositoryImmutableReleasesOrganization: [ + "PUT /orgs/{org}/settings/immutable-releases/repositories/{repository_id}" + ], + get: ["GET /orgs/{org}"], + getImmutableReleasesSettings: [ + "GET /orgs/{org}/settings/immutable-releases" + ], + getImmutableReleasesSettingsRepositories: [ + "GET /orgs/{org}/settings/immutable-releases/repositories" + ], + getMembershipForAuthenticatedUser: ["GET /user/memberships/orgs/{org}"], + getMembershipForUser: ["GET /orgs/{org}/memberships/{username}"], + getOrgRole: ["GET /orgs/{org}/organization-roles/{role_id}"], + getOrgRulesetHistory: ["GET /orgs/{org}/rulesets/{ruleset_id}/history"], + getOrgRulesetVersion: [ + "GET /orgs/{org}/rulesets/{ruleset_id}/history/{version_id}" + ], + getWebhook: ["GET /orgs/{org}/hooks/{hook_id}"], + getWebhookConfigForOrg: ["GET /orgs/{org}/hooks/{hook_id}/config"], + getWebhookDelivery: [ + "GET /orgs/{org}/hooks/{hook_id}/deliveries/{delivery_id}" + ], + list: ["GET /organizations"], + listAppInstallations: ["GET /orgs/{org}/installations"], + listArtifactStorageRecords: [ + "GET /orgs/{org}/artifacts/{subject_digest}/metadata/storage-records" + ], + listAttestationRepositories: ["GET /orgs/{org}/attestations/repositories"], + listAttestations: ["GET /orgs/{org}/attestations/{subject_digest}"], + listAttestationsBulk: [ + "POST /orgs/{org}/attestations/bulk-list{?per_page,before,after}" + ], + listBlockedUsers: ["GET /orgs/{org}/blocks"], + listFailedInvitations: ["GET /orgs/{org}/failed_invitations"], + listForAuthenticatedUser: ["GET /user/orgs"], + listForUser: ["GET /users/{username}/orgs"], + listInvitationTeams: ["GET /orgs/{org}/invitations/{invitation_id}/teams"], + listIssueTypes: ["GET /orgs/{org}/issue-types"], + listMembers: ["GET /orgs/{org}/members"], + listMembershipsForAuthenticatedUser: ["GET /user/memberships/orgs"], + listOrgRoleTeams: ["GET /orgs/{org}/organization-roles/{role_id}/teams"], + listOrgRoleUsers: ["GET /orgs/{org}/organization-roles/{role_id}/users"], + listOrgRoles: ["GET /orgs/{org}/organization-roles"], + listOrganizationFineGrainedPermissions: [ + "GET /orgs/{org}/organization-fine-grained-permissions" + ], + listOutsideCollaborators: ["GET /orgs/{org}/outside_collaborators"], + listPatGrantRepositories: [ + "GET /orgs/{org}/personal-access-tokens/{pat_id}/repositories" + ], + listPatGrantRequestRepositories: [ + "GET /orgs/{org}/personal-access-token-requests/{pat_request_id}/repositories" + ], + listPatGrantRequests: ["GET /orgs/{org}/personal-access-token-requests"], + listPatGrants: ["GET /orgs/{org}/personal-access-tokens"], + listPendingInvitations: ["GET /orgs/{org}/invitations"], + listPublicMembers: ["GET /orgs/{org}/public_members"], + listSecurityManagerTeams: [ + "GET /orgs/{org}/security-managers", + {}, + { + deprecated: "octokit.rest.orgs.listSecurityManagerTeams() is deprecated, see https://docs.github.com/rest/orgs/security-managers#list-security-manager-teams" + } + ], + listWebhookDeliveries: ["GET /orgs/{org}/hooks/{hook_id}/deliveries"], + listWebhooks: ["GET /orgs/{org}/hooks"], + pingWebhook: ["POST /orgs/{org}/hooks/{hook_id}/pings"], + redeliverWebhookDelivery: [ + "POST /orgs/{org}/hooks/{hook_id}/deliveries/{delivery_id}/attempts" + ], + removeMember: ["DELETE /orgs/{org}/members/{username}"], + removeMembershipForUser: ["DELETE /orgs/{org}/memberships/{username}"], + removeOutsideCollaborator: [ + "DELETE /orgs/{org}/outside_collaborators/{username}" + ], + removePublicMembershipForAuthenticatedUser: [ + "DELETE /orgs/{org}/public_members/{username}" + ], + removeSecurityManagerTeam: [ + "DELETE /orgs/{org}/security-managers/teams/{team_slug}", + {}, + { + deprecated: "octokit.rest.orgs.removeSecurityManagerTeam() is deprecated, see https://docs.github.com/rest/orgs/security-managers#remove-a-security-manager-team" + } + ], + reviewPatGrantRequest: [ + "POST /orgs/{org}/personal-access-token-requests/{pat_request_id}" + ], + reviewPatGrantRequestsInBulk: [ + "POST /orgs/{org}/personal-access-token-requests" + ], + revokeAllOrgRolesTeam: [ + "DELETE /orgs/{org}/organization-roles/teams/{team_slug}" + ], + revokeAllOrgRolesUser: [ + "DELETE /orgs/{org}/organization-roles/users/{username}" + ], + revokeOrgRoleTeam: [ + "DELETE /orgs/{org}/organization-roles/teams/{team_slug}/{role_id}" + ], + revokeOrgRoleUser: [ + "DELETE /orgs/{org}/organization-roles/users/{username}/{role_id}" + ], + setImmutableReleasesSettings: [ + "PUT /orgs/{org}/settings/immutable-releases" + ], + setImmutableReleasesSettingsRepositories: [ + "PUT /orgs/{org}/settings/immutable-releases/repositories" + ], + setMembershipForUser: ["PUT /orgs/{org}/memberships/{username}"], + setPublicMembershipForAuthenticatedUser: [ + "PUT /orgs/{org}/public_members/{username}" + ], + unblockUser: ["DELETE /orgs/{org}/blocks/{username}"], + update: ["PATCH /orgs/{org}"], + updateIssueType: ["PUT /orgs/{org}/issue-types/{issue_type_id}"], + updateMembershipForAuthenticatedUser: [ + "PATCH /user/memberships/orgs/{org}" + ], + updatePatAccess: ["POST /orgs/{org}/personal-access-tokens/{pat_id}"], + updatePatAccesses: ["POST /orgs/{org}/personal-access-tokens"], + updateWebhook: ["PATCH /orgs/{org}/hooks/{hook_id}"], + updateWebhookConfigForOrg: ["PATCH /orgs/{org}/hooks/{hook_id}/config"] + }, + packages: { + deletePackageForAuthenticatedUser: [ + "DELETE /user/packages/{package_type}/{package_name}" + ], + deletePackageForOrg: [ + "DELETE /orgs/{org}/packages/{package_type}/{package_name}" + ], + deletePackageForUser: [ + "DELETE /users/{username}/packages/{package_type}/{package_name}" + ], + deletePackageVersionForAuthenticatedUser: [ + "DELETE /user/packages/{package_type}/{package_name}/versions/{package_version_id}" + ], + deletePackageVersionForOrg: [ + "DELETE /orgs/{org}/packages/{package_type}/{package_name}/versions/{package_version_id}" + ], + deletePackageVersionForUser: [ + "DELETE /users/{username}/packages/{package_type}/{package_name}/versions/{package_version_id}" + ], + getAllPackageVersionsForAPackageOwnedByAnOrg: [ + "GET /orgs/{org}/packages/{package_type}/{package_name}/versions", + {}, + { renamed: ["packages", "getAllPackageVersionsForPackageOwnedByOrg"] } + ], + getAllPackageVersionsForAPackageOwnedByTheAuthenticatedUser: [ + "GET /user/packages/{package_type}/{package_name}/versions", + {}, + { + renamed: [ + "packages", + "getAllPackageVersionsForPackageOwnedByAuthenticatedUser" + ] + } + ], + getAllPackageVersionsForPackageOwnedByAuthenticatedUser: [ + "GET /user/packages/{package_type}/{package_name}/versions" + ], + getAllPackageVersionsForPackageOwnedByOrg: [ + "GET /orgs/{org}/packages/{package_type}/{package_name}/versions" + ], + getAllPackageVersionsForPackageOwnedByUser: [ + "GET /users/{username}/packages/{package_type}/{package_name}/versions" + ], + getPackageForAuthenticatedUser: [ + "GET /user/packages/{package_type}/{package_name}" + ], + getPackageForOrganization: [ + "GET /orgs/{org}/packages/{package_type}/{package_name}" + ], + getPackageForUser: [ + "GET /users/{username}/packages/{package_type}/{package_name}" + ], + getPackageVersionForAuthenticatedUser: [ + "GET /user/packages/{package_type}/{package_name}/versions/{package_version_id}" + ], + getPackageVersionForOrganization: [ + "GET /orgs/{org}/packages/{package_type}/{package_name}/versions/{package_version_id}" + ], + getPackageVersionForUser: [ + "GET /users/{username}/packages/{package_type}/{package_name}/versions/{package_version_id}" + ], + listDockerMigrationConflictingPackagesForAuthenticatedUser: [ + "GET /user/docker/conflicts" + ], + listDockerMigrationConflictingPackagesForOrganization: [ + "GET /orgs/{org}/docker/conflicts" + ], + listDockerMigrationConflictingPackagesForUser: [ + "GET /users/{username}/docker/conflicts" + ], + listPackagesForAuthenticatedUser: ["GET /user/packages"], + listPackagesForOrganization: ["GET /orgs/{org}/packages"], + listPackagesForUser: ["GET /users/{username}/packages"], + restorePackageForAuthenticatedUser: [ + "POST /user/packages/{package_type}/{package_name}/restore{?token}" + ], + restorePackageForOrg: [ + "POST /orgs/{org}/packages/{package_type}/{package_name}/restore{?token}" + ], + restorePackageForUser: [ + "POST /users/{username}/packages/{package_type}/{package_name}/restore{?token}" + ], + restorePackageVersionForAuthenticatedUser: [ + "POST /user/packages/{package_type}/{package_name}/versions/{package_version_id}/restore" + ], + restorePackageVersionForOrg: [ + "POST /orgs/{org}/packages/{package_type}/{package_name}/versions/{package_version_id}/restore" + ], + restorePackageVersionForUser: [ + "POST /users/{username}/packages/{package_type}/{package_name}/versions/{package_version_id}/restore" + ] + }, + privateRegistries: { + createOrgPrivateRegistry: ["POST /orgs/{org}/private-registries"], + deleteOrgPrivateRegistry: [ + "DELETE /orgs/{org}/private-registries/{secret_name}" + ], + getOrgPrivateRegistry: ["GET /orgs/{org}/private-registries/{secret_name}"], + getOrgPublicKey: ["GET /orgs/{org}/private-registries/public-key"], + listOrgPrivateRegistries: ["GET /orgs/{org}/private-registries"], + updateOrgPrivateRegistry: [ + "PATCH /orgs/{org}/private-registries/{secret_name}" + ] + }, + projects: { + addItemForOrg: ["POST /orgs/{org}/projectsV2/{project_number}/items"], + addItemForUser: [ + "POST /users/{username}/projectsV2/{project_number}/items" + ], + deleteItemForOrg: [ + "DELETE /orgs/{org}/projectsV2/{project_number}/items/{item_id}" + ], + deleteItemForUser: [ + "DELETE /users/{username}/projectsV2/{project_number}/items/{item_id}" + ], + getFieldForOrg: [ + "GET /orgs/{org}/projectsV2/{project_number}/fields/{field_id}" + ], + getFieldForUser: [ + "GET /users/{username}/projectsV2/{project_number}/fields/{field_id}" + ], + getForOrg: ["GET /orgs/{org}/projectsV2/{project_number}"], + getForUser: ["GET /users/{username}/projectsV2/{project_number}"], + getOrgItem: ["GET /orgs/{org}/projectsV2/{project_number}/items/{item_id}"], + getUserItem: [ + "GET /users/{username}/projectsV2/{project_number}/items/{item_id}" + ], + listFieldsForOrg: ["GET /orgs/{org}/projectsV2/{project_number}/fields"], + listFieldsForUser: [ + "GET /users/{username}/projectsV2/{project_number}/fields" + ], + listForOrg: ["GET /orgs/{org}/projectsV2"], + listForUser: ["GET /users/{username}/projectsV2"], + listItemsForOrg: ["GET /orgs/{org}/projectsV2/{project_number}/items"], + listItemsForUser: [ + "GET /users/{username}/projectsV2/{project_number}/items" + ], + updateItemForOrg: [ + "PATCH /orgs/{org}/projectsV2/{project_number}/items/{item_id}" + ], + updateItemForUser: [ + "PATCH /users/{username}/projectsV2/{project_number}/items/{item_id}" + ] + }, + pulls: { + checkIfMerged: ["GET /repos/{owner}/{repo}/pulls/{pull_number}/merge"], + create: ["POST /repos/{owner}/{repo}/pulls"], + createReplyForReviewComment: [ + "POST /repos/{owner}/{repo}/pulls/{pull_number}/comments/{comment_id}/replies" + ], + createReview: ["POST /repos/{owner}/{repo}/pulls/{pull_number}/reviews"], + createReviewComment: [ + "POST /repos/{owner}/{repo}/pulls/{pull_number}/comments" + ], + deletePendingReview: [ + "DELETE /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}" + ], + deleteReviewComment: [ + "DELETE /repos/{owner}/{repo}/pulls/comments/{comment_id}" + ], + dismissReview: [ + "PUT /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/dismissals" + ], + get: ["GET /repos/{owner}/{repo}/pulls/{pull_number}"], + getReview: [ + "GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}" + ], + getReviewComment: ["GET /repos/{owner}/{repo}/pulls/comments/{comment_id}"], + list: ["GET /repos/{owner}/{repo}/pulls"], + listCommentsForReview: [ + "GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/comments" + ], + listCommits: ["GET /repos/{owner}/{repo}/pulls/{pull_number}/commits"], + listFiles: ["GET /repos/{owner}/{repo}/pulls/{pull_number}/files"], + listRequestedReviewers: [ + "GET /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers" + ], + listReviewComments: [ + "GET /repos/{owner}/{repo}/pulls/{pull_number}/comments" + ], + listReviewCommentsForRepo: ["GET /repos/{owner}/{repo}/pulls/comments"], + listReviews: ["GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews"], + merge: ["PUT /repos/{owner}/{repo}/pulls/{pull_number}/merge"], + removeRequestedReviewers: [ + "DELETE /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers" + ], + requestReviewers: [ + "POST /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers" + ], + submitReview: [ + "POST /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/events" + ], + update: ["PATCH /repos/{owner}/{repo}/pulls/{pull_number}"], + updateBranch: [ + "PUT /repos/{owner}/{repo}/pulls/{pull_number}/update-branch" + ], + updateReview: [ + "PUT /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}" + ], + updateReviewComment: [ + "PATCH /repos/{owner}/{repo}/pulls/comments/{comment_id}" + ] + }, + rateLimit: { get: ["GET /rate_limit"] }, + reactions: { + createForCommitComment: [ + "POST /repos/{owner}/{repo}/comments/{comment_id}/reactions" + ], + createForIssue: [ + "POST /repos/{owner}/{repo}/issues/{issue_number}/reactions" + ], + createForIssueComment: [ + "POST /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions" + ], + createForPullRequestReviewComment: [ + "POST /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions" + ], + createForRelease: [ + "POST /repos/{owner}/{repo}/releases/{release_id}/reactions" + ], + createForTeamDiscussionCommentInOrg: [ + "POST /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions" + ], + createForTeamDiscussionInOrg: [ + "POST /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions" + ], + deleteForCommitComment: [ + "DELETE /repos/{owner}/{repo}/comments/{comment_id}/reactions/{reaction_id}" + ], + deleteForIssue: [ + "DELETE /repos/{owner}/{repo}/issues/{issue_number}/reactions/{reaction_id}" + ], + deleteForIssueComment: [ + "DELETE /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions/{reaction_id}" + ], + deleteForPullRequestComment: [ + "DELETE /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions/{reaction_id}" + ], + deleteForRelease: [ + "DELETE /repos/{owner}/{repo}/releases/{release_id}/reactions/{reaction_id}" + ], + deleteForTeamDiscussion: [ + "DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions/{reaction_id}" + ], + deleteForTeamDiscussionComment: [ + "DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions/{reaction_id}" + ], + listForCommitComment: [ + "GET /repos/{owner}/{repo}/comments/{comment_id}/reactions" + ], + listForIssue: ["GET /repos/{owner}/{repo}/issues/{issue_number}/reactions"], + listForIssueComment: [ + "GET /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions" + ], + listForPullRequestReviewComment: [ + "GET /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions" + ], + listForRelease: [ + "GET /repos/{owner}/{repo}/releases/{release_id}/reactions" + ], + listForTeamDiscussionCommentInOrg: [ + "GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions" + ], + listForTeamDiscussionInOrg: [ + "GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions" + ] + }, + repos: { + acceptInvitation: [ + "PATCH /user/repository_invitations/{invitation_id}", + {}, + { renamed: ["repos", "acceptInvitationForAuthenticatedUser"] } + ], + acceptInvitationForAuthenticatedUser: [ + "PATCH /user/repository_invitations/{invitation_id}" + ], + addAppAccessRestrictions: [ + "POST /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps", + {}, + { mapToData: "apps" } + ], + addCollaborator: ["PUT /repos/{owner}/{repo}/collaborators/{username}"], + addStatusCheckContexts: [ + "POST /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks/contexts", + {}, + { mapToData: "contexts" } + ], + addTeamAccessRestrictions: [ + "POST /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams", + {}, + { mapToData: "teams" } + ], + addUserAccessRestrictions: [ + "POST /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users", + {}, + { mapToData: "users" } + ], + cancelPagesDeployment: [ + "POST /repos/{owner}/{repo}/pages/deployments/{pages_deployment_id}/cancel" + ], + checkAutomatedSecurityFixes: [ + "GET /repos/{owner}/{repo}/automated-security-fixes" + ], + checkCollaborator: ["GET /repos/{owner}/{repo}/collaborators/{username}"], + checkImmutableReleases: ["GET /repos/{owner}/{repo}/immutable-releases"], + checkPrivateVulnerabilityReporting: [ + "GET /repos/{owner}/{repo}/private-vulnerability-reporting" + ], + checkVulnerabilityAlerts: [ + "GET /repos/{owner}/{repo}/vulnerability-alerts" + ], + codeownersErrors: ["GET /repos/{owner}/{repo}/codeowners/errors"], + compareCommits: ["GET /repos/{owner}/{repo}/compare/{base}...{head}"], + compareCommitsWithBasehead: [ + "GET /repos/{owner}/{repo}/compare/{basehead}" + ], + createAttestation: ["POST /repos/{owner}/{repo}/attestations"], + createAutolink: ["POST /repos/{owner}/{repo}/autolinks"], + createCommitComment: [ + "POST /repos/{owner}/{repo}/commits/{commit_sha}/comments" + ], + createCommitSignatureProtection: [ + "POST /repos/{owner}/{repo}/branches/{branch}/protection/required_signatures" + ], + createCommitStatus: ["POST /repos/{owner}/{repo}/statuses/{sha}"], + createDeployKey: ["POST /repos/{owner}/{repo}/keys"], + createDeployment: ["POST /repos/{owner}/{repo}/deployments"], + createDeploymentBranchPolicy: [ + "POST /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies" + ], + createDeploymentProtectionRule: [ + "POST /repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules" + ], + createDeploymentStatus: [ + "POST /repos/{owner}/{repo}/deployments/{deployment_id}/statuses" + ], + createDispatchEvent: ["POST /repos/{owner}/{repo}/dispatches"], + createForAuthenticatedUser: ["POST /user/repos"], + createFork: ["POST /repos/{owner}/{repo}/forks"], + createInOrg: ["POST /orgs/{org}/repos"], + createOrUpdateEnvironment: [ + "PUT /repos/{owner}/{repo}/environments/{environment_name}" + ], + createOrUpdateFileContents: ["PUT /repos/{owner}/{repo}/contents/{path}"], + createOrgRuleset: ["POST /orgs/{org}/rulesets"], + createPagesDeployment: ["POST /repos/{owner}/{repo}/pages/deployments"], + createPagesSite: ["POST /repos/{owner}/{repo}/pages"], + createRelease: ["POST /repos/{owner}/{repo}/releases"], + createRepoRuleset: ["POST /repos/{owner}/{repo}/rulesets"], + createUsingTemplate: [ + "POST /repos/{template_owner}/{template_repo}/generate" + ], + createWebhook: ["POST /repos/{owner}/{repo}/hooks"], + customPropertiesForReposCreateOrUpdateRepositoryValues: [ + "PATCH /repos/{owner}/{repo}/properties/values" + ], + customPropertiesForReposGetRepositoryValues: [ + "GET /repos/{owner}/{repo}/properties/values" + ], + declineInvitation: [ + "DELETE /user/repository_invitations/{invitation_id}", + {}, + { renamed: ["repos", "declineInvitationForAuthenticatedUser"] } + ], + declineInvitationForAuthenticatedUser: [ + "DELETE /user/repository_invitations/{invitation_id}" + ], + delete: ["DELETE /repos/{owner}/{repo}"], + deleteAccessRestrictions: [ + "DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions" + ], + deleteAdminBranchProtection: [ + "DELETE /repos/{owner}/{repo}/branches/{branch}/protection/enforce_admins" + ], + deleteAnEnvironment: [ + "DELETE /repos/{owner}/{repo}/environments/{environment_name}" + ], + deleteAutolink: ["DELETE /repos/{owner}/{repo}/autolinks/{autolink_id}"], + deleteBranchProtection: [ + "DELETE /repos/{owner}/{repo}/branches/{branch}/protection" + ], + deleteCommitComment: ["DELETE /repos/{owner}/{repo}/comments/{comment_id}"], + deleteCommitSignatureProtection: [ + "DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_signatures" + ], + deleteDeployKey: ["DELETE /repos/{owner}/{repo}/keys/{key_id}"], + deleteDeployment: [ + "DELETE /repos/{owner}/{repo}/deployments/{deployment_id}" + ], + deleteDeploymentBranchPolicy: [ + "DELETE /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies/{branch_policy_id}" + ], + deleteFile: ["DELETE /repos/{owner}/{repo}/contents/{path}"], + deleteInvitation: [ + "DELETE /repos/{owner}/{repo}/invitations/{invitation_id}" + ], + deleteOrgRuleset: ["DELETE /orgs/{org}/rulesets/{ruleset_id}"], + deletePagesSite: ["DELETE /repos/{owner}/{repo}/pages"], + deletePullRequestReviewProtection: [ + "DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews" + ], + deleteRelease: ["DELETE /repos/{owner}/{repo}/releases/{release_id}"], + deleteReleaseAsset: [ + "DELETE /repos/{owner}/{repo}/releases/assets/{asset_id}" + ], + deleteRepoRuleset: ["DELETE /repos/{owner}/{repo}/rulesets/{ruleset_id}"], + deleteWebhook: ["DELETE /repos/{owner}/{repo}/hooks/{hook_id}"], + disableAutomatedSecurityFixes: [ + "DELETE /repos/{owner}/{repo}/automated-security-fixes" + ], + disableDeploymentProtectionRule: [ + "DELETE /repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules/{protection_rule_id}" + ], + disableImmutableReleases: [ + "DELETE /repos/{owner}/{repo}/immutable-releases" + ], + disablePrivateVulnerabilityReporting: [ + "DELETE /repos/{owner}/{repo}/private-vulnerability-reporting" + ], + disableVulnerabilityAlerts: [ + "DELETE /repos/{owner}/{repo}/vulnerability-alerts" + ], + downloadArchive: [ + "GET /repos/{owner}/{repo}/zipball/{ref}", + {}, + { renamed: ["repos", "downloadZipballArchive"] } + ], + downloadTarballArchive: ["GET /repos/{owner}/{repo}/tarball/{ref}"], + downloadZipballArchive: ["GET /repos/{owner}/{repo}/zipball/{ref}"], + enableAutomatedSecurityFixes: [ + "PUT /repos/{owner}/{repo}/automated-security-fixes" + ], + enableImmutableReleases: ["PUT /repos/{owner}/{repo}/immutable-releases"], + enablePrivateVulnerabilityReporting: [ + "PUT /repos/{owner}/{repo}/private-vulnerability-reporting" + ], + enableVulnerabilityAlerts: [ + "PUT /repos/{owner}/{repo}/vulnerability-alerts" + ], + generateReleaseNotes: [ + "POST /repos/{owner}/{repo}/releases/generate-notes" + ], + get: ["GET /repos/{owner}/{repo}"], + getAccessRestrictions: [ + "GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions" + ], + getAdminBranchProtection: [ + "GET /repos/{owner}/{repo}/branches/{branch}/protection/enforce_admins" + ], + getAllDeploymentProtectionRules: [ + "GET /repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules" + ], + getAllEnvironments: ["GET /repos/{owner}/{repo}/environments"], + getAllStatusCheckContexts: [ + "GET /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks/contexts" + ], + getAllTopics: ["GET /repos/{owner}/{repo}/topics"], + getAppsWithAccessToProtectedBranch: [ + "GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps" + ], + getAutolink: ["GET /repos/{owner}/{repo}/autolinks/{autolink_id}"], + getBranch: ["GET /repos/{owner}/{repo}/branches/{branch}"], + getBranchProtection: [ + "GET /repos/{owner}/{repo}/branches/{branch}/protection" + ], + getBranchRules: ["GET /repos/{owner}/{repo}/rules/branches/{branch}"], + getClones: ["GET /repos/{owner}/{repo}/traffic/clones"], + getCodeFrequencyStats: ["GET /repos/{owner}/{repo}/stats/code_frequency"], + getCollaboratorPermissionLevel: [ + "GET /repos/{owner}/{repo}/collaborators/{username}/permission" + ], + getCombinedStatusForRef: ["GET /repos/{owner}/{repo}/commits/{ref}/status"], + getCommit: ["GET /repos/{owner}/{repo}/commits/{ref}"], + getCommitActivityStats: ["GET /repos/{owner}/{repo}/stats/commit_activity"], + getCommitComment: ["GET /repos/{owner}/{repo}/comments/{comment_id}"], + getCommitSignatureProtection: [ + "GET /repos/{owner}/{repo}/branches/{branch}/protection/required_signatures" + ], + getCommunityProfileMetrics: ["GET /repos/{owner}/{repo}/community/profile"], + getContent: ["GET /repos/{owner}/{repo}/contents/{path}"], + getContributorsStats: ["GET /repos/{owner}/{repo}/stats/contributors"], + getCustomDeploymentProtectionRule: [ + "GET /repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules/{protection_rule_id}" + ], + getDeployKey: ["GET /repos/{owner}/{repo}/keys/{key_id}"], + getDeployment: ["GET /repos/{owner}/{repo}/deployments/{deployment_id}"], + getDeploymentBranchPolicy: [ + "GET /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies/{branch_policy_id}" + ], + getDeploymentStatus: [ + "GET /repos/{owner}/{repo}/deployments/{deployment_id}/statuses/{status_id}" + ], + getEnvironment: [ + "GET /repos/{owner}/{repo}/environments/{environment_name}" + ], + getLatestPagesBuild: ["GET /repos/{owner}/{repo}/pages/builds/latest"], + getLatestRelease: ["GET /repos/{owner}/{repo}/releases/latest"], + getOrgRuleSuite: ["GET /orgs/{org}/rulesets/rule-suites/{rule_suite_id}"], + getOrgRuleSuites: ["GET /orgs/{org}/rulesets/rule-suites"], + getOrgRuleset: ["GET /orgs/{org}/rulesets/{ruleset_id}"], + getOrgRulesets: ["GET /orgs/{org}/rulesets"], + getPages: ["GET /repos/{owner}/{repo}/pages"], + getPagesBuild: ["GET /repos/{owner}/{repo}/pages/builds/{build_id}"], + getPagesDeployment: [ + "GET /repos/{owner}/{repo}/pages/deployments/{pages_deployment_id}" + ], + getPagesHealthCheck: ["GET /repos/{owner}/{repo}/pages/health"], + getParticipationStats: ["GET /repos/{owner}/{repo}/stats/participation"], + getPullRequestReviewProtection: [ + "GET /repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews" + ], + getPunchCardStats: ["GET /repos/{owner}/{repo}/stats/punch_card"], + getReadme: ["GET /repos/{owner}/{repo}/readme"], + getReadmeInDirectory: ["GET /repos/{owner}/{repo}/readme/{dir}"], + getRelease: ["GET /repos/{owner}/{repo}/releases/{release_id}"], + getReleaseAsset: ["GET /repos/{owner}/{repo}/releases/assets/{asset_id}"], + getReleaseByTag: ["GET /repos/{owner}/{repo}/releases/tags/{tag}"], + getRepoRuleSuite: [ + "GET /repos/{owner}/{repo}/rulesets/rule-suites/{rule_suite_id}" + ], + getRepoRuleSuites: ["GET /repos/{owner}/{repo}/rulesets/rule-suites"], + getRepoRuleset: ["GET /repos/{owner}/{repo}/rulesets/{ruleset_id}"], + getRepoRulesetHistory: [ + "GET /repos/{owner}/{repo}/rulesets/{ruleset_id}/history" + ], + getRepoRulesetVersion: [ + "GET /repos/{owner}/{repo}/rulesets/{ruleset_id}/history/{version_id}" + ], + getRepoRulesets: ["GET /repos/{owner}/{repo}/rulesets"], + getStatusChecksProtection: [ + "GET /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks" + ], + getTeamsWithAccessToProtectedBranch: [ + "GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams" + ], + getTopPaths: ["GET /repos/{owner}/{repo}/traffic/popular/paths"], + getTopReferrers: ["GET /repos/{owner}/{repo}/traffic/popular/referrers"], + getUsersWithAccessToProtectedBranch: [ + "GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users" + ], + getViews: ["GET /repos/{owner}/{repo}/traffic/views"], + getWebhook: ["GET /repos/{owner}/{repo}/hooks/{hook_id}"], + getWebhookConfigForRepo: [ + "GET /repos/{owner}/{repo}/hooks/{hook_id}/config" + ], + getWebhookDelivery: [ + "GET /repos/{owner}/{repo}/hooks/{hook_id}/deliveries/{delivery_id}" + ], + listActivities: ["GET /repos/{owner}/{repo}/activity"], + listAttestations: [ + "GET /repos/{owner}/{repo}/attestations/{subject_digest}" + ], + listAutolinks: ["GET /repos/{owner}/{repo}/autolinks"], + listBranches: ["GET /repos/{owner}/{repo}/branches"], + listBranchesForHeadCommit: [ + "GET /repos/{owner}/{repo}/commits/{commit_sha}/branches-where-head" + ], + listCollaborators: ["GET /repos/{owner}/{repo}/collaborators"], + listCommentsForCommit: [ + "GET /repos/{owner}/{repo}/commits/{commit_sha}/comments" + ], + listCommitCommentsForRepo: ["GET /repos/{owner}/{repo}/comments"], + listCommitStatusesForRef: [ + "GET /repos/{owner}/{repo}/commits/{ref}/statuses" + ], + listCommits: ["GET /repos/{owner}/{repo}/commits"], + listContributors: ["GET /repos/{owner}/{repo}/contributors"], + listCustomDeploymentRuleIntegrations: [ + "GET /repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules/apps" + ], + listDeployKeys: ["GET /repos/{owner}/{repo}/keys"], + listDeploymentBranchPolicies: [ + "GET /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies" + ], + listDeploymentStatuses: [ + "GET /repos/{owner}/{repo}/deployments/{deployment_id}/statuses" + ], + listDeployments: ["GET /repos/{owner}/{repo}/deployments"], + listForAuthenticatedUser: ["GET /user/repos"], + listForOrg: ["GET /orgs/{org}/repos"], + listForUser: ["GET /users/{username}/repos"], + listForks: ["GET /repos/{owner}/{repo}/forks"], + listInvitations: ["GET /repos/{owner}/{repo}/invitations"], + listInvitationsForAuthenticatedUser: ["GET /user/repository_invitations"], + listLanguages: ["GET /repos/{owner}/{repo}/languages"], + listPagesBuilds: ["GET /repos/{owner}/{repo}/pages/builds"], + listPublic: ["GET /repositories"], + listPullRequestsAssociatedWithCommit: [ + "GET /repos/{owner}/{repo}/commits/{commit_sha}/pulls" + ], + listReleaseAssets: [ + "GET /repos/{owner}/{repo}/releases/{release_id}/assets" + ], + listReleases: ["GET /repos/{owner}/{repo}/releases"], + listTags: ["GET /repos/{owner}/{repo}/tags"], + listTeams: ["GET /repos/{owner}/{repo}/teams"], + listWebhookDeliveries: [ + "GET /repos/{owner}/{repo}/hooks/{hook_id}/deliveries" + ], + listWebhooks: ["GET /repos/{owner}/{repo}/hooks"], + merge: ["POST /repos/{owner}/{repo}/merges"], + mergeUpstream: ["POST /repos/{owner}/{repo}/merge-upstream"], + pingWebhook: ["POST /repos/{owner}/{repo}/hooks/{hook_id}/pings"], + redeliverWebhookDelivery: [ + "POST /repos/{owner}/{repo}/hooks/{hook_id}/deliveries/{delivery_id}/attempts" + ], + removeAppAccessRestrictions: [ + "DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps", + {}, + { mapToData: "apps" } + ], + removeCollaborator: [ + "DELETE /repos/{owner}/{repo}/collaborators/{username}" + ], + removeStatusCheckContexts: [ + "DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks/contexts", + {}, + { mapToData: "contexts" } + ], + removeStatusCheckProtection: [ + "DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks" + ], + removeTeamAccessRestrictions: [ + "DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams", + {}, + { mapToData: "teams" } + ], + removeUserAccessRestrictions: [ + "DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users", + {}, + { mapToData: "users" } + ], + renameBranch: ["POST /repos/{owner}/{repo}/branches/{branch}/rename"], + replaceAllTopics: ["PUT /repos/{owner}/{repo}/topics"], + requestPagesBuild: ["POST /repos/{owner}/{repo}/pages/builds"], + setAdminBranchProtection: [ + "POST /repos/{owner}/{repo}/branches/{branch}/protection/enforce_admins" + ], + setAppAccessRestrictions: [ + "PUT /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps", + {}, + { mapToData: "apps" } + ], + setStatusCheckContexts: [ + "PUT /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks/contexts", + {}, + { mapToData: "contexts" } + ], + setTeamAccessRestrictions: [ + "PUT /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams", + {}, + { mapToData: "teams" } + ], + setUserAccessRestrictions: [ + "PUT /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users", + {}, + { mapToData: "users" } + ], + testPushWebhook: ["POST /repos/{owner}/{repo}/hooks/{hook_id}/tests"], + transfer: ["POST /repos/{owner}/{repo}/transfer"], + update: ["PATCH /repos/{owner}/{repo}"], + updateBranchProtection: [ + "PUT /repos/{owner}/{repo}/branches/{branch}/protection" + ], + updateCommitComment: ["PATCH /repos/{owner}/{repo}/comments/{comment_id}"], + updateDeploymentBranchPolicy: [ + "PUT /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies/{branch_policy_id}" + ], + updateInformationAboutPagesSite: ["PUT /repos/{owner}/{repo}/pages"], + updateInvitation: [ + "PATCH /repos/{owner}/{repo}/invitations/{invitation_id}" + ], + updateOrgRuleset: ["PUT /orgs/{org}/rulesets/{ruleset_id}"], + updatePullRequestReviewProtection: [ + "PATCH /repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews" + ], + updateRelease: ["PATCH /repos/{owner}/{repo}/releases/{release_id}"], + updateReleaseAsset: [ + "PATCH /repos/{owner}/{repo}/releases/assets/{asset_id}" + ], + updateRepoRuleset: ["PUT /repos/{owner}/{repo}/rulesets/{ruleset_id}"], + updateStatusCheckPotection: [ + "PATCH /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks", + {}, + { renamed: ["repos", "updateStatusCheckProtection"] } + ], + updateStatusCheckProtection: [ + "PATCH /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks" + ], + updateWebhook: ["PATCH /repos/{owner}/{repo}/hooks/{hook_id}"], + updateWebhookConfigForRepo: [ + "PATCH /repos/{owner}/{repo}/hooks/{hook_id}/config" + ], + uploadReleaseAsset: [ + "POST /repos/{owner}/{repo}/releases/{release_id}/assets{?name,label}", + { baseUrl: "https://uploads.github.com" } + ] + }, + search: { + code: ["GET /search/code"], + commits: ["GET /search/commits"], + issuesAndPullRequests: ["GET /search/issues"], + labels: ["GET /search/labels"], + repos: ["GET /search/repositories"], + topics: ["GET /search/topics"], + users: ["GET /search/users"] + }, + secretScanning: { + createPushProtectionBypass: [ + "POST /repos/{owner}/{repo}/secret-scanning/push-protection-bypasses" + ], + getAlert: [ + "GET /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}" + ], + getScanHistory: ["GET /repos/{owner}/{repo}/secret-scanning/scan-history"], + listAlertsForOrg: ["GET /orgs/{org}/secret-scanning/alerts"], + listAlertsForRepo: ["GET /repos/{owner}/{repo}/secret-scanning/alerts"], + listLocationsForAlert: [ + "GET /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}/locations" + ], + listOrgPatternConfigs: [ + "GET /orgs/{org}/secret-scanning/pattern-configurations" + ], + updateAlert: [ + "PATCH /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}" + ], + updateOrgPatternConfigs: [ + "PATCH /orgs/{org}/secret-scanning/pattern-configurations" + ] + }, + securityAdvisories: { + createFork: [ + "POST /repos/{owner}/{repo}/security-advisories/{ghsa_id}/forks" + ], + createPrivateVulnerabilityReport: [ + "POST /repos/{owner}/{repo}/security-advisories/reports" + ], + createRepositoryAdvisory: [ + "POST /repos/{owner}/{repo}/security-advisories" + ], + createRepositoryAdvisoryCveRequest: [ + "POST /repos/{owner}/{repo}/security-advisories/{ghsa_id}/cve" + ], + getGlobalAdvisory: ["GET /advisories/{ghsa_id}"], + getRepositoryAdvisory: [ + "GET /repos/{owner}/{repo}/security-advisories/{ghsa_id}" + ], + listGlobalAdvisories: ["GET /advisories"], + listOrgRepositoryAdvisories: ["GET /orgs/{org}/security-advisories"], + listRepositoryAdvisories: ["GET /repos/{owner}/{repo}/security-advisories"], + updateRepositoryAdvisory: [ + "PATCH /repos/{owner}/{repo}/security-advisories/{ghsa_id}" + ] + }, + teams: { + addOrUpdateMembershipForUserInOrg: [ + "PUT /orgs/{org}/teams/{team_slug}/memberships/{username}" + ], + addOrUpdateRepoPermissionsInOrg: [ + "PUT /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}" + ], + checkPermissionsForRepoInOrg: [ + "GET /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}" + ], + create: ["POST /orgs/{org}/teams"], + createDiscussionCommentInOrg: [ + "POST /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments" + ], + createDiscussionInOrg: ["POST /orgs/{org}/teams/{team_slug}/discussions"], + deleteDiscussionCommentInOrg: [ + "DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}" + ], + deleteDiscussionInOrg: [ + "DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}" + ], + deleteInOrg: ["DELETE /orgs/{org}/teams/{team_slug}"], + getByName: ["GET /orgs/{org}/teams/{team_slug}"], + getDiscussionCommentInOrg: [ + "GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}" + ], + getDiscussionInOrg: [ + "GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}" + ], + getMembershipForUserInOrg: [ + "GET /orgs/{org}/teams/{team_slug}/memberships/{username}" + ], + list: ["GET /orgs/{org}/teams"], + listChildInOrg: ["GET /orgs/{org}/teams/{team_slug}/teams"], + listDiscussionCommentsInOrg: [ + "GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments" + ], + listDiscussionsInOrg: ["GET /orgs/{org}/teams/{team_slug}/discussions"], + listForAuthenticatedUser: ["GET /user/teams"], + listMembersInOrg: ["GET /orgs/{org}/teams/{team_slug}/members"], + listPendingInvitationsInOrg: [ + "GET /orgs/{org}/teams/{team_slug}/invitations" + ], + listReposInOrg: ["GET /orgs/{org}/teams/{team_slug}/repos"], + removeMembershipForUserInOrg: [ + "DELETE /orgs/{org}/teams/{team_slug}/memberships/{username}" + ], + removeRepoInOrg: [ + "DELETE /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}" + ], + updateDiscussionCommentInOrg: [ + "PATCH /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}" + ], + updateDiscussionInOrg: [ + "PATCH /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}" + ], + updateInOrg: ["PATCH /orgs/{org}/teams/{team_slug}"] + }, + users: { + addEmailForAuthenticated: [ + "POST /user/emails", + {}, + { renamed: ["users", "addEmailForAuthenticatedUser"] } + ], + addEmailForAuthenticatedUser: ["POST /user/emails"], + addSocialAccountForAuthenticatedUser: ["POST /user/social_accounts"], + block: ["PUT /user/blocks/{username}"], + checkBlocked: ["GET /user/blocks/{username}"], + checkFollowingForUser: ["GET /users/{username}/following/{target_user}"], + checkPersonIsFollowedByAuthenticated: ["GET /user/following/{username}"], + createGpgKeyForAuthenticated: [ + "POST /user/gpg_keys", + {}, + { renamed: ["users", "createGpgKeyForAuthenticatedUser"] } + ], + createGpgKeyForAuthenticatedUser: ["POST /user/gpg_keys"], + createPublicSshKeyForAuthenticated: [ + "POST /user/keys", + {}, + { renamed: ["users", "createPublicSshKeyForAuthenticatedUser"] } + ], + createPublicSshKeyForAuthenticatedUser: ["POST /user/keys"], + createSshSigningKeyForAuthenticatedUser: ["POST /user/ssh_signing_keys"], + deleteAttestationsBulk: [ + "POST /users/{username}/attestations/delete-request" + ], + deleteAttestationsById: [ + "DELETE /users/{username}/attestations/{attestation_id}" + ], + deleteAttestationsBySubjectDigest: [ + "DELETE /users/{username}/attestations/digest/{subject_digest}" + ], + deleteEmailForAuthenticated: [ + "DELETE /user/emails", + {}, + { renamed: ["users", "deleteEmailForAuthenticatedUser"] } + ], + deleteEmailForAuthenticatedUser: ["DELETE /user/emails"], + deleteGpgKeyForAuthenticated: [ + "DELETE /user/gpg_keys/{gpg_key_id}", + {}, + { renamed: ["users", "deleteGpgKeyForAuthenticatedUser"] } + ], + deleteGpgKeyForAuthenticatedUser: ["DELETE /user/gpg_keys/{gpg_key_id}"], + deletePublicSshKeyForAuthenticated: [ + "DELETE /user/keys/{key_id}", + {}, + { renamed: ["users", "deletePublicSshKeyForAuthenticatedUser"] } + ], + deletePublicSshKeyForAuthenticatedUser: ["DELETE /user/keys/{key_id}"], + deleteSocialAccountForAuthenticatedUser: ["DELETE /user/social_accounts"], + deleteSshSigningKeyForAuthenticatedUser: [ + "DELETE /user/ssh_signing_keys/{ssh_signing_key_id}" + ], + follow: ["PUT /user/following/{username}"], + getAuthenticated: ["GET /user"], + getById: ["GET /user/{account_id}"], + getByUsername: ["GET /users/{username}"], + getContextForUser: ["GET /users/{username}/hovercard"], + getGpgKeyForAuthenticated: [ + "GET /user/gpg_keys/{gpg_key_id}", + {}, + { renamed: ["users", "getGpgKeyForAuthenticatedUser"] } + ], + getGpgKeyForAuthenticatedUser: ["GET /user/gpg_keys/{gpg_key_id}"], + getPublicSshKeyForAuthenticated: [ + "GET /user/keys/{key_id}", + {}, + { renamed: ["users", "getPublicSshKeyForAuthenticatedUser"] } + ], + getPublicSshKeyForAuthenticatedUser: ["GET /user/keys/{key_id}"], + getSshSigningKeyForAuthenticatedUser: [ + "GET /user/ssh_signing_keys/{ssh_signing_key_id}" + ], + list: ["GET /users"], + listAttestations: ["GET /users/{username}/attestations/{subject_digest}"], + listAttestationsBulk: [ + "POST /users/{username}/attestations/bulk-list{?per_page,before,after}" + ], + listBlockedByAuthenticated: [ + "GET /user/blocks", + {}, + { renamed: ["users", "listBlockedByAuthenticatedUser"] } + ], + listBlockedByAuthenticatedUser: ["GET /user/blocks"], + listEmailsForAuthenticated: [ + "GET /user/emails", + {}, + { renamed: ["users", "listEmailsForAuthenticatedUser"] } + ], + listEmailsForAuthenticatedUser: ["GET /user/emails"], + listFollowedByAuthenticated: [ + "GET /user/following", + {}, + { renamed: ["users", "listFollowedByAuthenticatedUser"] } + ], + listFollowedByAuthenticatedUser: ["GET /user/following"], + listFollowersForAuthenticatedUser: ["GET /user/followers"], + listFollowersForUser: ["GET /users/{username}/followers"], + listFollowingForUser: ["GET /users/{username}/following"], + listGpgKeysForAuthenticated: [ + "GET /user/gpg_keys", + {}, + { renamed: ["users", "listGpgKeysForAuthenticatedUser"] } + ], + listGpgKeysForAuthenticatedUser: ["GET /user/gpg_keys"], + listGpgKeysForUser: ["GET /users/{username}/gpg_keys"], + listPublicEmailsForAuthenticated: [ + "GET /user/public_emails", + {}, + { renamed: ["users", "listPublicEmailsForAuthenticatedUser"] } + ], + listPublicEmailsForAuthenticatedUser: ["GET /user/public_emails"], + listPublicKeysForUser: ["GET /users/{username}/keys"], + listPublicSshKeysForAuthenticated: [ + "GET /user/keys", + {}, + { renamed: ["users", "listPublicSshKeysForAuthenticatedUser"] } + ], + listPublicSshKeysForAuthenticatedUser: ["GET /user/keys"], + listSocialAccountsForAuthenticatedUser: ["GET /user/social_accounts"], + listSocialAccountsForUser: ["GET /users/{username}/social_accounts"], + listSshSigningKeysForAuthenticatedUser: ["GET /user/ssh_signing_keys"], + listSshSigningKeysForUser: ["GET /users/{username}/ssh_signing_keys"], + setPrimaryEmailVisibilityForAuthenticated: [ + "PATCH /user/email/visibility", + {}, + { renamed: ["users", "setPrimaryEmailVisibilityForAuthenticatedUser"] } + ], + setPrimaryEmailVisibilityForAuthenticatedUser: [ + "PATCH /user/email/visibility" + ], + unblock: ["DELETE /user/blocks/{username}"], + unfollow: ["DELETE /user/following/{username}"], + updateAuthenticated: ["PATCH /user"] + } }; +var endpoints_default = Endpoints; -const unionFastGlobResults = (results, filter) => results.flat().filter(fastGlobResult => filter(fastGlobResult)); - -const convertNegativePatterns = (patterns, options) => { - // If all patterns are negative and expandNegationOnlyPatterns is enabled (default), - // prepend a positive catch-all pattern to make negation-only patterns work intuitively - // (e.g., '!*.json' matches all files except JSON) - if (patterns.length > 0 && patterns.every(pattern => isNegativePattern(pattern))) { - if (options.expandNegationOnlyPatterns === false) { - return []; - } - - patterns = ['**/*', ...patterns]; - } +//# sourceMappingURL=endpoints.js.map - patterns = patterns.map(pattern => isNegativePattern(pattern) - ? `!${normalizeAbsolutePatternToRelative(pattern.slice(1))}` - : pattern); +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@octokit/plugin-rest-endpoint-methods/17.0.0/23bcad6a6f09bbdd8bd9193c1b6ebd3b4d7d5c15f3d5d6a119345284a74f0760/node_modules/@octokit/plugin-rest-endpoint-methods/dist-src/endpoints-to-methods.js - const tasks = []; +const endpointMethodsMap = /* @__PURE__ */ new Map(); +for (const [scope, endpoints] of Object.entries(endpoints_default)) { + for (const [methodName, endpoint] of Object.entries(endpoints)) { + const [route, defaults, decorations] = endpoint; + const [method, url] = route.split(/ /); + const endpointDefaults = Object.assign( + { + method, + url + }, + defaults + ); + if (!endpointMethodsMap.has(scope)) { + endpointMethodsMap.set(scope, /* @__PURE__ */ new Map()); + } + endpointMethodsMap.get(scope).set(methodName, { + scope, + methodName, + endpointDefaults, + decorations + }); + } +} +const handler = { + has({ scope }, methodName) { + return endpointMethodsMap.get(scope).has(methodName); + }, + getOwnPropertyDescriptor(target, methodName) { + return { + value: this.get(target, methodName), + // ensures method is in the cache + configurable: true, + writable: true, + enumerable: true + }; + }, + defineProperty(target, methodName, descriptor) { + Object.defineProperty(target.cache, methodName, descriptor); + return true; + }, + deleteProperty(target, methodName) { + delete target.cache[methodName]; + return true; + }, + ownKeys({ scope }) { + return [...endpointMethodsMap.get(scope).keys()]; + }, + set(target, methodName, value) { + return target.cache[methodName] = value; + }, + get({ octokit, scope, cache }, methodName) { + if (cache[methodName]) { + return cache[methodName]; + } + const method = endpointMethodsMap.get(scope).get(methodName); + if (!method) { + return void 0; + } + const { endpointDefaults, decorations } = method; + if (decorations) { + cache[methodName] = decorate( + octokit, + scope, + methodName, + endpointDefaults, + decorations + ); + } else { + cache[methodName] = octokit.request.defaults(endpointDefaults); + } + return cache[methodName]; + } +}; +function endpointsToMethods(octokit) { + const newMethods = {}; + for (const scope of endpointMethodsMap.keys()) { + newMethods[scope] = new Proxy({ octokit, scope, cache: {} }, handler); + } + return newMethods; +} +function decorate(octokit, scope, methodName, defaults, decorations) { + const requestWithDefaults = octokit.request.defaults(defaults); + function withDecorations(...args) { + let options = requestWithDefaults.endpoint.merge(...args); + if (decorations.mapToData) { + options = Object.assign({}, options, { + data: options[decorations.mapToData], + [decorations.mapToData]: void 0 + }); + return requestWithDefaults(options); + } + if (decorations.renamed) { + const [newScope, newMethodName] = decorations.renamed; + octokit.log.warn( + `octokit.${scope}.${methodName}() has been renamed to octokit.${newScope}.${newMethodName}()` + ); + } + if (decorations.deprecated) { + octokit.log.warn(decorations.deprecated); + } + if (decorations.renamedParameters) { + const options2 = requestWithDefaults.endpoint.merge(...args); + for (const [name, alias] of Object.entries( + decorations.renamedParameters + )) { + if (name in options2) { + octokit.log.warn( + `"${name}" parameter is deprecated for "octokit.${scope}.${methodName}()". Use "${alias}" instead` + ); + if (!(alias in options2)) { + options2[alias] = options2[name]; + } + delete options2[name]; + } + } + return requestWithDefaults(options2); + } + return requestWithDefaults(...args); + } + return Object.assign(withDecorations, requestWithDefaults); +} - while (patterns.length > 0) { - const index = patterns.findIndex(pattern => isNegativePattern(pattern)); +//# sourceMappingURL=endpoints-to-methods.js.map - if (index === -1) { - tasks.push({patterns, options}); - break; - } +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@octokit/plugin-rest-endpoint-methods/17.0.0/23bcad6a6f09bbdd8bd9193c1b6ebd3b4d7d5c15f3d5d6a119345284a74f0760/node_modules/@octokit/plugin-rest-endpoint-methods/dist-src/index.js - const ignorePattern = patterns[index].slice(1); - for (const task of tasks) { - task.options.ignore.push(ignorePattern); - } +function restEndpointMethods(octokit) { + const api = endpointsToMethods(octokit); + return { + rest: api + }; +} +restEndpointMethods.VERSION = plugin_rest_endpoint_methods_dist_src_version_VERSION; +function legacyRestEndpointMethods(octokit) { + const api = endpointsToMethods(octokit); + return { + ...api, + rest: api + }; +} +legacyRestEndpointMethods.VERSION = plugin_rest_endpoint_methods_dist_src_version_VERSION; - if (index !== 0) { - tasks.push({ - patterns: patterns.slice(0, index), - options: { - ...options, - ignore: [ - ...options.ignore, - ignorePattern, - ], - }, - }); - } +//# sourceMappingURL=index.js.map - patterns = patterns.slice(index + 1); - } +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@octokit/rest/22.0.1/4c3bb74612de15a47f9dee5e98a684c7ea32d1bf8fb5361ea1471543c9284017/node_modules/@octokit/rest/dist-src/version.js +const rest_dist_src_version_VERSION = "22.0.1"; - return tasks; -}; -const applyParentDirectoryIgnoreAdjustments = tasks => tasks.map(task => ({ - patterns: task.patterns, - options: { - ...task.options, - ignore: adjustIgnorePatternsForParentDirectories(task.patterns, task.options.ignore), - }, -})); +;// CONCATENATED MODULE: ../../../Library/pnpm/store/v10/links/@octokit/rest/22.0.1/4c3bb74612de15a47f9dee5e98a684c7ea32d1bf8fb5361ea1471543c9284017/node_modules/@octokit/rest/dist-src/index.js -const normalizeExpandDirectoriesOption = (options, cwd) => ({ - ...(cwd ? {cwd} : {}), - ...(Array.isArray(options) ? {files: options} : options), -}); -const generateTasks = async (patterns, options) => { - const globTasks = convertNegativePatterns(patterns, options); - const {cwd, expandDirectories, fs: fsImplementation} = options; - if (!expandDirectories) { - return applyParentDirectoryIgnoreAdjustments(globTasks); - } - const directoryToGlobOptions = { - ...normalizeExpandDirectoriesOption(expandDirectories, cwd), - fs: fsImplementation, - }; +const dist_src_Octokit = Octokit.plugin(requestLog, legacyRestEndpointMethods, paginateRest).defaults( + { + userAgent: `octokit-rest.js/${rest_dist_src_version_VERSION}` + } +); - return Promise.all(globTasks.map(async task => { - let {patterns, options} = task; - [ - patterns, - options.ignore, - ] = await Promise.all([ - directoryToGlob(patterns, directoryToGlobOptions), - directoryToGlob(options.ignore, {cwd, fs: fsImplementation}), - ]); +// EXTERNAL MODULE: ../../../Library/pnpm/store/v10/links/@/undici/7.20.0/0345d75ecd64b200bf7baf2fdf6ebb3cfcab1af1828f13a4ec4996b0e77c2d98/node_modules/undici/index.js +var node_modules_undici = __nccwpck_require__(2514); +;// CONCATENATED MODULE: ./src/setup.ts +/** + * Author: hustcer + * Created: 2022/04/28 18:50:20 + */ - // Adjust ignore patterns for parent directory references - options.ignore = adjustIgnorePatternsForParentDirectories(patterns, options.ignore); - return {patterns, options}; - })); -}; -const generateTasksSync = (patterns, options) => { - const globTasks = convertNegativePatterns(patterns, options); - const {cwd, expandDirectories, fs: fsImplementation} = options; - if (!expandDirectories) { - return applyParentDirectoryIgnoreAdjustments(globTasks); - } - const directoryToGlobSyncOptions = { - ...normalizeExpandDirectoriesOption(expandDirectories, cwd), - fs: fsImplementation, - }; - return globTasks.map(task => { - let {patterns, options} = task; - patterns = directoryToGlobSync(patterns, directoryToGlobSyncOptions); - options.ignore = directoryToGlobSync(options.ignore, {cwd, fs: fsImplementation}); - // Adjust ignore patterns for parent directory references - options.ignore = adjustIgnorePatternsForParentDirectories(patterns, options.ignore); - return {patterns, options}; - }); +const PLATFORM_DEFAULT_MAP = { + darwin_x64: ['x86_64-apple-darwin', 'macOS.zip'], + darwin_arm64: ['aarch64-apple-darwin', 'macOS.zip'], + win32_x64: ['x86_64-pc-windows-msvc.zip', 'windows.zip'], + win32_arm64: ['aarch64-pc-windows-msvc.zip'], + linux_riscv64: ['riscv64gc-unknown-linux-gnu'], + linux_loong64: ['loongarch64-unknown-linux-gnu'], + linux_arm64: ['aarch64-unknown-linux-musl', 'aarch64-unknown-linux-gnu'], + linux_x64: ['x86_64-unknown-linux-musl', 'x86_64-unknown-linux-gnu', 'linux.tar.gz'], +}; +const PLATFORM_FULL_MAP = { + darwin_x64: ['x86_64-darwin-full'], + darwin_arm64: ['aarch64-darwin-full'], + win32_x64: ['x86_64-windows-msvc-full.zip'], + win32_arm64: ['aarch64-windows-msvc-full.zip'], + linux_arm64: ['aarch64-linux-gnu-full'], + linux_riscv64: ['riscv64gc-unknown-linux-gnu-full'], + linux_loong64: ['loongarch64-unknown-linux-gnu-full'], + linux_x64: ['x86_64-linux-musl-full', 'x86_64-linux-gnu-full'], }; +// Singleton to ensure efficient use of connection pooling, resources, etc. +const proxyAgent = new node_modules_undici/* EnvHttpProxyAgent */.J2(); +/** + * @returns {string[]} possible nushell target specifiers for the current platform. + */ +function getTargets(features) { + const { arch, platform } = process; + const selector = `${platform}_${arch}`; + info(`Try to get assets for Nu: arch = ${arch}, platform = ${platform}, feature = ${features}`); + const platformMap = features === 'default' ? PLATFORM_DEFAULT_MAP : PLATFORM_FULL_MAP; + const targets = platformMap[selector]; + if (!targets) { + throw new Error(`Unsupported Nu target combination: arch = ${arch}, platform = ${platform}, feature = ${features}`); + } + return targets; +} +/** + * Filter the matching release for the given tool with the specified versionSpec. + * + * @param response the response to filter a release from with the given versionSpec. + * @returns {Release[]} a single GitHub release. + */ +// biome-ignore lint: Ignore +function filterMatch(response, versionSpec, features) { + const targets = getTargets(features); + return (response.data + // biome-ignore lint: Ignore + .map((rel) => { + const asset = rel.assets.find((ass) => targets.some((target) => ass.name.includes(target))); + if (asset) { + return { + version: rel.tag_name.replace(/^v/, ''), + downloadUrl: asset.browser_download_url, + }; + } + }) + .filter((rel) => rel && versionSpec ? node_modules_semver.satisfies(rel.version, versionSpec) : true)); +} +/** + * Filter the latest matching release for the given tool. + * + * @param response the response to filter a latest release from. + * @returns {Release[]} a single GitHub release. + */ +// biome-ignore lint: Ignore +function filterLatest(response, features) { + const targets = getTargets(features); + const versions = response.data.map((r) => r.tag_name); + const latest = node_modules_semver.rsort(versions)[0]; + return (response.data + .filter((rel) => rel && rel.tag_name === latest) + // biome-ignore lint: Ignore + .map((rel) => { + const asset = rel.assets.find((ass) => targets.some((target) => ass.name.includes(target))); + if (asset) { + return { + version: rel.tag_name.replace(/^v/, ''), + downloadUrl: asset.browser_download_url, + }; + } + })); +} +/** + * Filter the latest matching release for the given tool. + * + * @param response the response to filter a latest release from. + * @returns {Release[]} a single GitHub release. + */ +// biome-ignore lint: Ignore +function filterLatestNightly(response, features) { + const targets = getTargets(features); + const publishedAt = response.data.map((r) => r.published_at); + const sortedDates = publishedAt.sort((a, b) => new Date(b).getTime() - new Date(a).getTime()); + const latest = sortedDates[0]; + info(`Try to get latest nightly version published at: ${latest}`); + return (response.data + .filter((rel) => rel && rel.published_at === latest) + // biome-ignore lint: Ignore + .map((rel) => { + const asset = rel.assets.find((ass) => targets.some((target) => ass.name.includes(target))); + if (asset) { + return { + version: rel.tag_name.replace(/^v/, ''), + downloadUrl: asset.browser_download_url, + }; + } + })); +} +/** + * Fetch the latest matching release for the given tool. + * + * @param tool the tool to fetch a release for. + * + * @returns {Promise} a single GitHub release. + */ +async function getRelease(tool) { + const { owner, name, versionSpec, checkLatest = false, features = 'default' } = tool; + const isNightly = versionSpec === 'nightly'; + const octokit = new dist_src_Octokit({ + auth: tool.githubToken, + // Use public GitHub API for Nushell assets query, make it work for GitHub Enterprise + baseUrl: 'https://api.github.com', + request: { fetch: proxyFetch }, + }); + return octokit + .paginate(octokit.repos.listReleases, { owner, repo: name }, (response, done) => { + const nightlyReleases = isNightly ? filterLatestNightly(response, features) : []; + const officialReleases = checkLatest + ? filterLatest(response, features) + : filterMatch(response, versionSpec, features); + const releases = isNightly ? nightlyReleases : officialReleases; + if (releases) { + done(); + } + return releases; + }) + .then((releases) => { + const release = releases.find((release) => release != null); + if (release === undefined) { + if (features === 'full') { + warning('The "full" feature was removed for Nu after v0.93.1, try to use "default" feature instead.'); + } + throw new Error(`No release for Nushell matching version specifier ${versionSpec} of ${features} feature.`); + } + return release; + }); +} +function proxyFetch(url, opts) { + return (0,node_modules_undici/* fetch */.hd)(url, { + ...opts, + dispatcher: proxyAgent, + }); +} +async function handleBadBinaryPermissions(tool, dir) { + const { name, bin } = tool; + if (process.platform !== 'win32') { + const findBin = async () => { + const files = await external_node_fs_namespaceObject.promises.readdir(dir); + for await (const file of files) { + if (file.toLowerCase() === name.toLowerCase()) { + return file; + } + } + return name; + }; + const binary = external_node_path_.join(dir, bin ? bin : await findBin()); + try { + await external_node_fs_namespaceObject.promises.access(binary, external_node_fs_namespaceObject.constants.X_OK); + } + catch { + await external_node_fs_namespaceObject.promises.chmod(binary, '755'); + core_debug(`Fixed file permissions (-> 0o755) for ${binary}`); + } + } +} +/** + * Checks the tool cache for the tool, and if it is missing + * fetches it from GitHub releases. + * + * @param tool the tool to check or install. + * + * @returns the directory containing the tool binary. + */ +async function checkOrInstallTool(tool) { + const { name, versionSpec } = tool; + // first check if we have previously downloaded the tool + let dir = find(name, versionSpec || '*'); + if (!dir) { + // find the latest release by querying GitHub API + const { version, downloadUrl } = await getRelease(tool); + // download, extract, and cache the tool + const artifact = await downloadTool(downloadUrl); + core_debug(`Successfully downloaded ${name} v${version}`); + let extractDir; + if (downloadUrl.endsWith('.zip')) { + extractDir = await extractZip(artifact); + } + else { + extractDir = await extractTar(artifact); + } + core_debug(`Successfully extracted archive for ${name} v${version}`); + const paths = await globby([ + `${extractDir}/**/nu_plugin_*`, + // For nu v0.61~0.63 on Windows OS + external_node_path_.join(extractDir, '**', 'nu_plugin_*').replace(/\\/g, '/'), + ], { + unique: true, + absolute: true, + }); + const cacheSource = paths.length > 0 ? external_node_path_.dirname(paths[0]) : extractDir; + if (paths.length === 0) { + warning('No nu_plugin_* binaries found; caching extracted directory instead.'); + } + dir = await cacheDir(cacheSource, name, version); + // handle bad binary permissions, the binary needs to be executable! + await handleBadBinaryPermissions(tool, dir); + } + // is there a better way to get the version? + const version = external_node_path_.basename(external_node_path_.dirname(dir)); + return { version, dir, ...tool }; +} -const globby = normalizeArguments(async (patterns, options) => { - // Apply ignore files and get filter (reads .gitignore files once) - const {options: modifiedOptions, filter} = await applyIgnoreFilesAndGetFilter(options); +;// CONCATENATED MODULE: ./src/plugins.ts - // Generate tasks with modified options (includes gitignore patterns in ignore option) - const tasks = await generateTasks(patterns, modifiedOptions); - const results = await Promise.all(tasks.map(task => out(task.patterns, task.options))); - return unionFastGlobResults(results, filter); -}); -const globbySync = normalizeArgumentsSync((patterns, options) => { - // Apply ignore files and get filter (reads .gitignore files once) - const {options: modifiedOptions, filter} = applyIgnoreFilesAndGetFilterSync(options); +/** + * Validates enablePlugins input to prevent command injection. + * Allows: 'true', 'false', or comma-separated plugin names (alphanumeric, underscore only). + */ +function validatePluginInput(input) { + // Allow 'true', 'false', or comma-separated identifiers (word characters only) + if (!/^(true|false|[\w]+(,[\w]+)*)$/i.test(input)) { + throw new Error(`Invalid enable-plugins input: "${input}". Only alphanumeric characters, underscores, and commas are allowed.`); + } +} +/** + * Validates version string to prevent command injection. + * Allows: alphanumeric, dots, hyphens (e.g., "0.95.0", "nightly-56ed69a"). + */ +function validateVersion(version) { + if (!/^[\w.-]+$/.test(version)) { + throw new Error(`Invalid version format: "${version}". Only alphanumeric characters, dots, and hyphens are allowed.`); + } +} +const nu = String.raw; +const pluginRegisterScript = nu ` +#!/usr/bin/env nu - // Generate tasks with modified options (includes gitignore patterns in ignore option) - const tasks = generateTasksSync(patterns, modifiedOptions); +# REF +# 1. https://github.com/actions/runner-images/blob/main/images/win/Windows2022-Readme.md - const results = tasks.map(task => out.sync(task.patterns, task.options)); - return unionFastGlobResults(results, filter); -}); +# Config files are needed to avoid plugin register failure. +# The following lines were used to fix "× Plugin failed to load: No such file or directory (os error 2)" -const globbyStream = normalizeArgumentsSync((patterns, options) => { - // Apply ignore files and get filter (reads .gitignore files once) - const {options: modifiedOptions, filter} = applyIgnoreFilesAndGetFilterSync(options); +def main [ + enablePlugins: string, # Whether to enable or disable plugins. + version: string, # The tag name or version of the release to use. + --debug, # Whether to enable debug mode. + --is-legacy, # Whether to use the legacy plugin registration command for Nu 0.92.3 and below. +] { - // Generate tasks with modified options (includes gitignore patterns in ignore option) - const tasks = generateTasksSync(patterns, modifiedOptions); + let useRegister = if $is_legacy { true } else { false } + let nuDir = $nu.current-exe | path dirname + print $'enablePlugins: ($enablePlugins) of Nu version: ($version)' - const streams = tasks.map(task => out.stream(task.patterns, task.options)); + if $debug { + print 'Output of ($nu.current-exe):'; print $nu.current-exe + print 'Directory contents:'; ls $nuDir | print + } - if (streams.length === 0) { - return external_node_stream_.Readable.from([]); - } + # print $nu + # Create Nu config directory if it does not exist + if not ($nu.default-config-dir | path exists) { mkdir $nu.default-config-dir } + config env --default | save -f $nu.env-path + config nu --default | save -f $nu.config-path + # print (ls $nu.default-config-dir) - const stream = mergeStreams(streams).filter(fastGlobResult => filter(fastGlobResult)); + let allPlugins = ls $nuDir | where name =~ nu_plugin + let filteredPlugins = if $enablePlugins == "'true'" or $enablePlugins == 'true' { + $allPlugins + } else { + $allPlugins | reduce -f [] {|it, acc| + # "split row . | first" used to handle binary with .exe extension + if $enablePlugins =~ ($it.name | path basename | split row . | first) { + $acc | append $it + } else { + $acc + } + } + } - // Returning a web stream will require revisiting once Readable.toWeb integration is viable. - // return Readable.toWeb(stream); + if $debug { + print $'Filtered plugins:'; print $filteredPlugins + } - return stream; -}); + $filteredPlugins | each {|plugin| + let p = $plugin.name | str replace -a \ / + if $useRegister { + echo ([('print "' + $'Registering ($p)' + '"') $'register ($p)'] | str join "\n") + } else { + echo ([('print "' + $'Registering ($p)' + '"') $'plugin add ($p)'] | str join "\n") + } + } + | str join "\n" + | save -rf do-register.nu +} -const isDynamicPattern = normalizeArgumentsSync((patterns, options) => patterns.some(pattern => out.isDynamicPattern(pattern, options))); +`; +async function registerPlugins(enablePlugins, version) { + if (enablePlugins === '' || enablePlugins === 'false') { + return; + } + // Validate inputs to prevent command injection + validatePluginInput(enablePlugins); + validateVersion(version); + const LEGACY_VERSION = '0.92.3'; + const script = 'register-plugins.nu'; + const isLegacyVersion = !version.includes('nightly') && semver_default().lte(version, LEGACY_VERSION); + const execOrThrow = (command) => { + const result = shell_default().exec(command); + if (result.code !== 0) { + throw new Error(`Command failed (${command}): ${result.stderr || result.stdout}`); + } + }; + await external_node_fs_namespaceObject.promises.writeFile(script, pluginRegisterScript); + try { + await external_node_fs_namespaceObject.promises.access(script, external_node_fs_namespaceObject.constants.X_OK); + } + catch { + await external_node_fs_namespaceObject.promises.chmod(script, '755'); + console.log(`Fixed file permissions (-> 0o755) for ${script}`); + } + const registerCommand = isLegacyVersion + ? `nu ${script} "'${enablePlugins}'" ${version} --is-legacy` + : `nu ${script} "'${enablePlugins}'" ${version}`; + execOrThrow(registerCommand); + // console.log('Contents of `do-register.nu`:\n'); + // const content = shell.cat('do-register.nu'); + // console.log(content.toString()); + console.log('\nRegistering plugins...\n'); + execOrThrow('nu do-register.nu'); + console.log(`Plugins registered successfully for Nu ${version}.`); +} -const generateGlobTasks = normalizeArguments(generateTasks); -const generateGlobTasksSync = normalizeArgumentsSync(generateTasksSync); +;// CONCATENATED MODULE: ./src/index.ts +/** + * Author: hustcer + * Created: 2022/04/28 18:50:20 + */ -const {convertPathToPattern} = out; -/***/ }) +async function main() { + try { + const versionSpec = getInput('version'); + console.log(`versionSpec: ${versionSpec}`); + const checkLatest = (getInput('check-latest') || 'false').toUpperCase() === 'TRUE'; + const enablePlugins = (getInput('enable-plugins') || 'false').toLowerCase(); + const rawFeatures = (getInput('features') || 'default').toLowerCase(); + if (rawFeatures !== 'default' && rawFeatures !== 'full') { + throw new Error(`Invalid features input: ${rawFeatures}`); + } + const features = rawFeatures; + const githubToken = getInput('github-token'); + const version = ['*', 'nightly'].includes(versionSpec) ? versionSpec : semver_default().valid(semver_default().coerce(versionSpec)); + console.log(`coerce version: ${version}`); + const ver = version === null ? undefined : version; + if (!ver) { + throw new Error(`Invalid version input: ${versionSpec}`); + } + const tool = await checkOrInstallTool({ + checkLatest, + githubToken, + enablePlugins, + bin: 'nu', + owner: 'nushell', + versionSpec: ver, + features: features, + name: version === 'nightly' ? 'nightly' : 'nushell', + }); + addPath(tool.dir); + // version: * --> 0.95.0; nightly --> nightly-56ed69a; 0.95 --> 0.95.0 + info(`Successfully setup Nu ${tool.version}, with ${features} features.`); + // Change to workspace directory (fallback to current dir for local runs). + const workspaceDir = process.env.GITHUB_WORKSPACE || process.cwd(); + shell_default().cd(workspaceDir); + console.log(`Current directory: ${process.cwd()}`); + await registerPlugins(enablePlugins, tool.version); + } + catch (err) { + setFailed(err instanceof Error ? err.message : String(err)); + } +} +main(); -/******/ }); -/************************************************************************/ -/******/ // The module cache -/******/ var __webpack_module_cache__ = {}; -/******/ -/******/ // The require function -/******/ function __nccwpck_require__(moduleId) { -/******/ // Check if module is in cache -/******/ var cachedModule = __webpack_module_cache__[moduleId]; -/******/ if (cachedModule !== undefined) { -/******/ return cachedModule.exports; -/******/ } -/******/ // Create a new module (and put it into the cache) -/******/ var module = __webpack_module_cache__[moduleId] = { -/******/ id: moduleId, -/******/ loaded: false, -/******/ exports: {} -/******/ }; -/******/ -/******/ // Execute the module function -/******/ var threw = true; -/******/ try { -/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __nccwpck_require__); -/******/ threw = false; -/******/ } finally { -/******/ if(threw) delete __webpack_module_cache__[moduleId]; -/******/ } -/******/ -/******/ // Flag the module as loaded -/******/ module.loaded = true; -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/************************************************************************/ -/******/ /* webpack/runtime/define property getters */ -/******/ (() => { -/******/ // define getter functions for harmony exports -/******/ __nccwpck_require__.d = (exports, definition) => { -/******/ for(var key in definition) { -/******/ if(__nccwpck_require__.o(definition, key) && !__nccwpck_require__.o(exports, key)) { -/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); -/******/ } -/******/ } -/******/ }; -/******/ })(); -/******/ -/******/ /* webpack/runtime/hasOwnProperty shorthand */ -/******/ (() => { -/******/ __nccwpck_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) -/******/ })(); -/******/ -/******/ /* webpack/runtime/make namespace object */ -/******/ (() => { -/******/ // define __esModule on exports -/******/ __nccwpck_require__.r = (exports) => { -/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { -/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); -/******/ } -/******/ Object.defineProperty(exports, '__esModule', { value: true }); -/******/ }; -/******/ })(); -/******/ -/******/ /* webpack/runtime/node module decorator */ -/******/ (() => { -/******/ __nccwpck_require__.nmd = (module) => { -/******/ module.paths = []; -/******/ if (!module.children) module.children = []; -/******/ return module; -/******/ }; -/******/ })(); -/******/ -/******/ /* webpack/runtime/compat */ -/******/ -/******/ if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = __dirname + "/"; -/******/ -/************************************************************************/ -/******/ -/******/ // startup -/******/ // Load entry module and return exports -/******/ // This entry module is referenced by other modules so it can't be inlined -/******/ var __webpack_exports__ = __nccwpck_require__(5074); -/******/ module.exports = __webpack_exports__; -/******/ -/******/ })() -; \ No newline at end of file diff --git a/dist/package.json b/dist/package.json new file mode 100644 index 00000000..3dbc1ca --- /dev/null +++ b/dist/package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +} diff --git a/package.json b/package.json index 657349c..9fa5f97 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "version": "3.22.0", "actionVer": "v3.22", "description": "A Github Action to Setup a Nushell Environment to Run Nu Scripts or Commands", + "type": "module", "main": "dist/index.js", "private": true, "scripts": { diff --git a/src/index.ts b/src/index.ts index 55aa6bd..a6a3268 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,8 +7,8 @@ import shell from 'shelljs'; import semver from 'semver'; import * as core from '@actions/core'; -import * as setup from './setup'; -import { registerPlugins } from './plugins'; +import * as setup from './setup.js'; +import { registerPlugins } from './plugins.js'; async function main() { try { diff --git a/src/setup.ts b/src/setup.ts index f42fb69..086a194 100644 --- a/src/setup.ts +++ b/src/setup.ts @@ -313,9 +313,7 @@ export async function checkOrInstallTool(tool: Tool): Promise { [ `${extractDir}/**/nu_plugin_*`, // For nu v0.61~0.63 on Windows OS - path - .join(extractDir, '**', 'nu_plugin_*') - .replace(/\\/g, '/'), + path.join(extractDir, '**', 'nu_plugin_*').replace(/\\/g, '/'), ], { unique: true, diff --git a/tsconfig.json b/tsconfig.json index a36eb37..8fb0a65 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,8 +2,8 @@ "compilerOptions": { /* Basic Options */ // "incremental": true, /* Enable incremental compilation */ - "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ - "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ + "target": "ES2022", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ + "module": "NodeNext", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ // "lib": [], /* Specify library files to be included in the compilation. */ // "allowJs": true, /* Allow javascript files to be compiled. */ // "checkJs": true, /* Report errors in .js files. */ @@ -39,7 +39,7 @@ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ /* Module Resolution Options */ - "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + "moduleResolution": "NodeNext", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ From 957a0010e4e7ad18eb1b5cb74ef1db68b7d7f095 Mon Sep 17 00:00:00 2001 From: hustcer Date: Fri, 6 Feb 2026 19:38:02 +0800 Subject: [PATCH 3/6] deps: Upgrade @actions/core,@actions/tool-cache,undici,lefthook & semver --- Justfile | 2 ++ dist/{exec-child.js => exec-child.cjs} | 0 dist/index.js | 2 +- package.json | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) rename dist/{exec-child.js => exec-child.cjs} (100%) diff --git a/Justfile b/Justfile index 9003aa1..aa698c9 100644 --- a/Justfile +++ b/Justfile @@ -69,6 +69,8 @@ build: rm -rf dist/*; \ open src/plugins-tpl.ts | str replace __PLUGIN_REGISTER_SCRIPT__ (open nu/register-plugins.nu) | save -rf src/plugins.ts; \ npx ncc build src/index.ts --minify --no-cache; \ + mv dist/exec-child.js dist/exec-child.cjs; \ + open dist/index.js | str replace 'exec-child.js' 'exec-child.cjs' | save -rf dist/index.js; \ $'(ansi g)The `build` task finished!(ansi reset)(char nl)'; # Test action locally diff --git a/dist/exec-child.js b/dist/exec-child.cjs similarity index 100% rename from dist/exec-child.js rename to dist/exec-child.cjs diff --git a/dist/index.js b/dist/index.js index 145b071..079183b 100644 --- a/dist/index.js +++ b/dist/index.js @@ -11593,7 +11593,7 @@ __nccwpck_require__(1642); __nccwpck_require__(473); __nccwpck_require__(2016); __nccwpck_require__(1927); -__nccwpck_require__(2107); // A hint to the bundler to keep exec-child.js +__nccwpck_require__(2107); // A hint to the bundler to keep exec-child.cjs __nccwpck_require__(9638); __nccwpck_require__(573); __nccwpck_require__(1787); diff --git a/package.json b/package.json index 9fa5f97..172bc16 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "scripts": { "fmt": "biome format . --write", "lint": "biome lint **/*.ts", - "build": "rm -rf dist/ && ncc build src/index.ts --minify", + "build": "rm -rf dist/ && ncc build src/index.ts --minify && mv dist/exec-child.js dist/exec-child.cjs && sed -i '' 's/exec-child.js/exec-child.cjs/g' dist/index.js", "run": "pnpm run build && RUNNER_TOOL_CACHE=./runner/cache RUNNER_TEMP=./runner/temp node dist/index.js" }, "repository": { From 6c833df9bcf49afd40bbad87e5f135ecbe191739 Mon Sep 17 00:00:00 2001 From: hustcer Date: Fri, 6 Feb 2026 19:39:08 +0800 Subject: [PATCH 4/6] deps: Upgrade @actions/core,@actions/tool-cache,undici,lefthook & semver --- Justfile | 2 +- dist/index.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Justfile b/Justfile index aa698c9..7c43dfa 100644 --- a/Justfile +++ b/Justfile @@ -70,7 +70,7 @@ build: open src/plugins-tpl.ts | str replace __PLUGIN_REGISTER_SCRIPT__ (open nu/register-plugins.nu) | save -rf src/plugins.ts; \ npx ncc build src/index.ts --minify --no-cache; \ mv dist/exec-child.js dist/exec-child.cjs; \ - open dist/index.js | str replace 'exec-child.js' 'exec-child.cjs' | save -rf dist/index.js; \ + open dist/index.js | str replace --all 'exec-child.js' 'exec-child.cjs' | save -rf dist/index.js; \ $'(ansi g)The `build` task finished!(ansi reset)(char nl)'; # Test action locally diff --git a/dist/index.js b/dist/index.js index 079183b..6cded80 100644 --- a/dist/index.js +++ b/dist/index.js @@ -13640,7 +13640,7 @@ function execSync(cmd, opts, pipe) { writeFileLockedDown(paramsFile, JSON.stringify(paramsToSerialize)); var execArgs = [ - __nccwpck_require__.ab + "exec-child.js", + __nccwpck_require__.ab + "exec-child.cjs", paramsFile, ]; From a7f0a4eb72f0bc7a3be559a8493b77d762fa4be9 Mon Sep 17 00:00:00 2001 From: hustcer Date: Fri, 6 Feb 2026 19:40:15 +0800 Subject: [PATCH 5/6] deps: Upgrade @actions/core,@actions/tool-cache,undici,lefthook & semver --- Justfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Justfile b/Justfile index 7c43dfa..675d164 100644 --- a/Justfile +++ b/Justfile @@ -70,7 +70,7 @@ build: open src/plugins-tpl.ts | str replace __PLUGIN_REGISTER_SCRIPT__ (open nu/register-plugins.nu) | save -rf src/plugins.ts; \ npx ncc build src/index.ts --minify --no-cache; \ mv dist/exec-child.js dist/exec-child.cjs; \ - open dist/index.js | str replace --all 'exec-child.js' 'exec-child.cjs' | save -rf dist/index.js; \ + ^sed -i '' 's/exec-child.js/exec-child.cjs/g' dist/index.js; \ $'(ansi g)The `build` task finished!(ansi reset)(char nl)'; # Test action locally From a12649b03e76b805e106cbd2af02e4f6b7d1a2cc Mon Sep 17 00:00:00 2001 From: hustcer Date: Fri, 6 Feb 2026 19:43:27 +0800 Subject: [PATCH 6/6] fix: Use cross-platform Node.js script for sed replacement Replace macOS-specific `sed -i ''` with a Node.js one-liner that works on both macOS and Linux to fix the exec-child.js -> exec-child.cjs replacement in CI. Co-Authored-By: Claude Opus 4.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 172bc16..901f074 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "scripts": { "fmt": "biome format . --write", "lint": "biome lint **/*.ts", - "build": "rm -rf dist/ && ncc build src/index.ts --minify && mv dist/exec-child.js dist/exec-child.cjs && sed -i '' 's/exec-child.js/exec-child.cjs/g' dist/index.js", + "build": "rm -rf dist/ && ncc build src/index.ts --minify && mv dist/exec-child.js dist/exec-child.cjs && node -e \"const fs=require('fs');const f='dist/index.js';fs.writeFileSync(f,fs.readFileSync(f,'utf8').replace(/exec-child\\.js/g,'exec-child.cjs'))\"", "run": "pnpm run build && RUNNER_TOOL_CACHE=./runner/cache RUNNER_TEMP=./runner/temp node dist/index.js" }, "repository": {